--- /dev/null
+# $NetBSD: Makefile,v 1.1 1996/01/31 23:14:53 mark Exp $
+# @(#)Makefile 7.3 (Berkeley) 6/9/91
+
+# Makefile for arm32 tags file and boot blocks
+
+NOPROG= noprog
+NOMAN= noman
+
+SUBDIR=
+
+TARM32= ../arm32/tags
+SARM32= ../arm32/arm32/*.[ch] ../arm32/include/*.h ../arm32/dev/*.[ch] \
+ ../arm32/podulebus/*.[ch] ../arm32/mainbus/*.[ch]
+AARM32= ../arm32/arm32/*.s
+
+# Directories in which to place arm32 tags links
+DARM32= dev mainbus podulebus include
+
+tags:
+ -ctags -dtf ${TARM32} ${COMM} ${SARM32}
+ egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AARM32} | \
+ sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+ >> ${TARM32}
+ sort -o ${TARM32} ${TARM32}
+
+links:
+ -for i in ${DARM32}; do \
+ cd $$i && rm -f tags; ln -s ../tags tags; done
+
+obj: _SUBDIRUSE
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $NetBSD: ast.c,v 1.2 1996/03/08 18:54:55 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * ast.c
+ *
+ * Code to handle ast's and returns to user mode
+ *
+ * Created : 11/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/acct.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/signal.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/katelib.h>
+#include <machine/psl.h>
+
+int want_resched = 0;
+
+void
+userret(p, pc, oticks)
+ register struct proc *p;
+ int pc;
+ u_quad_t oticks;
+{
+ int sig, s;
+
+ if (p == NULL)
+ panic("userret: p=0 curproc=%08x", curproc);
+
+#ifdef DIAGNOSTIC
+ if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) {
+ traceback();
+ panic("userret called in non SVC mode !");
+ }
+
+ if (current_spl_level != SPL_0)
+ printf("WARNING: (1) current spl level=%d\n", current_spl_level);
+#endif
+
+/* take pending signals */
+
+ while ((sig = (CURSIG(p))) != 0) {
+ postsig(sig);
+ }
+
+ p->p_priority = p->p_usrpri;
+
+/*
+ * Check for reschedule request
+ */
+
+ if (want_resched) {
+ /*
+ * Since we are curproc, a clock interrupt could
+ * change our priority without changing run queues
+ * (the running process is not kept on a run queue).
+ * If this happened after we setrunqueue ourselves but
+ * before we switch()'ed, we might not be on the queue
+ * indicated by our priority
+ */
+
+ s = splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nivcsw++;
+
+ mi_switch();
+
+ (void)splx(s);
+ while ((sig = (CURSIG(p))) != 0) {
+ postsig(sig);
+ }
+ }
+
+/*
+ * Not sure if this profiling bit is working yet ... Not been tested
+ */
+
+ if (p->p_flag & P_PROFIL) {
+ extern int psratio;
+ addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio);
+ }
+
+ curpriority = p->p_priority;
+
+#ifdef DIAGNOSTIC
+ if (current_spl_level != SPL_0)
+ printf("WARNING: (2) current spl level=%d\n", current_spl_level);
+#endif
+}
+
+
+/*
+ * void ast(trapframe_t *frame)
+ *
+ * Handle asynchronous system traps.
+ * This is called from the irq handler to deliver signals
+ * and switch processes if required.
+ * userret() does all the signal delivery and process switching work
+ */
+
+void
+ast(frame)
+ trapframe_t *frame;
+{
+ register struct proc *p;
+
+ cnt.v_trap++;
+
+ if ((p = curproc) == 0)
+ p = &proc0;
+ if (&p->p_addr->u_pcb == 0)
+ panic("ast: nopcb!");
+
+ cnt.v_soft++;
+ if (p->p_flag & P_OWEUPC) {
+ p->p_flag &= ~P_OWEUPC;
+ ADDUPROF(p);
+ }
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 3);
+#endif
+
+ userret(p, frame->tf_pc, p->p_sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 3);
+#endif
+}
+
+/* End of ast.c */
--- /dev/null
+/* $NetBSD: autoconf.c,v 1.2 1996/03/06 23:11:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * autoconf.c
+ *
+ * Autoconfiguration functions
+ *
+ * Created : 08/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/disklabel.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/irqhandler.h>
+#include <machine/bootconfig.h>
+
+#include "wdc.h"
+#include "fdc.h"
+#include "rd.h"
+#include "sd.h"
+#include "cd.h"
+#include "wcd.h"
+
+extern dev_t rootdev;
+extern dev_t swapdev;
+extern dev_t dumpdev;
+extern dev_t argdev;
+
+extern struct swdevt swdevt[];
+
+extern char *boot_args;
+extern int pmap_debug_level;
+
+char * strstr __P((char */*s1*/, char */*s2*/));
+long strtoul __P((const char *, char **, int));
+
+/* Table major numbers for the device names, NULL terminated */
+
+struct {
+ char *name;
+ dev_t dev;
+} rootdevices[] = {
+#if NWDC > 0
+ { "wd", 0x10 },
+#endif
+#if NFDC > 0
+ { "fd", 0x11 },
+#endif
+#if NRD > 0
+ { "rd", 0x12 },
+#endif
+#if NSD > 0
+ { "sd", 0x18 },
+#endif
+#if NCD > 0
+ { "cd", 0x1a },
+#endif
+#if NWCD > 0
+ { "wcd", 0x14 },
+#endif
+ { NULL, 0x00 },
+};
+
+/* Decode a device name to a major and minor number */
+
+dev_t
+get_device(name)
+ char *name;
+{
+ int loop;
+ int unit;
+ int part;
+
+ if (strncmp(name, "/dev/", 5) == 0)
+ name += 5;
+
+ for (loop = 0; rootdevices[loop].name; ++loop) {
+ if (strncmp(name, rootdevices[loop].name,
+ strlen(rootdevices[loop].name)) == 0) {
+ name += strlen(rootdevices[loop].name);
+ unit = name[0] - '0';
+ part = name[1] - 'a';
+ if (unit < 0 || unit > 9)
+ return(NODEV);
+ if (part < 0 || part > MAXPARTITIONS)
+ return(NODEV);
+ return(makedev(rootdevices[loop].dev,
+ unit * MAXPARTITIONS + part));
+ }
+ }
+ return(NODEV);
+}
+
+
+/* Set the rootdev variable from the root specifier in the boot args */
+
+void
+set_root_device()
+{
+ char *ptr;
+
+ if (boot_args) {
+ ptr = strstr(boot_args, "root=");
+ if (ptr) {
+ ptr += 5;
+ rootdev = get_device(ptr);
+
+ if (pmap_debug_level >= 0)
+ printf("rootdev = %08x\n", rootdev);
+ }
+ }
+
+ if (rootdev == NODEV)
+ panic("No root device specified in boot config\n");
+}
+
+
+/* Set the swap devices from the swap specifiers in the boot ars */
+
+void
+set_swap_device()
+{
+ char *ptr;
+ int nswap = 0;
+
+ if (boot_args) {
+ ptr = boot_args;
+ do {
+ ptr = strstr(ptr, "swap=");
+ if (ptr) {
+ ptr += 5;
+ swdevt[nswap].sw_dev = get_device(ptr);
+
+ /*
+ * Remember the first swap device
+ */
+
+ if (nswap == 0)
+ swapdev = get_device(ptr);
+ ++nswap;
+ }
+ } while (ptr);
+ }
+}
+
+
+/*
+ * Configure swap space and related parameters.
+ */
+
+void
+swapconf()
+{
+ register struct swdevt *swp;
+ register int nblks;
+ int swapsize = -1;
+ char *ptr;
+ int maj;
+ int s; /* The spl stuff was here for debugging reaons */
+
+ /*
+ * Loop round all the defined swap device configuring them.
+ */
+
+ for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
+ maj = major(swp->sw_dev);
+ if (maj > nblkdev)
+ break;
+ if (bdevsw[maj].d_psize) {
+ s = spltty();
+ printf("swap dev %04x ", swp->sw_dev);
+ (void)splx(s);
+ if (swapsize == -1)
+ nblks = (*bdevsw[maj].d_psize)(swp->sw_dev);
+ else
+ nblks = swapsize;
+ s = spltty();
+ if (nblks == -1)
+ printf("-> device not configured for swap\n");
+ else
+ printf("-> %d bytes\n", nblks*DEV_BSIZE);
+ (void)splx(s);
+ if (nblks != -1 &&
+ (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
+ swp->sw_nblks = nblks;
+ swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
+ }
+ }
+}
+
+
+/* Set up the root and swap device numbers, configure the swap space and dump space */
+
+void
+set_boot_devs()
+{
+ set_root_device();
+ set_swap_device();
+
+ if (swapdev == NODEV && minor(rootdev) < (MAXPARTITIONS - 2))
+ swapdev = makedev(major(rootdev), minor(rootdev) + 1);
+
+ dumpdev = swapdev;
+ argdev = swapdev;
+ swdevt[0].sw_dev = swapdev;
+
+ swapconf();
+ dumpconf();
+}
+
+
+/*
+ * void configure()
+ *
+ * Configure all the root devices
+ * The root devices are expected to configure their own children
+ */
+
+void
+configure()
+{
+
+/*
+ * Loop round all the root devices configuring them. Configure failure
+ * is not expected for the root devices
+ */
+
+ config_rootfound("mainbus", NULL);
+ config_rootfound("podulebus", NULL);
+
+/* Debugging information */
+
+ printf("ipl_bio=%08x ipl_net=%08x ipl_tty=%08x ipl_clock=%08x ipl_imp=%08x\n",
+ irqmasks[IPL_BIO], irqmasks[IPL_NET], irqmasks[IPL_TTY],
+ irqmasks[IPL_CLOCK], irqmasks[IPL_IMP]);
+
+/* Time to start taking interrupts so lets open the flood gates .... */
+
+ (void)spl0();
+}
+
+/* End of autoconf.c */
--- /dev/null
+/* $NetBSD: bcopy.S,v 1.1 1996/01/31 23:15:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * memset.S
+ *
+ * optimized memset function
+ *
+ * Created : 16/05/95
+ * Last updated : 16/05/95
+ *
+ * $Id: bcopy.S,v 1.1.1.1 1996/04/24 11:08:23 deraadt Exp $
+ */
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+ .global _bcopy
+ .global _ovbcopy
+
+_bcopy:
+_ovbcopy:
+ teq r2, #0x00000000
+ moveq r0, #0x00000000
+ moveq pc, lr
+ cmp r0, r1
+ blt bcopy_back
+
+bcopy_loop:
+ ldrb r3, [r0], #0x0001
+ strb r3, [r1], #0x0001
+ subs r2, r2, #0x00000001
+ bne bcopy_loop
+
+ mov pc, r14
+
+bcopy_back:
+ add r0, r0, r2
+ add r1, r1, r2
+
+bcopy_bloop:
+ ldrb r3, [r0, #-0x0001]!
+ strb r3, [r1, #-0x0001]!
+ subs r2, r2, #0x00000001
+ bne bcopy_bloop
+
+ mov pc, r14
+
+
+ .global _memcpy
+
+_memcpy:
+ teq r2, #0x00000000
+ moveq r0, #0x00000000
+ moveq pc, lr
+ cmp r1, r0
+ blt memcpy_back
+
+memcpy_loop:
+ ldrb r3, [r1], #0x0001
+ strb r3, [r0], #0x0001
+ subs r2, r2, #0x00000001
+ bne memcpy_loop
+
+ mov pc, r14
+
+memcpy_back:
+ add r0, r0, r2
+ add r1, r1, r2
+
+memcpy_bloop:
+ ldrb r3, [r1, #-0x0001]!
+ strb r3, [r0, #-0x0001]!
+ subs r2, r2, #0x00000001
+ bne memcpy_bloop
+
+ mov pc, r14
--- /dev/null
+/* $NetBSD: bcopy_page.S,v 1.1 1996/01/31 23:15:17 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Scott Stevens.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * bcopy_page.S
+ *
+ * page optimised bcopy and bzero routines
+ *
+ * Created : 08/04/95
+ * Last updated : 12/05/95
+ *
+ * $Id: bcopy_page.S,v 1.1.1.1 1996/04/24 11:08:23 deraadt Exp $
+ */
+
+#include <machine/param.h>
+
+/* TODO:
+ *
+ * Use r2 as the counter so that r3-r10 can be used instead of r4-r11
+ * This means r11 will not need to be pushed on the stack.
+ */
+
+/* bcopy_page(src, dest)
+ * r0 - src
+ * r1 - dest
+ * number of bytes (NBPG) is a multiple of 512
+ */
+
+ .global _bcopy_page
+_bcopy_page:
+ mov r3, #(NBPG >> 9)
+
+ STMFD r13!, {r4-r11, r14}
+
+loopcopy:
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+ ldmia r0!, {r4-r11}
+ stmia r1!, {r4-r11}
+
+ subs r3, r3, #1
+ bgt loopcopy
+
+ ldmfd r13!, {r4-r11, r15}
+
+/* bzero_page(dest)
+ * r0 - dest
+ * number of bytes is a multiple of 512
+ */
+
+ .global _bzero_page
+_bzero_page:
+ mov r3, #(NBPG >> 9)
+
+ stmfd r13!, {r4-r11, r14}
+
+ mov r4, #0
+ mov r5, #0
+ mov r6, #0
+ mov r7, #0
+ mov r8, #0
+ mov r9, #0
+ mov r10, #0
+ mov r11, #0
+
+loopzero:
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+ stmia r0!, {r4-r11}
+
+ subs r3, r3, #1
+ bgt loopzero
+
+ ldmfd r13!, {r4-r11, r15}
--- /dev/null
+/* $NetBSD: bcopyinout.S,v 1.3 1996/02/02 18:05:47 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * bcopyinout.S
+ *
+ * optimized and fault protected copyinout function
+ *
+ * Created : 16/05/95
+ * Last updated : 16/05/95
+ *
+ * $Id: bcopyinout.S,v 1.1.1.1 1996/04/24 11:08:24 deraadt Exp $
+ */
+
+#include "assym.h"
+#include <sys/errno.h>
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+Lcurpcb:
+ .word _curpcb
+
+Lcurproc:
+ .word _curproc
+
+bcopyinoutfault:
+ mov r0, #0x00000000
+ str r0, [r4, #PCB_ONFAULT]
+ mov r0, #EFAULT
+ ldmfd sp!, {r4}
+ mov pc, lr
+
+bcopyinoutpcbfault:
+ stmfd sp!, {lr}
+ mov r3, r1
+ mov r1, r4
+ add r0, pc, #bcopyinouttext - . - 8
+ mov r2, r3
+ ldr r3, Lcurproc
+ ldr r3, [r3]
+ bl _printf
+ mov r0, #EFAULT
+ ldmfd sp!, {lr}
+ ldmfd sp!, {r4}
+ mov pc, lr
+
+bcopyinouttext:
+ .asciz "Alert ! PCB = %08x during bcopyinout addr=%08x curproc=%08x\n"
+
+ .align 0
+
+ .global _bcopyinout
+
+_bcopyinout:
+ teq r2, #0x00000000
+ moveq r0, #0x000000000
+ moveq pc,lr
+
+ stmfd sp!, {r4}
+ ldr r4, Lcurpcb
+ ldr r4, [r4]
+ teq r4, #0x00000000
+ beq bcopyinoutpcbfault
+ add r3, pc, #bcopyinoutfault - . - 8
+ str r3, [r4, #PCB_ONFAULT]
+
+ cmp r0, r1
+ blt bcopy_back
+
+bcopy_loop:
+ ldrb r3, [r0], #0x0001
+ strb r3, [r1], #0x0001
+ subs r2, r2, #0x00000001
+ bne bcopy_loop
+
+ mov r0, #0x00000000
+ str r0, [r4, #PCB_ONFAULT]
+ ldmfd sp!, {r4}
+ mov pc, lr
+
+bcopy_back:
+ add r0, r0, r2
+ add r1, r1, r2
+
+bcopy_bloop:
+ ldrb r3, [r0, #-0x0001]!
+ strb r3, [r1, #-0x0001]!
+ subs r2, r2, #0x00000001
+ bne bcopy_bloop
+
+ mov r0, #0x00000000
+ str r0, [r4, #PCB_ONFAULT]
+ ldmfd sp!, {r4}
+ mov pc, r14
+
--- /dev/null
+/* $NetBSD: blockio.S,v 1.1 1996/01/31 23:15:22 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * blockio.S
+ *
+ * optimised block read/write from/to IO routines.
+ *
+ * Created : 08/10/94
+ * Last updated : 12/05/95
+ *
+ * $Id: blockio.S,v 1.1.1.1 1996/04/24 11:08:24 deraadt Exp $
+ */
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+
+ .global _insw
+/*
+ * Reads short ints (16 bits) from an I/O address into a block of memory
+ *
+ * r0 = address to read from (IO)
+ * r1 = address to write to (memory)
+ * r2 = length
+ */
+
+_insw:
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+/* If the destination address and the size is word aligned, do it fast */
+
+ tst r2, #0x00000001
+ tsteq r1, #0x00000003
+ beq fastinsw
+
+/* Non aligned insw */
+
+inswloop:
+ ldr r3, [r0]
+ strb r3, [r1], #0x0001
+ mov r3, r3, lsr #8
+ strb r3, [r1], #0x0001
+ subs r2, r2, #0x00000001
+ bgt inswloop
+
+ mov pc, lr
+
+/* Word aligned insw */
+
+fastinsw:
+ stmfd r13!, {r4}
+
+fastinswloop:
+ ldr r3, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr r4, [r0]
+ mov r3, r3, lsr #16 /* Put the two shorts together */
+ orr r3, r3, r4, lsl #16
+ str r3, [r1], #0x0004 /* Store */
+ subs r2, r2, #0x00000002 /* Next */
+ bgt fastinswloop
+
+ ldmfd r13!, {r4}
+
+ mov pc, lr
+
+
+ .global _outsw
+
+/*
+ * Writes short ints (16 bits) from a block of memory to an I/O address
+ *
+ * r0 = address to write to (IO)
+ * r1 = address to read from (memory)
+ * r2 = length
+ */
+
+_outsw:
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+#ifdef notyet
+
+/*
+ * The optimised routines have not been tested yet and I don't feel
+ * like testing the new write code on 2.8 Gig of valuable data.
+ * Need to wait until I hang another HD on my machine
+ */
+
+/* If the destination address and the size is word aligned, do it fast */
+
+ tst r2, #0x00000001
+ tsteq r1, #0x00000003
+ beq fastoutsw
+#endif
+
+/* Non aligned outsw */
+
+ stmfd sp!, {r4}
+
+outswloop:
+ ldrb r3, [r1], #0x0001
+ ldrb r4, [r1], #0x0001
+ orr r3, r3, r4, lsl #8
+ orr r3, r3, r3, lsl #16
+ str r3, [r0]
+ subs r2, r2, #0x00000001
+ bgt outswloop
+
+ ldmfd sp!, {r4}
+
+ mov pc, lr
+
+#ifdef notyet
+/* Word aligned outsw */
+
+fastoutsw:
+ stmfd r13!, {r4}
+
+fastoutswloop:
+ ldr r3, [r1], #0x0004
+
+ mov r4, r3, lsl #16
+ orr r4, r4, lsr #16
+ str r4, [r0]
+
+ mov r4, r3, lsr #16
+ orr r4, r4, lsl #16
+ str r4, [r0]
+
+ subs r2, r2, #0x00000002
+ bgt outswloop
+
+ ldmfd sp!, {r4}
+
+ mov pc, lr
+#endif
+
+ .global _insw16
+/*
+ * reads short ints (16 bits) from an I/O address into a block of memory
+ * with a length garenteed to be a multiple of 16 bytes
+ * with a word aligned destination address
+ *
+ * r0 = address to read from (IO)
+ * r1 = address to write to (memory)
+ * r2 = length
+ */
+
+_insw16:
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+/* If the destination address and the size is word aligned, do it fast */
+
+ tst r2, #0x0000000f
+ tsteq r1, #0x00000003
+
+ bne _insw
+
+/* Word aligned insw */
+
+ stmfd r13!, {r4-r7}
+
+insw16loop:
+ ldr r3, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr r7, [r0]
+ mov r3, r3, lsr #16 /* Put the two shorts together */
+ orr r3, r3, r7, lsl #16
+
+ ldr r4, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr r7, [r0]
+ mov r4, r4, lsr #16 /* Put the two shorts together */
+ orr r4, r4, r7, lsl #16
+
+ ldr r5, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr r7, [r0]
+ mov r5, r5, lsr #16 /* Put the two shorts together */
+ orr r5, r5, r7, lsl #16
+
+ ldr r6, [r0, #0x0002] /* take advantage of nonaligned
+ * word accesses */
+ ldr r7, [r0]
+ mov r6, r6, lsr #16 /* Put the two shorts together */
+ orr r6, r6, r7, lsl #16
+
+ stmia r1!, {r3-r6}
+ subs r2, r2, #0x00000008 /* Next */
+ bgt insw16loop
+
+ ldmfd r13!, {r4-r7}
+
+ mov pc, lr
+
+
+#ifdef notyet
+/*
+ * The optimised routines have not been tested yet and I don't feel
+ * like testing the new write code on 2.8 Gig of valuable data.
+ * Need to wait until I hang another HD on my machine
+ */
+ .global _outsw16
+/*
+ * Writes short ints (16 bits) from a block of memory to an I/O address
+ *
+ * r0 = address to write to (IO)
+ * r1 = address to read from (memory)
+ * r2 = length
+ */
+
+_outsw16:
+/* Make sure that we have a positive length */
+ cmp r2, #0x00000000
+ movle pc, lr
+
+/* If the destination address and the size is word aligned, do it fast */
+
+ tst r2, #0x0000000f
+ tsteq r1, #0x00000003
+
+ bne _outsw
+
+/* Word aligned outsw */
+
+ stmfd r13!, {r4-r8}
+
+outsw16loop:
+ ldmia r1!, {r4-r8}
+
+ mov r3, r4, lsl #16
+ orr r3, r3, lsr #16
+ str r3, [r0]
+
+ mov r3, r4, lsr #16
+ orr r3, r4, lsl #16
+ str r3, [r0]
+
+ mov r3, r5, lsl #16
+ orr r3, r3, lsr #16
+ str r3, [r0]
+
+ mov r3, r5, lsr #16
+ orr r3, r4, lsl #16
+ str r3, [r0]
+
+ mov r3, r6, lsl #16
+ orr r3, r3, lsr #16
+ str r3, [r0]
+
+ mov r3, r6, lsr #16
+ orr r3, r4, lsl #16
+ str r3, [r0]
+
+ mov r3, r7, lsl #16
+ orr r3, r3, lsr #16
+ str r3, [r0]
+
+ mov r3, r7, lsr #16
+ orr r3, r4, lsl #16
+ str r3, [r0]
+
+ subs r2, r2, #0x00000008
+ bgt outsw16loop
+
+ ldmfd sp!, {r4-r8}
+
+ mov pc, lr
+#endif
--- /dev/null
+/* $NetBSD: clock.c,v 1.4 1996/04/19 19:39:17 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * clock.c
+ *
+ * Timer related machine specific code
+ *
+ * Created : 29/09/94
+ */
+
+/* Include header files */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+
+#include <machine/katelib.h>
+#include <machine/iomd.h>
+#include <machine/irqhandler.h>
+#include <machine/cpu.h>
+#include <machine/rtc.h>
+
+#define TIMER0_COUNT 20000 /* 100Hz */
+#define TIMER_FREQUENCY 20000000 /* 2MHz clock */
+#define TICKS_PER_MICROSECOND (TIMER_FREQUENCY / 10000000)
+
+static irqhandler_t clockirq;
+static irqhandler_t statclockirq;
+
+
+/*
+ * int clockhandler(struct clockframe *frame)
+ *
+ * Function called by timer 0 interrupts. This just calls
+ * hardclock(). Eventually the irqhandler can call hardclock() directly
+ * but for now we use this function so that we can debug IRQ's
+ */
+
+int
+clockhandler(frame)
+ struct clockframe *frame;
+{
+ hardclock(frame);
+ return(1);
+}
+
+
+/*
+ * int statclockhandler(struct clockframe *frame)
+ *
+ * Function called by timer 1 interrupts. This just calls
+ * statclock(). Eventually the irqhandler can call statclock() directly
+ * but for now we use this function so that we can debug IRQ's
+ */
+
+int
+statclockhandler(frame)
+ struct clockframe *frame;
+{
+ statclock(frame);
+ return(1);
+}
+
+
+/*
+ * void setstatclockrate(int hz)
+ *
+ * Set the stat clock rate. The stat clock uses timer1
+ */
+
+void
+setstatclockrate(hz)
+ int hz;
+{
+ int count;
+
+ count = TIMER_FREQUENCY / hz;
+
+ printf("Setting statclock to %dHz (%d ticks)\n", hz, count);
+
+ WriteByte(IOMD_T1LOW, (count >> 0) & 0xff);
+ WriteByte(IOMD_T1HIGH, (count >> 8) & 0xff);
+
+/* reload the counter */
+
+ WriteByte(IOMD_T1GO, 0);
+}
+
+
+/*
+ * void cpu_initclocks(void)
+ *
+ * Initialise the clocks.
+ * This sets up the two timers in the IOMD and installs the IRQ handlers
+ *
+ * NOTE: Currently only timer 0 is setup and the IRQ handler is not installed
+ */
+
+void
+cpu_initclocks()
+{
+/*
+ * Load timer 0 with count down value
+ * This timer generates 100Hz interrupts for the system clock
+ */
+
+ printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz);
+
+ WriteByte(IOMD_T0LOW, (TIMER0_COUNT >> 0) & 0xff);
+ WriteByte(IOMD_T0HIGH, (TIMER0_COUNT >> 8) & 0xff);
+
+/* reload the counter */
+
+ WriteByte(IOMD_T0GO, 0);
+
+ clockirq.ih_func = clockhandler;
+ clockirq.ih_arg = 0;
+ clockirq.ih_level = IPL_CLOCK;
+ clockirq.ih_name = "TMR0 hard clk";
+ if (irq_claim(IRQ_TIMER0, &clockirq) == -1)
+ panic("Cannot installer timer 0 IRQ handler\n");
+
+ if (stathz) {
+ setstatclockrate(stathz);
+
+ statclockirq.ih_func = statclockhandler;
+ statclockirq.ih_arg = 0;
+ statclockirq.ih_level = IPL_CLOCK;
+ if (irq_claim(IRQ_TIMER1, &clockirq) == -1)
+ panic("Cannot installer timer 1 IRQ handler\n");
+ }
+}
+
+
+/*
+ * void microtime(struct timeval *tvp)
+ *
+ * Fill in the specified timeval struct with the current time
+ * accurate to the microsecond.
+ */
+
+void
+microtime(tvp)
+ struct timeval *tvp;
+{
+ int s;
+ int tm;
+ int deltatm;
+ static int oldtm;
+ static struct timeval oldtv;
+
+ s = splhigh();
+
+/*
+ * Latch the current value of the timer and then read it. This garentees
+ * an atmoic reading of the time.
+ */
+
+ WriteByte(IOMD_T0LATCH, 0);
+ tm = ReadByte(IOMD_T0LOW) + (ReadByte(IOMD_T0HIGH) << 8);
+ deltatm = tm - oldtm;
+ if (deltatm < 0) deltatm += TIMER0_COUNT;
+ if (deltatm < 0) {
+ printf("opps deltatm < 0 tm=%d oldtm=%d deltatm=%d\n",
+ tm, oldtm, deltatm);
+ }
+ oldtm = tm;
+
+/* Fill in the timeval struct */
+
+ *tvp = time;
+ tvp->tv_usec += (deltatm / TICKS_PER_MICROSECOND);
+
+/* Make sure the micro seconds don't overflow. */
+
+ while (tvp->tv_usec > 1000000) {
+ tvp->tv_usec -= 1000000;
+ ++tvp->tv_sec;
+ }
+
+/* Make sure the time has advanced. */
+
+ if (tvp->tv_sec == oldtv.tv_sec &&
+ tvp->tv_usec <= oldtv.tv_usec) {
+ tvp->tv_usec = oldtv.tv_usec + 1;
+ if (tvp->tv_usec > 1000000) {
+ tvp->tv_usec -= 1000000;
+ ++tvp->tv_sec;
+ }
+ }
+
+
+ oldtv = *tvp;
+ (void)splx(s);
+}
+
+
+void
+need_proftick(p)
+ struct proc *p;
+{
+}
+
+
+static inline int
+yeartoday(year)
+ int year;
+{
+ return((year % 4) ? 365 : 366);
+}
+
+
+static int month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static int timeset = 0;
+
+#define SECPERDAY (24*60*60)
+#define SECPERNYEAR (365*SECPERDAY)
+#define SECPER4YEARS (4*SECPERNYEAR+SECPERDAY)
+#define EPOCHYEAR 1970
+
+/*
+ * Write back the time of day to the rtc
+ */
+
+void
+resettodr()
+{
+ int s;
+ time_t year, mon, day, hour, min, sec;
+ rtc_t rtc;
+
+ if (!timeset)
+ return;
+
+ sec = time.tv_sec;
+ year = (sec / SECPER4YEARS) * 4;
+ sec %= SECPER4YEARS;
+
+ /* year now hold the number of years rounded down 4 */
+
+ while (sec > (yeartoday(EPOCHYEAR+year) * SECPERDAY)) {
+ sec -= yeartoday(EPOCHYEAR+year)*SECPERDAY;
+ year++;
+ }
+
+ /* year is now a correct offset from the EPOCHYEAR */
+
+ year+=EPOCHYEAR;
+ mon=0;
+ if (yeartoday(year) == 366)
+ month[1]=29;
+ else
+ month[1]=28;
+ while ((sec/SECPERDAY) > month[mon]) {
+ sec -= month[mon]*SECPERDAY;
+ mon++;
+ }
+
+ day = sec / SECPERDAY;
+ sec %= SECPERDAY;
+ hour = sec / 3600;
+ sec %= 3600;
+ min = sec / 60;
+ sec %= 60;
+ rtc.rtc_cen = year / 100;
+ rtc.rtc_year = year % 100;
+ rtc.rtc_mon = mon+1;
+ rtc.rtc_day = day+1;
+ rtc.rtc_hour = hour;
+ rtc.rtc_min = min;
+ rtc.rtc_sec = sec;
+ rtc.rtc_centi =
+ rtc.rtc_micro = 0;
+
+/*
+ printf("resettod: %d/%d/%d%d %d:%d:%d\n", rtc.rtc_day,
+ rtc.rtc_mon, rtc.rtc_cen, rtc.rtc_year, rtc.rtc_hour,
+ rtc.rtc_min, rtc.rtc_sec);
+*/
+
+ s = splclock();
+ rtc_write(&rtc);
+ (void)splx(s);
+}
+
+/*
+ * Initialise the time of day register, based on the time base which is, e.g.
+ * from a filesystem.
+ */
+
+void
+inittodr(base)
+ time_t base;
+{
+ time_t n;
+ int i, days = 0;
+ int s;
+ int year;
+ rtc_t rtc;
+
+/*
+ * We ignore the suggested time for now and go for the RTC
+ * clock time stored in the CMOS RAM.
+ */
+
+ s = splclock();
+ if (rtc_read(&rtc) == 0) {
+ (void)splx(s);
+ return;
+ }
+
+ (void)splx(s);
+
+ n = rtc.rtc_sec + 60 * rtc.rtc_min + 3600 * rtc.rtc_hour;
+ n += (rtc.rtc_day - 1) * 3600 * 24;
+ year = (rtc.rtc_year + rtc.rtc_cen * 100) - 1900;
+
+ if (yeartoday(year) == 366)
+ month[1] = 29;
+ for (i = rtc.rtc_mon - 2; i >= 0; i--)
+ days += month[i];
+ month[1] = 28;
+
+ for (i = 70; i < year; i++)
+ days += yeartoday(i);
+
+ n += days * 3600 * 24;
+
+ n += tz.tz_minuteswest * 60;
+ if (tz.tz_dsttime)
+ n -= 3600;
+
+ time.tv_sec = n;
+ time.tv_usec = 0;
+
+/* timeset is used to ensure the time is valid before a resettodr() */
+
+ timeset = 1;
+
+/* If the base was 0 then keep quiet */
+
+ if (base) {
+ printf("inittodr: %02d:%02d:%02d.%02d%02d %02d/%02d/%02d%02d\n",
+ rtc.rtc_hour, rtc.rtc_min, rtc.rtc_sec, rtc.rtc_centi,
+ rtc.rtc_micro, rtc.rtc_day, rtc.rtc_mon, rtc.rtc_cen,
+ rtc.rtc_year);
+
+ if (n > base + 60) {
+ days = (n - base) / SECPERDAY;
+ printf("Clock has gained %d day%c %ld hours %ld minutes %ld secs\n",
+ days, ((days == 1) ? 0 : 's'), ((n - base) / 3600) % 24,
+ ((n - base) / 60) % 60, (n - base) % 60);
+ }
+ }
+}
+
+/* End of clock.c */
--- /dev/null
+/* $NetBSD: conf.c,v 1.6 1996/04/19 19:40:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * conf.c
+ *
+ * Character and Block Device configuration
+ * Console configuration
+ *
+ * Defines the structures cdevsw and constab
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+#include <sys/vnode.h>
+
+int ttselect __P((dev_t, int, struct proc *));
+
+#ifndef LKM
+#define lkmenodev enodev
+#else
+int lkmenodev();
+#endif
+
+#include "wdc.h"
+bdev_decl(wd);
+bdev_decl(sw);
+#include "fdc.h"
+bdev_decl(fd);
+#include "rd.h"
+bdev_decl(rd);
+#include "sd.h"
+bdev_decl(sd);
+#include "st.h"
+bdev_decl(st);
+#include "cd.h"
+bdev_decl(cd);
+#include "vnd.h"
+bdev_decl(vnd);
+#include "ccd.h"
+bdev_decl(ccd);
+/* Temporary hack for ATAPI CDROM */
+#include "wcd.h"
+bdev_decl(wcd);
+
+/* Block devices */
+
+struct bdevsw bdevsw[] = {
+ bdev_lkm_dummy(), /* 0: */
+ bdev_swap_init(1, sw), /* 1: swap pseudo-device */
+ bdev_lkm_dummy(), /* 2: */
+ bdev_lkm_dummy(), /* 3: */
+ bdev_lkm_dummy(), /* 4: */
+ bdev_lkm_dummy(), /* 5: */
+ bdev_lkm_dummy(), /* 6: */
+ bdev_lkm_dummy(), /* 7: */
+ bdev_lkm_dummy(), /* 8: */
+ bdev_lkm_dummy(), /* 9: */
+ bdev_lkm_dummy(), /* 10: */
+ bdev_lkm_dummy(), /* 11: */
+ bdev_lkm_dummy(), /* 12: */
+ bdev_lkm_dummy(), /* 13: */
+ bdev_lkm_dummy(), /* 14: */
+ bdev_lkm_dummy(), /* 15: */
+ bdev_disk_init(NWDC, wd), /* 16: Internal IDE disk */
+ bdev_disk_init(NFDC, fd), /* 17: floppy diskette */
+ bdev_disk_init(NRD, rd), /* 18: ramdisk */
+ bdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
+ bdev_disk_init(NWCD, wcd), /* 20: */
+ bdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */
+ bdev_lkm_dummy(), /* 22: */
+ bdev_lkm_dummy(), /* 23: */
+ bdev_disk_init(NSD,sd), /* 24: SCSI disk */
+ bdev_tape_init(NST,st), /* 25: SCSI tape */
+ bdev_disk_init(NCD,cd), /* 26: SCSI cdrom */
+ bdev_lkm_dummy(), /* 27: */
+ bdev_lkm_dummy(), /* 28: */
+ bdev_lkm_dummy(), /* 29: */
+ bdev_lkm_dummy(), /* 30: */
+ bdev_lkm_dummy(), /* 31: */
+ bdev_lkm_dummy(), /* 32: */
+ bdev_lkm_dummy(), /* 33: */
+ bdev_lkm_dummy(), /* 34: */
+ bdev_lkm_dummy(), /* 35: */
+ bdev_lkm_dummy(), /* 36: */
+ bdev_lkm_dummy(), /* 37: */
+ bdev_lkm_dummy(), /* 38: */
+ bdev_lkm_dummy(), /* 39: */
+ bdev_lkm_dummy(), /* 40: */
+ bdev_lkm_dummy(), /* 41: */
+ bdev_lkm_dummy(), /* 42: */
+ bdev_lkm_dummy(), /* 43: */
+ };
+
+int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
+
+
+/* Character device declarations */
+
+/* open, close, read, write, ioctl, tty, mmap */
+#define cdev_physcon_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \
+ dev_init(c,n,tty), ttselect, dev_init(c,n,mmap), 0 }
+
+/* open, close, write, ioctl */
+#define cdev_lpt_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+ 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, write, ioctl */
+#define cdev_beep_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, write, ioctl */
+#define cdev_kbd_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, write, ioctl */
+#define cdev_cpu_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, write, ioctl */
+#define cdev_vidcvid_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ 0, seltrue, dev_init(c,n,mmap), 0 }
+
+/* open, close, write, ioctl */
+#define cdev_uk_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ dev_init(c,n,write), dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, read, ioctl */
+#define cdev_ss_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, seltrue, \
+ (dev_type_mmap((*))) enodev }
+
+/* open, close, write, ioctl */
+#define cdev_iic_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+ 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, write, ioctl */
+#define cdev_rtc_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+ 0, seltrue, (dev_type_mmap((*))) enodev, 0 }
+
+cdev_decl(cn);
+cdev_decl(ctty);
+#include "vt.h"
+cdev_decl(physcon);
+cdev_decl(vidcvideo);
+#define mmread mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
+cdev_decl(wd);
+cdev_decl(sw);
+#include "pty.h"
+#define ptstty ptytty
+#define ptsioctl ptyioctl
+cdev_decl(pts);
+#define ptctty ptytty
+#define ptcioctl ptyioctl
+cdev_decl(ptc);
+cdev_decl(log);
+#include "com.h"
+cdev_decl(com);
+#include "lpt.h"
+cdev_decl(lpt);
+cdev_decl(fd);
+dev_decl(filedesc,open);
+cdev_decl(rd);
+#include "bpfilter.h"
+cdev_decl(bpf);
+cdev_decl(sd);
+cdev_decl(st);
+cdev_decl(cd);
+#include "ch.h"
+cdev_decl(ch);
+#include "uk.h"
+cdev_decl(uk);
+#include "ss.h"
+cdev_decl(ss);
+#ifdef LKM
+#define NLKM 1
+#else
+#define NLKM 0
+#endif
+cdev_decl(lkm);
+#include "tun.h"
+cdev_decl(tun);
+cdev_decl(vnd);
+cdev_decl(ccd);
+#include "quadmouse.h"
+cdev_decl(quadmouse);
+#include "pms.h"
+cdev_decl(pms);
+#include "beep.h"
+cdev_decl(beep);
+#include "kbd.h"
+cdev_decl(kbd);
+#include "audio.h"
+cdev_decl(audio);
+#include "cpu.h"
+cdev_decl(cpu);
+#include "iic.h"
+cdev_decl(iic);
+#include "rtc.h"
+cdev_decl(rtc);
+/* Temporary hack for ATAPI CDROM */
+cdev_decl(wcd);
+
+/* Character devices */
+
+struct cdevsw cdevsw[] = {
+ cdev_mm_init(1, mm), /* 0: /dev/{null,mem,kmem,...} */
+ cdev_swap_init(1, sw), /* 1: /dev/drum (swap pseudo-device) */
+ cdev_cn_init(1, cn), /* 2: virtual console */
+ cdev_ctty_init(1,ctty), /* 3: controlling terminal */
+ cdev_physcon_init(NVT, physcon), /* 4: RPC console */
+ cdev_log_init(1,log), /* 5: /dev/klog */
+ cdev_ptc_init(NPTY,ptc), /* 6: pseudo-tty master */
+ cdev_tty_init(NPTY,pts), /* 7: pseudo-tty slave */
+ cdev_lpt_init(NLPT,lpt), /* 8: parallel printer */
+ cdev_mouse_init(NQUADMOUSE,quadmouse), /* 9: quadmouse driver */
+ cdev_beep_init(NBEEP,beep), /* 10: simple beep device */
+ cdev_kbd_init(NKBD,kbd), /* 11: kbd device */
+ cdev_tty_init(NCOM,com), /* 12: serial port */
+ cdev_lkm_dummy(), /* 13: */
+ cdev_lkm_dummy(), /* 14: */
+ cdev_lkm_dummy(), /* 15: */
+ cdev_disk_init(NWDC, wd), /* 16: ST506/ESDI/IDE disk */
+ cdev_disk_init(NFDC, fd), /* 17: floppy diskette */
+ cdev_disk_init(NRD, rd), /* 18: ram disk driver */
+ cdev_disk_init(NVND,vnd), /* 19: vnode disk driver */
+ cdev_disk_init(NWCD, wcd), /* 20: */
+ cdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */
+ cdev_lkm_dummy(), /* 22: */
+ cdev_lkm_dummy(), /* 23: */
+ cdev_disk_init(NSD,sd), /* 24: SCSI disk */
+ cdev_tape_init(NST,st), /* 25: SCSI tape */
+ cdev_disk_init(NCD,cd), /* 26: SCSI CD-ROM */
+ cdev_ch_init(NCH,ch), /* 27: SCSI autochanger */
+ cdev_ch_init(NUK,uk), /* 28: SCSI unknown */
+ cdev_ss_init(NSS,ss), /* 29: SCSI scanner */
+ cdev_lkm_dummy(), /* 30: */
+ cdev_lkm_dummy(), /* 31: */
+ cdev_bpftun_init(NBPFILTER,bpf),/* 32: Berkeley packet filter */
+ cdev_bpftun_init(NTUN,tun), /* 33: network tunnel */
+ cdev_fd_init(1,filedesc), /* 34: file descriptor pseudo-device */
+ cdev_lkm_init(NLKM,lkm), /* 35: loadable module driver */
+ cdev_audio_init(NAUDIO,audio), /* 36: generic audio I/O */
+ cdev_vidcvid_init(1,vidcvideo), /* 37: vidcvideo device */
+ cdev_cpu_init(NCPU,cpu), /* 38: cpu device */
+ cdev_lkm_dummy(), /* 39: */
+ cdev_mouse_init(NPMS,pms), /* 40: PS2 mouse driver */
+ cdev_lkm_dummy(), /* 41: */
+ cdev_iic_init(NIIC, iic), /* 42: IIC bus driver */
+ cdev_rtc_init(NRTC, rtc), /* 43: RTC driver */
+};
+
+int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
+
+int mem_no = 0; /* major device number of memory special file */
+
+
+/*
+ * Returns true if dev is /dev/mem or /dev/kmem.
+ */
+int
+iskmemdev(dev)
+ dev_t dev;
+{
+ return (major(dev) == mem_no && minor(dev) < 2);
+}
+
+/*
+ * Returns true if dev is /dev/zero.
+ */
+int
+iszerodev(dev)
+ dev_t dev;
+{
+ return (major(dev) == mem_no && minor(dev) == 3);
+}
+
+
+static int chrtoblktbl[] = {
+/* XXXX This needs to be dynamic for LKMs. */
+ /*VCHR*/ /*VBLK*/
+ /* 0 */ NODEV,
+ /* 1 */ 1,
+ /* 2 */ NODEV,
+ /* 3 */ NODEV,
+ /* 4 */ NODEV,
+ /* 5 */ NODEV,
+ /* 6 */ NODEV,
+ /* 7 */ NODEV,
+ /* 8 */ NODEV,
+ /* 9 */ NODEV,
+ /* 10 */ NODEV,
+ /* 11 */ NODEV,
+ /* 12 */ NODEV,
+ /* 13 */ NODEV,
+ /* 14 */ NODEV,
+ /* 15 */ NODEV,
+ /* 16 */ 16,
+ /* 17 */ 17,
+ /* 18 */ 18,
+ /* 19 */ 19,
+ /* 20 */ 20,
+ /* 21 */ 21,
+ /* 22 */ NODEV,
+ /* 23 */ NODEV,
+ /* 24 */ 24,
+ /* 25 */ 25,
+ /* 26 */ 26,
+ /* 27 */ NODEV,
+ /* 28 */ NODEV,
+ /* 29 */ NODEV,
+ /* 30 */ NODEV,
+ /* 31 */ NODEV,
+ /* 32 */ NODEV,
+ /* 33 */ NODEV,
+ /* 34 */ NODEV,
+ /* 35 */ NODEV,
+ /* 36 */ NODEV,
+ /* 37 */ NODEV,
+ /* 38 */ NODEV,
+ /* 39 */ NODEV,
+ /* 40 */ NODEV,
+ /* 41 */ NODEV,
+ /* 42 */ NODEV,
+ /* 43 */ NODEV,
+};
+
+/*
+ * Convert a character device number to a block device number.
+ */
+
+dev_t
+chrtoblk(dev)
+ dev_t dev;
+{
+ int blkmaj;
+
+ if (major(dev) >= nchrdev)
+ return (NODEV);
+
+ blkmaj = chrtoblktbl[major(dev)];
+ if (blkmaj == NODEV)
+ return (NODEV);
+ return (makedev(blkmaj, minor(dev)));
+}
+
+/*
+ * This entire table could be autoconfig()ed but that would mean that
+ * the kernel's idea of the console would be out of sync with that of
+ * the standalone boot. I think it best that they both use the same
+ * known algorithm unless we see a pressing need otherwise.
+ */
+
+#include <dev/cons.h>
+
+cons_decl(rpcconsole);
+cons_decl(com);
+
+struct consdev constab[] = {
+#if (NVT + NRPC > 0)
+ cons_init(rpcconsole),
+#endif
+
+/*#if (NCOM > 0)
+ cons_init(com),
+#endif*/
+ { 0 },
+};
+
+/* End of conf.c */
--- /dev/null
+/* $NetBSD: coproc15.S,v 1.1 1996/01/31 23:15:33 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * coproc15.S
+ *
+ * Manipulation of the CPU internal coprocessor #15 registers
+ *
+ * Created : 29/11/94
+ * Last updated : 28/08/95
+ *
+ * Based on arm/readcoproc15.S & arm/writecoproc15.S
+ *
+ * $Id: coproc15.S,v 1.1.1.1 1996/04/24 11:08:24 deraadt Exp $
+ */
+
+lr .req r14
+pc .req r15
+
+.text
+/*
+ * Functions to read the internal coprocessor registers
+ *
+ * Currently the only registers that can be read are
+ * r0 - CPU ID
+ * r5 - Fault status
+ * r6 - Fault address
+ *
+ * Eventually these should be inlined.
+ */
+
+ .global _cpu_id
+
+_cpu_id:
+ mrc 15, 0, r0, c0, c0, 0
+ mov pc, lr
+
+ .global _cpu_faultstatus
+
+_cpu_faultstatus:
+ mrc 15, 0, r0, c5, c0, 0
+ mov pc, lr
+
+ .global _cpu_faultaddress
+
+_cpu_faultaddress:
+ mrc 15, 0, r0, c6, c0, 0
+ mov pc, lr
+
+
+/*
+ * Functions to write the internal coprocessor registers
+ *
+ *
+ * Currently the only registers that can be write are
+ * r1 - CPU Control
+ * r2 - TTB
+ * r3 - Domain Access Control
+ * r5 - Flush TLB
+ * r6 - Purge TLB
+ * r7 - Flush IDC
+ *
+ * Eventually these should be inlined.
+ */
+
+ .global _cpu_control
+
+_cpu_control:
+ mcr 15, 0, r0, c1, c0, 0
+ mov pc, lr
+
+ .global _setttb
+
+_setttb:
+/* We need to flush the cache as it uses virtual addresses that are about to change */
+ mcr 15, 0, r0, c7, c0, 0
+
+/* Write the TTB */
+ mcr 15, 0, r0, c2, c0, 0
+
+/* If we have updated the TTB we must flush the TLB */
+ mcr 15, 0, r0, c5, c0, 0
+
+/* For good measure we will flush the IDC as well - do we need this */
+ mcr 15, 0, r0, c7, c0, 0
+
+/* Make sure that pipeline is emptied */
+
+ mov r0, r0
+ mov r0, r0
+
+ mov pc, lr
+
+ .global _cpu_domains
+
+_cpu_domains:
+ mcr 15, 0, r0, c3, c0, 0
+ mov pc, lr
+
+ .global _tlbflush
+
+_tlbflush:
+ mcr 15, 0, r0, c5, c0, 0
+ mov pc, lr
+
+ .global _tlbpurge
+
+_tlbpurge:
+ mcr 15, 0, r0, c6, c0, 0
+ mov pc, lr
+
+ .global _idcflush
+
+_idcflush:
+ mcr 15, 0, r0, c7, c0, 0
+ mov pc, lr
--- /dev/null
+/* $NetBSD: copystr.S,v 1.4 1996/03/27 22:19:32 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * copystr.S
+ *
+ * optimised and fault protected copystr function
+ *
+ * Created : 16/05/95
+ */
+
+#include "assym.h"
+#include <sys/errno.h>
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+ .text
+Lcurpcb:
+ .word _curpcb
+
+Lcurproc:
+ .word _curproc
+
+copystrfault:
+ mov r0, #0x00000000
+ str r0, [r4, #PCB_ONFAULT]
+ mov r0, #EFAULT
+ ldmfd sp!, {r4-r6}
+ mov pc, lr
+
+copystrpcbfault:
+ stmfd sp!, {lr}
+ mov r3, r1
+ mov r1, r4
+ add r0, pc, #copystrtext - . - 8
+ mov r2, r3
+ ldr r3, Lcurproc
+ ldr r3, [r3]
+ bl _printf
+
+ bl _traceback
+
+ mov r0, #EFAULT
+ ldmfd sp!, {lr}
+ ldmfd sp!, {r4-r6}
+ mov pc, lr
+
+copystrtext:
+ .asciz "Alert ! PCB = %08x during copystr addr=%08x curproc=%08x\n"
+
+ .align 0
+
+/*
+ * r0 - from
+ * r1 - to
+ * r2 - maxlens
+ * r3 - lencopied
+ */
+
+ .global _copystrinout
+
+_copystrinout:
+ stmfd sp!, {r4-r6}
+ teq r2, #0x00000000
+ moveq r5, #0x00000000
+ moveq r6, #0x00000000
+ beq copystrexit
+
+ ldr r4, Lcurpcb
+ ldr r4, [r4]
+ teq r4, #0x00000000
+ beq copystrpcbfault
+ add r5, pc, #copystrfault - . - 8
+ str r5, [r4, #PCB_ONFAULT]
+ mov r6, #0x00000000
+
+copystr_loop:
+ ldrb r5, [r0], #0x0001
+ strb r5, [r1], #0x0001
+ add r6, r6, #0x00000001
+ teq r5, #0x00000000
+ teqne r6, r2
+ bne copystr_loop
+
+copystrexit:
+ teq r3, #0x00000000
+ strne r6, [r3]
+
+ teq r5, #0x00000000
+ moveq r0, #0x00000000
+ movne r0, #ENAMETOOLONG
+
+ mov r6, #0x00000000
+ str r6, [r4, #PCB_ONFAULT]
+ ldmfd sp!, {r4-r6}
+ mov pc, lr
--- /dev/null
+/* $NetBSD: cpuswitch.S,v 1.6 1996/03/27 21:24:39 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * cpu.S
+ *
+ * cpu switching functions
+ *
+ * Created : 15/10/94
+ */
+
+#include "assym.h"
+#include <machine/param.h>
+#include <machine/cpu.h>
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+/*
+ * PULLFRAME - macro to pull a trap frame from the stack in the current mode
+ * Since the current mode is used, the SVC R14 field is ignored.
+ */
+
+#define PULLFRAME \
+ ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \
+ msr spsr_all, r0; \
+ add sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ add sp, sp, #0x00000004; /* Skip SVC R14 */ \
+ ldr lr, [sp], #0x0004; /* Pull the return address */
+
+/*
+ * setrunqueue() and remrq()
+ *
+ * Functions to add and remove a process for the run queue.
+ */
+
+ .text
+
+Lwhichqs:
+ .word _whichqs
+
+Lqs:
+ .word _qs
+
+/*
+ * On entry
+ * r0 = process
+ */
+
+ .global _setrunqueue
+_setrunqueue:
+/*
+ * Local register usage
+ * r0 = process
+ * r1 = queue
+ * r2 = &qs[queue]
+ * r3 = temp
+ * r4 = whichqs
+ */
+ stmfd sp!, {r4}
+
+#ifdef DIAGNOSTIC
+ ldr r1, [r0, #(P_BACK)]
+ teq r1, #0x00000000
+ bne Lsetrunqueue_erg
+
+ ldr r1, [r0, #(P_WCHAN)]
+ teq r1, #0x00000000
+ bne Lsetrunqueue_erg
+#endif
+
+/* Get the priority of the queue */
+
+ ldrb r1, [r0, #(P_PRIORITY)]
+ mov r1, r1, lsr #2
+
+/* Indicate that there is a process on this queue */
+
+ ldr r4, Lwhichqs
+ ldr r2, [r4]
+ mov r3, #0x00000001
+ mov r3, r3, lsl r1
+ orr r2, r2, r3
+ str r2, [r4]
+
+/* Get the address of the queue */
+
+ ldr r2, Lqs
+ add r1, r2, r1, lsl # 3
+
+/* Hook the process in */
+ str r1, [r0, #(P_FORW)]
+ ldr r2, [r1, #(P_BACK)]
+
+ str r0, [r1, #(P_BACK)]
+#ifdef DIAGNOSTIC
+ teq r2, #0x00000000
+ beq Lsetrunqueue_erg
+#endif
+ str r0, [r2, #(P_FORW)]
+ str r2, [r0, #(P_BACK)]
+
+ ldmfd sp!, {r4}
+
+ mov pc, lr
+
+#ifdef DIAGNOSTIC
+Lsetrunqueue_erg:
+ mov r2, r1
+ mov r1, r0
+ add r0, pc, #Ltext1 - . - 8
+ bl _printf
+
+ ldr r2, Lqs
+ ldr r1, [r2]
+ add r0, pc, #Ltext2 - . - 8
+ b _panic
+
+Ltext1:
+ .asciz "setrunqueue : %08x %08x\n"
+Ltext2:
+ .asciz "setrunqueue : [qs]=%08x qs=%08x\n"
+ .align 0
+#endif
+
+/*
+ * On entry
+ * r0 = process
+ */
+
+ .global _remrq
+_remrq:
+
+/*
+ * Local register usage
+ * r0 = oldproc
+ * r1 = queue
+ * r2 = &qs[queue]
+ * r3 = scratch
+ * r4 = whichqs
+ */
+ stmfd sp!, {r4}
+
+/* Get the priority of the queue */
+
+ ldrb r1, [r0, #(P_PRIORITY)]
+ mov r1, r1, lsr #2
+
+/* Unhook the process */
+
+ ldr r2, [r0, #(P_FORW)]
+ ldr r3, [r0, #(P_BACK)]
+
+ str r3, [r2, #(P_BACK)]
+ str r2, [r3, #(P_FORW)]
+
+/* If the queue is now empty clear the queue not empty flag */
+
+ teq r2, r3
+
+/* This could be reworked to avoid the use of r4 */
+
+ ldreq r4, Lwhichqs
+ ldreq r2, [r4]
+ moveq r3, #0x00000001
+ moveq r3, r3, lsl r1
+ biceq r2, r2, r3
+ streq r2, [r4]
+
+/* Remove the back pointer for the process */
+
+ mov r1, #0x00000000
+ str r1, [r0, #(P_BACK)]
+
+ ldmfd sp!, {r4}
+
+ mov pc, lr
+
+
+/*
+ * cpuswitch()
+ *
+ * preforms a process context switch.
+ * This function has several entry points
+ */
+
+
+Lcurproc:
+ .word _curproc
+
+ .global _curpcb
+
+_curpcb:
+ .word 0x00000000
+
+Lcurpcb:
+ .word _curpcb
+
+Lwant_resched:
+ .word _want_resched
+
+
+/*
+ * Idle loop, exercised while waiting for a process to wake up.
+ */
+
+ .global _idle
+_idle:
+idle:
+
+/* Enable interrupts */
+
+ IRQenable
+
+#ifdef CPU_ARM7500
+/* ARM7500 has a suspend mode so use it ! [danny, does this work ? - mark] */
+
+ mov r7, #(IOMD_BASE)
+ orr r7, r7, #(IOMD_SUSPEND - IOMD_BASE)
+ mov r3, #0x00000001
+ strb r3, [r7]
+#endif
+
+/* Disable interrupts while we check for an active queue */
+
+ IRQdisable
+ ldr r7, Lwhichqs
+ ldr r3, [r7]
+ teq r3, #0x00000000
+ bne sw1
+
+/* All processes are still asleep so idle a while longer */
+
+ b idle
+
+
+/*
+ * Find a new process to run, save the current context and
+ * load the new context
+ */
+
+ .global _cpu_switch
+_cpu_switch:
+/*
+ * Local register usage. Some of these registers are out of date.
+ * r1 = oldproc
+ * r2 = spl level
+ * r3 = whichqs
+ * r4 = queue
+ * r5 = &qs[queue]
+ * r6 = newproc
+ * r7 = scratch
+ */
+ stmfd sp!, {r4-r7, lr}
+
+/*
+ * Get the current process and indicate that there is no longer a valid
+ * process (curproc = 0)
+ */
+
+ ldr r7, Lcurproc
+ ldr r1, [r7]
+ mov r0, #0x00000000
+ str r0, [r7]
+
+/* Zero the pcb */
+
+ ldr r7, Lcurpcb
+ str r0, [r7]
+
+/* Lower the spl level to spl0 and get the current spl level. */
+
+ mov r7, r1
+
+#ifdef spl0
+ mov r0, #(SPL_0)
+ bl _splx
+#else
+ bl _spl0
+#endif
+
+/* Push the old spl level onto the stack */
+
+ str r0, [sp, #-0x0004]!
+
+ mov r1, r7
+
+/* First phase : find a new process */
+
+/* rem: r1 = old proc */
+
+switch_search:
+ IRQdisable
+
+/* Do we have any active queues */
+
+ ldr r7, Lwhichqs
+ ldr r3, [r7]
+
+/* If not we must idle until we do. */
+
+ teq r3, #0x00000000
+ beq idle
+
+sw1:
+/* rem: r1 = old proc */
+/* rem: r3 = whichqs */
+/* rem: interrupts are disabled */
+
+/*
+ * Paranoid debug time ....
+ * Is this overkill ? If we are not in SVC mode then things are
+ * very sick and will probably have already died.
+ */
+
+#ifdef DIAGNOSTIC
+ mrs r4, cpsr_all
+ and r4, r4, #(PSR_MODE)
+ teq r4, #(PSR_SVC32_MODE)
+ beq switchmodeok
+
+ add r0, pc, #switchpanic - . - 8
+ mrs r1, cpsr_all
+ bl _panic
+
+switchpanic:
+ .asciz "Yikes! In cpu_switch() but not in SVC mode (%08x)\n"
+ .align 0
+
+switchmodeok:
+#endif
+
+/*
+ * We have found an active queue. Currently we do not know which queue
+ * is active just that one of them is.
+ * We must check each queue to find the active one.
+ * r3 contains a bit for each of the 32 queues. A one indicates that
+ * that the queue has something in it.
+ */
+
+/* This ffs() type routine code be optimised */
+
+ mov r4, #0x00000000
+
+findqueue:
+ mov r0, #0x00000001
+ mov r0, r0, lsl r4
+
+ tst r3, r0
+ addeq r4, r4, #0x00000001
+ beq findqueue
+
+/*
+ * Ok we have found the active queue. The above code can never fail as
+ * we only get to it if r3 != 0
+ * r4 contains the number of the first queue found with a process in it.
+ */
+
+/* rem: r0 = bit mask of chosen queue (1 << r4) */
+/* rem: r1 = old proc */
+/* rem: r3 = whichqs */
+/* rem: r4 = queue number */
+/* rem: interrupts are disabled */
+
+/* Get the address of the queue (&qs[queue]) */
+
+ ldr r5, Lqs
+ add r5, r5, r4, lsl #3
+
+/*
+ * Get the process from the queue and place the next process in the queue
+ * at the head. This basically unlinks the process at the head of the queue.
+ */
+ ldr r6, [r5, #(P_FORW)]
+
+/* rem: r6 = new process */
+
+ ldr r7, [r6, #(P_FORW)]
+ str r7, [r5, #(P_FORW)]
+
+/*
+ * Test to see if the queue is now empty. If the head of the queue points
+ * to the queue itself then there are no more processes in the queue.
+ * We can therefore clear the queue not empty flag held in r3.
+ */
+
+ teq r5, r7
+ biceq r3, r3, r0
+
+/* rem: r0 = bit mask of chosen queue (1 << r4) - NOT NEEDED AN MORE */
+
+/* Fix the back pointer for the process now at the head of the queue. */
+
+ ldr r0, [r6, #(P_BACK)]
+ str r0, [r7, #(P_BACK)]
+
+/* Update the RAM copy of the queue not empty flags word. */
+
+ ldr r7, Lwhichqs
+ str r3, [r7]
+
+/* rem: r1 = old proc */
+/* rem: r3 = whichqs - NOT NEEDED ANY MORE */
+/* rem: r4 = queue number - NOT NEEDED ANY MORE */
+/* rem: r6 = new process */
+/* rem: interrupts are disabled */
+
+/* Clear the want_resched flag */
+
+ mov r0, #0x00000000
+ ldr r7, Lwant_resched
+ str r0, [r7]
+
+/*
+ * Clear the back pointer of the process we have removed from the head
+ * of the queue. The new process is isolated now.
+ */
+
+ mov r0, #0x00000000
+ str r0, [r6, #(P_BACK)]
+
+/* We have a new curproc now so make a note it */
+
+ ldr r7, Lcurproc
+ str r6, [r7]
+
+/* Hook in a new pcb */
+
+ ldr r7, Lcurpcb
+ ldr r0, [r6, #(P_ADDR)]
+ str r0, [r7]
+
+/* At this point we can allow IRQ's again. */
+
+/*
+ IRQenable
+ IRQdisable
+*/
+
+/* rem: r1 = old proc */
+/* rem: r6 = new process */
+/* rem: interrupts are disabled */
+
+/*
+ * If the new process is the same as the process that called cpu_switch
+ * Then we do not need to save and restore any contexts. This means
+ * we can make a quick exit.
+ * The test is simple if curproc on entry (now in r1) is the same as the
+ * proc removed from the queue we can jump to the exit.
+ */
+
+ teq r1, r6
+ beq switch_return
+
+/*
+ * If the curproc on entry to cpu_switch was zero then the process that
+ * called it was exiting. This means that we do not need to save the current
+ * context. Instead we can jump straight to restoring the context for
+ * the new process.
+ */
+
+ teq r1, #0x00000000
+ beq switch_exited
+
+/* rem: r1 = old proc */
+/* rem: r6 = new process */
+/* rem: interrupts are disabled */
+
+/* Stage two : Save old context */
+
+/* Remember the old process in r0 */
+
+ mov r0, r1
+
+/* Get the user structure for the old process. */
+
+ ldr r1, [r1, #(P_ADDR)]
+
+/* Save all the registers in the old process's pcb */
+
+ add r7, r1, #(PCB_R8)
+ stmia r7, {r8-r13}
+
+/*
+ * This can be optimised... We know we want to go from SVC32 mode to UND32
+ * mode
+ */
+
+ mrs r3, cpsr_all
+ bic r2, r3, #(PSR_MODE)
+ orr r2, r2, #(PSR_UND32_MODE | I32_bit | F32_bit)
+ msr cpsr_all, r2
+
+ str sp, [r1, #(PCB_UND_SP)]
+
+ msr cpsr_all, r3 /* Restore the old mode */
+
+/* rem: r0 = old proc */
+/* rem: r0 = old pcb */
+/* rem: r6 = new process */
+/* rem: interrupts are disabled */
+
+/* What else needs to be saved Only FPA stuff when that is supported */
+
+/* Third phase : restore saved context */
+
+switch_exited:
+
+/* At this point we need to kill IRQ's again. */
+
+ mrs r0, cpsr_all
+ orr r0, r0, #(I32_bit | F32_bit)
+ msr cpsr_all , r0
+
+/* IRQdisable*/
+
+/* Get the user structure for the new process in r1 */
+
+ ldr r1, [r6, #(P_ADDR)]
+
+/* Get the pagedir physical address for the process. */
+
+ ldr r0, [r1, #(PCB_PAGEDIR)]
+
+/* Switch the memory to the new process */
+
+/* For good measure we will flush the IDC as well */
+ mcr 15, 0, r0, c7, c0, 0
+
+/* Write the TTB */
+ mcr 15, 0, r0, c2, c0, 0
+
+/* If we have updated the TTB we must flush the TLB */
+ mcr 15, 0, r0, c5, c0, 0
+
+/* For good measure we will flush the IDC as well */
+ mcr 15, 0, r0, c7, c0, 0
+
+/* Make sure that pipeline is emptied */
+ mov r0, r0
+ mov r0, r0
+
+/*
+ * This can be optimised... We know we want to go from SVC32 mode to UND32
+ * mode
+ */
+
+ mrs r3, cpsr_all
+ bic r2, r3, #(PSR_MODE)
+ orr r2, r2, #(PSR_UND32_MODE)
+ msr cpsr_all, r2
+
+ ldr sp, [r1, #(PCB_UND_SP)]
+
+ msr cpsr_all, r3 /* Restore the old mode */
+
+/* Restore all the save registers */
+
+ add r7, r1, #PCB_R8
+ ldmia r7, {r8-r13}
+
+/* Remember the pcb currently in use */
+
+ ldr r7, Lcurpcb
+ str r1, [r7]
+
+/* We can enable interrupts again */
+
+/*
+ IRQenable
+*/
+
+#ifdef ARMFPE
+ add r0, r1, #(USER_SIZE) & 0x00ff
+ add r0, r0, #(USER_SIZE) & 0xff00
+ bl _arm_fpe_core_changecontext
+#endif
+
+switch_return:
+
+/* We have a new curproc now so make a note it */
+
+/*
+ ldr r7, Lcurproc
+ str r6, [r7]
+*/
+
+/* Get the spl level from the stack and update the current spl level */
+
+ ldr r0, [sp], #0x0004
+ bl _splx
+
+/* IRQenable*/
+
+/* cpu_switch returns the proc it switched to. */
+
+ mov r0, r6
+
+/*
+ * Pull the registers that got pushed when either savectx or cpu_switch
+ * was called and return.
+ */
+ ldmfd sp!, {r4-r7, pc}
+
+Lproc0:
+ .word _proc0
+
+Lkernel_map:
+ .word _kernel_map
+
+
+ .global _switch_exit
+
+_switch_exit:
+
+/*
+ * r0 = proc
+ * r1 = proc0
+ */
+
+ ldr r1, Lproc0
+
+/* In case we fault */
+
+ mov r2, #0x00000000
+ ldr r3, Lcurproc
+ str r2, [r3]
+
+/* ldr r3, Lcurpcb
+ str r2, [r3]*/
+
+/* Switch to proc0 context */
+
+ IRQdisable
+
+ ldr r2, [r1, #(P_ADDR)]
+ ldr r3, [r2, #(PCB_PAGEDIR)]
+
+/* For good measure we will flush the IDC as well */
+ mcr 15, 0, r0, c7, c0, 0
+
+/* Write the TTB */
+ mcr 15, 0, r3, c2, c0, 0
+
+/* If we have updated the TTB we must flush the TLB */
+ mcr 15, 0, r0, c5, c0, 0
+
+/* For good measure we will flush the IDC as well */
+ mcr 15, 0, r0, c7, c0, 0
+
+/* Make sure that pipeline is emptied */
+ mov r0, r0
+ mov r0, r0
+
+/* Restore all the save registers */
+
+ add r7, r2, #PCB_R8
+ ldmia r7, {r8-r13}
+
+/* This is not really needed ! */
+/* Yes it is for the su and fu routines */
+
+/* ldr sp, [r2, #(PCB_SP)]*/
+ ldr r3, Lcurpcb
+ str r2, [r3]
+
+/* IRQenable*/
+
+ str r0, [sp, #-0x0004]!
+
+/* Thoroughly nuke the old process's resources. */
+
+/* This has to be done here, before we lose the pmap */
+
+ mov r1, #0x00000000
+ add r2, r1, #NBPG
+ ldr r0, [r0, #(P_VMSPACE)]
+ add r0, r0, #(VM_PMAP)
+ bl _pmap_remove
+ ldr r0, [sp]
+
+/*
+ * Have to wait until we have switched to proc0 as the pmap gets released
+ * in vmspace_free()
+ */
+
+ ldr r0, [r0, #(P_VMSPACE)]
+ bl _vmspace_free
+
+/* This has to be done here */
+
+ mov r2, #(UPAGES << PGSHIFT)
+ ldr r0, [sp], #0x0004
+ ldr r1, [r0, #(P_ADDR)]
+ ldr r0, Lkernel_map
+ ldr r0, [r0]
+ bl _kmem_free
+
+/* Paranoia */
+
+ mov r0, #0x00000000
+ ldr r1, Lcurproc
+ str r0, [r1]
+
+ ldr r1, Lproc0
+ b switch_search
+
+
+Lcurrent_spl_level:
+ .word _current_spl_level
+
+ .global _savectx
+_savectx:
+/*
+ * r0 = pcb
+ */
+
+/* Push registers.*/
+
+ stmfd sp!, {r4-r7, lr}
+
+/* Store all the registers in the process's pcb */
+
+ add r2, r0, #(PCB_R8)
+ stmia r2, {r8-r13}
+
+/* Pull the regs of the stack */
+
+ ldmfd sp!, {r4-r7, pc}
+
+
+ .global _proc_trampoline
+_proc_trampoline:
+ add lr, pc, #(trampoline_return - . - 8)
+ mov r0, r5
+ mov r1, sp
+ mov pc, r4
+
+trampoline_return:
+/* Kill irq's */
+
+ mrs r0, cpsr_all
+ orr r0, r0, #(I32_bit)
+ msr cpsr_all, r0
+
+ PULLFRAME
+
+ movs pc, lr /* Exit */
+
--- /dev/null
+/* $NetBSD: db_disasm.c,v 1.2 1996/03/06 22:46:37 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe.
+ * Copyright (c) 1996 Brini.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * db_disasm.c
+ *
+ * Kernel disassembler
+ *
+ * Created : 10/02/96
+ *
+ * Structured after the sparc/sparc/db_disasm.c by David S. Miller &
+ * Paul Kranenburg
+ *
+ * This code is not complete. Not all instructions are disassembled.
+ * Current LDF, STF, CDT and MSRF are not supported.
+ */
+
+#include <sys/param.h>
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+
+/*
+ * General instruction format
+ *
+ * insn[cc][mod] [operands]
+ *
+ * Those fields with an uppercase format code indicate that the field follows
+ * directly after the instruction before the separator i.e. they modify the instruction
+ * rather than just being an operand to the instruction. The only exception is the
+ * writeback flag which follows a operand.
+ *
+ *
+ * 2 - print Operand 2 of a data processing instrcution
+ * d - destination register (bits 12-15)
+ * n - n register (bits 16-19)
+ * s - s register (bits 8-11)
+ * o - indirect register rn (bits 16-19) (used by swap)
+ * m - m register (bits 0-4)
+ * a - address operand of ldr/str instruction
+ * l - register list for ldm/stm instruction
+ * f - 1st fp operand (register) (bits 12-14)
+ * g - 2nd fp operand (register) (bits 16-18)
+ * h - 3rd fp operand (register/immediate) (bits 0-4)
+ * b - branch address
+ * X - block transfer type
+ * c - comment field bits(0-23)
+ * p - saved or current status register
+ * B - byte transfer flag
+ * S - set status flag
+ * T - user mode transfer
+ * P - fp precision
+ * R - fp rounding
+ * w - writeback flag
+ * # - co-processor number
+ * y - co-processor data processing registers
+ * z - co-processor data transfer registers
+ */
+
+struct arm32_insn {
+ u_int mask;
+ u_int pattern;
+ char* name;
+ char* format;
+};
+
+struct arm32_insn arm32_i[] = {
+ { 0x0f000000, 0x0f000000, "swi", "c" },
+ { 0x0f000000, 0x0a000000, "b", "b" },
+ { 0x0f000000, 0x0b000000, "bl", "b" },
+ { 0x0fe000f0, 0x00000090, "mul", "Sdms" },
+ { 0x0fe000f0, 0x00200090, "mla", "Sdmsn" },
+ { 0x0e100000, 0x04000000, "str", "BTdaW" },
+ { 0x0e100000, 0x04100000, "ldr", "BTdaW" },
+ { 0x0c100010, 0x04000000, "str", "BTdaW" },
+ { 0x0c100010, 0x04100000, "ldr", "BTdaW" },
+ { 0x0e100000, 0x08000000, "stm", "XnWl" },
+ { 0x0e100000, 0x08100000, "ldm", "XnWl" },
+ { 0x0fb00ff0, 0x01000090, "swap", "Bdmo" },
+ { 0x0fbf0fff, 0x010f0000, "mrs", "dp" },
+ { 0x0dbffff0, 0x0129f000, "msr", "pm" },
+ { 0x0dbffff0, 0x0128f000, "msrf", "pm" },
+ { 0x0de00000, 0x00000000, "and", "Sdn2" },
+ { 0x0de00000, 0x00200000, "eor", "Sdn2" },
+ { 0x0de00000, 0x00400000, "sub", "Sdn2" },
+ { 0x0de00000, 0x00600000, "rsb", "Sdn2" },
+ { 0x0de00000, 0x00800000, "add", "Sdn2" },
+ { 0x0de00000, 0x00a00000, "adc", "Sdn2" },
+ { 0x0de00000, 0x00c00000, "sbc", "Sdn2" },
+ { 0x0de00000, 0x00e00000, "rsc", "Sdn2" },
+ { 0x0de00000, 0x01000000, "tst", "Sn2" },
+ { 0x0de00000, 0x01200000, "teq", "Sn2" },
+ { 0x0de00000, 0x01400000, "cmp", "Sn2" },
+ { 0x0de00000, 0x01600000, "cmn", "Sn2" },
+ { 0x0de00000, 0x01800000, "orr", "Sdn2" },
+ { 0x0de00000, 0x01a00000, "mov", "Sd2" },
+ { 0x0de00000, 0x01c00000, "bic", "Sdn2" },
+ { 0x0de00000, 0x01e00000, "mvn", "Sd2" },
+ { 0x0ff08f10, 0x0e000100, "adf", "PRfgh" },
+ { 0x0ff08f10, 0x0e100100, "muf", "PRfgh" },
+ { 0x0ff08f10, 0x0e200100, "suf", "PRfgh" },
+ { 0x0ff08f10, 0x0e300100, "rsf", "PRfgh" },
+ { 0x0ff08f10, 0x0e400100, "dvf", "PRfgh" },
+ { 0x0ff08f10, 0x0e500100, "rdf", "PRfgh" },
+ { 0x0ff08f10, 0x0e600100, "pow", "PRfgh" },
+ { 0x0ff08f10, 0x0e700100, "rpw", "PRfgh" },
+ { 0x0ff08f10, 0x0e800100, "rmf", "PRfgh" },
+ { 0x0ff08f10, 0x0e900100, "fml", "PRfgh" },
+ { 0x0ff08f10, 0x0ea00100, "fdv", "PRfgh" },
+ { 0x0ff08f10, 0x0eb00100, "frd", "PRfgh" },
+ { 0x0ff08f10, 0x0ec00100, "pol", "PRfgh" },
+ { 0x0f008f10, 0x0e000100, "fpbop", "PRfgh" },
+ { 0x0ff08f10, 0x0e008100, "mvf", "PRfh" },
+ { 0x0ff08f10, 0x0e108100, "mnf", "PRfh" },
+ { 0x0ff08f10, 0x0e208100, "abs", "PRfh" },
+ { 0x0ff08f10, 0x0e308100, "rnd", "PRfh" },
+ { 0x0ff08f10, 0x0e408100, "sqt", "PRfh" },
+ { 0x0ff08f10, 0x0e508100, "log", "PRfh" },
+ { 0x0ff08f10, 0x0e608100, "lgn", "PRfh" },
+ { 0x0ff08f10, 0x0e708100, "exp", "PRfh" },
+ { 0x0ff08f10, 0x0e808100, "sin", "PRfh" },
+ { 0x0ff08f10, 0x0e908100, "cos", "PRfh" },
+ { 0x0ff08f10, 0x0ea08100, "tan", "PRfh" },
+ { 0x0ff08f10, 0x0eb08100, "asn", "PRfh" },
+ { 0x0ff08f10, 0x0ec08100, "acs", "PRfh" },
+ { 0x0ff08f10, 0x0ed08100, "atn", "PRfh" },
+ { 0x0f008f10, 0x0e008100, "fpuop", "PRfh" },
+ { 0x0e100f00, 0x0c000100, "stf", "P" },
+ { 0x0e100f00, 0x0c100100, "ldf", "P" },
+ { 0x0f100010, 0x0e000010, "mcr", "#z" },
+ { 0x0f100010, 0x0e100010, "mrc", "#z" },
+ { 0x0f000010, 0x0e000000, "cdp", "#y" },
+ { 0x0e000000, 0x0c000000, "cdt", "#" },
+ { 0x00000000, 0x00000000, NULL, NULL }
+};
+
+char *arm32_insn_conditions[] = {
+ "eq",
+ "ne",
+ "cs",
+ "cc",
+ "mi",
+ "pl",
+ "vs",
+ "vc",
+ "hi",
+ "ls",
+ "ge",
+ "lt",
+ "gt",
+ "le",
+ "",
+ "nv"
+};
+
+char *insn_block_transfers[] = {
+ "da",
+ "ia",
+ "db",
+ "ib"
+};
+
+char *insn_stack_block_transfers[] = {
+ "fa",
+ "ea",
+ "fd",
+ "fa"
+};
+
+char *op_shifts[] = {
+ "lsl",
+ "lsr",
+ "asr",
+ "ror"
+};
+
+char *insn_fpa_rounding[] = {
+ "",
+ "p",
+ "m",
+ "z"
+};
+
+char *insn_fpa_precision[] = {
+ "s",
+ "d",
+ "e",
+ "p"
+};
+
+char *insn_fpaconstants[] = {
+ "0.0",
+ "1.0",
+ "2.0",
+ "3.0",
+ "4.0",
+ "5.0",
+ "0.5",
+ "10.0"
+};
+
+#define insn_condition(x) arm32_insn_conditions[(x >> 28) & 0x0f]
+#define insn_blktrans(x) insn_block_transfers[(x >> 23) & 3]
+#define insn_stkblktrans(x) insn_stack_block_transfers[(x >> 23) & 3]
+#define op2_shift(x) op_shifts[(x >> 5) & 3]
+#define insn_fparnd(x) insn_fpa_rounding[(x >> 5) & 0x03]
+#define insn_fpaprec(x) insn_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 3]
+#define insn_fpaimm(x) insn_fpaconstants[x & 0x07]
+
+void db_register_shift __P((u_int insn));
+void db_print_reglist __P((u_int insn));
+void db_insn_ldrstr __P((u_int insn, u_int loc));
+
+
+vm_offset_t
+db_disasm(loc, altfmt)
+ vm_offset_t loc;
+ boolean_t altfmt;
+{
+ struct arm32_insn* i_ptr = (struct arm32_insn *)&arm32_i;
+
+ u_int insn;
+ int matchp;
+ int branch;
+ char* f_ptr, *cp;
+ int fmt;
+
+ fmt = 0;
+ matchp = 0;
+ insn = db_get_value(loc, 4, 0);
+
+/* db_printf("loc=%08x insn=%08x : ", loc, insn);*/
+/* db_printf("loc=%08x : ", loc);*/
+
+ while (i_ptr->name) {
+ if ((insn & i_ptr->mask) == i_ptr->pattern) {
+ matchp = 1;
+ break;
+ }
+ i_ptr++;
+ }
+
+ if (!matchp) {
+ db_printf("undefined\n");
+ return(loc + 4);
+ }
+
+ db_printf("%s%s", i_ptr->name, insn_condition(insn));
+
+ f_ptr = i_ptr->format;
+
+ while (*f_ptr) {
+ switch (*f_ptr) {
+ case '2':
+ if (insn & 0x02000000) {
+ db_printf("#0x%08x", (insn & 0xff) << (((insn >> 7) & 0x1e)));
+ } else {
+ db_register_shift(insn);
+ }
+ break;
+ case 'd':
+ db_printf("r%d", ((insn >> 12) & 0x0f));
+ break;
+ case 'n':
+ db_printf("r%d", ((insn >> 16) & 0x0f));
+ break;
+ case 's':
+ db_printf("r%d", ((insn >> 8) & 0x0f));
+ break;
+ case 'o':
+ db_printf("[r%d]", ((insn >> 16) & 0x0f));
+ break;
+ case 'm':
+ db_printf("r%d", ((insn >> 0) & 0x0f));
+ break;
+ case 'a':
+ db_insn_ldrstr(insn, loc);
+ break;
+ case 'l':
+ db_print_reglist(insn);
+ break;
+ case 'f':
+ db_printf("f%d", (insn >> 12) & 7);
+ break;
+ case 'g':
+ db_printf("f%d", (insn >> 16) & 7);
+ break;
+ case 'h':
+ if (insn & (1 << 3))
+ db_printf("#%s", insn_fpaimm(insn));
+ else
+ db_printf("f%d", insn & 7);
+ break;
+ case 'b':
+ branch = ((insn << 2) & 0x03ffffff);
+ if (branch & 0x02000000)
+ branch |= 0xfc000000;
+ db_printsym((db_addr_t)(loc + 8 + branch),
+ DB_STGY_ANY);
+ break;
+ case 'X':
+ db_printf("%s", insn_blktrans(insn));
+ break;
+ case 'c':
+ db_printf("0x%08x", (insn & 0x00ffffff));
+ break;
+ case 'p':
+ if (insn & 0x00400000)
+ db_printf("spsr");
+ else
+ db_printf("cpsr");
+ case 'B':
+ if (insn & 0x00400000)
+ db_printf("b");
+ break;
+ case 'S':
+ if (insn & 0x00100000)
+ db_printf("s");
+ break;
+ case 'T':
+ if ((insn & 0x01200000) == 0x00200000)
+ db_printf("t");
+ break;
+ case 'P':
+ db_printf("%s", insn_fpaprec(insn));
+ break;
+ case 'R':
+ db_printf("%s", insn_fparnd(insn));
+ break;
+ case 'W':
+ if (insn & (1 << 21))
+ db_printf("!");
+ break;
+ case '#':
+ db_printf("CP #%d", (insn >> 8) & 0x0f);
+ break;
+ case 'y':
+ db_printf("%d, ", (insn >> 20) & 0x0f);
+
+ db_printf("cr%d, cr%d, cr%d", (insn >> 12) & 0x0f, (insn >> 16) & 0x0f,
+ insn & 0x0f);
+
+ db_printf(", %d", (insn >> 5) & 0x07);
+ break;
+ case 'z':
+ db_printf("%d, ", (insn >> 21) & 0x07);
+ db_printf("r%d, cr%d, cr%d", (insn >> 12) & 0x0f, (insn >> 16) & 0x0f,
+ insn & 0x0f);
+
+ if (((insn >> 5) & 0x07) != 0)
+ db_printf(", %d", (insn >> 5) & 0x07);
+ break;
+ default:
+ db_printf("[%02x:c](unknown)", *f_ptr, *f_ptr);
+ break;
+ }
+ ++fmt;
+ if (*(f_ptr+1) > 'A' && *(f_ptr+1) < 'Z')
+ ++f_ptr;
+ else if (*(++f_ptr)) {
+ if (fmt == 1)
+ db_printf("\t");
+ else
+ db_printf(", ");
+ }
+ };
+
+ db_printf("\n");
+
+ return(loc + 4);
+}
+
+
+void
+db_register_shift(insn)
+ u_int insn;
+{
+ db_printf("r%d", (insn & 0x0f));
+ if ((insn & 0x00000ff0) == 0)
+ ;
+ else if ((insn & 0x00000ff0) == 0x00000060)
+ db_printf(", RRX");
+ else {
+ if (insn & 0x10)
+ db_printf(", %s r%d", op2_shift(insn),
+ (insn >> 8) & 0x0f);
+ else
+ db_printf(", %s #%d", op2_shift(insn),
+ (insn >> 7) & 0x1f);
+ }
+}
+
+
+void
+db_print_reglist(insn)
+ u_int insn;
+{
+ int loop;
+ int start;
+ int comma;
+
+ db_printf("{");
+ start = -1;
+ comma = 0;
+
+ for (loop = 0; loop < 17; ++loop) {
+ if (start != -1) {
+ if (!(insn & (1 << loop)) || loop == 16) {
+ if (comma)
+ db_printf(", ");
+ else
+ comma = 1;
+ if (start == loop - 1)
+ db_printf("r%d", start);
+ else
+ db_printf("r%d-r%d", start, loop - 1);
+ start = -1;
+ }
+ } else {
+ if (insn & (1 << loop))
+ start = loop;
+ }
+ }
+ db_printf("}");
+
+ if (insn & (1 << 22))
+ db_printf("^");
+}
+
+void
+db_insn_ldrstr(insn, loc)
+ u_int insn;
+ u_int loc;
+{
+ if (((insn >> 16) & 0x0f) == 15 && (insn & (1 << 21)) == 0
+ && (insn & (1 << 24)) != 0 && (insn & (1 << 25) == 0)) {
+ if (insn & 0x00800000)
+ loc += (insn & 0xffff);
+ else
+ loc -= (insn & 0xffff);
+ db_printsym((db_addr_t)(loc - 8), DB_STGY_ANY);
+ } else {
+ printf("[r%d", (insn >> 16) & 0x0f);
+ printf("%s, ", (insn & (1 << 24)) ? "" : "]");
+
+ if (!(insn & 0x00800000))
+ printf("-");
+ if (insn & (1 << 25))
+ db_register_shift(insn);
+ else
+ printf("#0x%04x", insn & 0xfff);
+ if (insn & (1 << 24))
+ printf("]");
+ }
+}
+
+
+
+#if 0
+
+u_int instruction_msrf(u_int addr, u_int word)
+ {
+ printf("MSR%s\t", opcode_condition(word));
+
+ printf("%s_flg, ", (word & 0x00400000) ? "SPSR" : "CPSR");
+
+ if (word & 0x02000000)
+ printf("#0x%08x", (word & 0xff) << (32 - ((word >> 7) & 0x1e)));
+ else
+ printf("r%d", word &0x0f);
+ return(addr);
+ }
+
+
+u_int instruction_cdt(u_int addr, u_int word)
+ {
+ printf("%s%s%s\t", (word & (1 << 20)) ? "LDC" : "STC",
+ opcode_condition(word), (word & (1 << 22)) ? "L" : "");
+
+ printf("CP #%d, cr%d, ", (word >> 8) & 0x0f, (word >> 12) & 0x0f);
+
+ printf("[r%d", (word >> 16) & 0x0f);
+
+ printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+ if (!(word & (1 << 23)))
+ printf("-");
+
+ printf("#0x%02x", word & 0xff);
+
+ if (word & (1 << 24))
+ printf("]");
+
+ if (word & (1 << 21))
+ printf("!");
+
+ return(addr);
+ }
+
+
+u_int instruction_ldfstf(u_int addr, u_int word)
+ {
+ printf("%s%s%s\t", (word & (1 << 20)) ? "LDF" : "STF",
+ opcode_condition(word), (word & (1 << 22)) ? "L" : "");
+
+ printf("f%d, [r%d", (word >> 12) & 0x07, (word >> 16) & 0x0f);
+
+ printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+ if (!(word & (1 << 23)))
+ printf("-");
+
+ printf("#0x%03x", (word & 0xff) << 2);
+
+ if (word & (1 << 24))
+ printf("]");
+
+ if (word & (1 << 21))
+ printf("!");
+
+ return(addr);
+ }
+
+#endif
+
+/* End of db_disasm.c */
--- /dev/null
+/* $NetBSD: db_interface.c,v 1.5 1996/03/18 21:33:05 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Scott K. Stevens
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
+ */
+
+/*
+ * Interface to new debugger.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/systm.h> /* just for boothowto */
+#include <sys/exec.h>
+
+#include <vm/vm.h>
+
+#include <machine/db_machdep.h>
+#include <machine/katelib.h>
+#include <machine/pte.h>
+#include <ddb/db_command.h>
+#include <ddb/db_variables.h>
+
+static int nil;
+
+int db_access_svc_sp __P((struct db_variable *, db_expr_t *, int));
+
+struct db_variable db_regs[] = {
+ { "spsr", (int *)&DDB_TF->tf_spsr, FCN_NULL, },
+ { "r0", (int *)&DDB_TF->tf_r0, FCN_NULL, },
+ { "r1", (int *)&DDB_TF->tf_r1, FCN_NULL, },
+ { "r2", (int *)&DDB_TF->tf_r2, FCN_NULL, },
+ { "r3", (int *)&DDB_TF->tf_r3, FCN_NULL, },
+ { "r4", (int *)&DDB_TF->tf_r4, FCN_NULL, },
+ { "r5", (int *)&DDB_TF->tf_r5, FCN_NULL, },
+ { "r6", (int *)&DDB_TF->tf_r6, FCN_NULL, },
+ { "r7", (int *)&DDB_TF->tf_r7, FCN_NULL, },
+ { "r8", (int *)&DDB_TF->tf_r8, FCN_NULL, },
+ { "r9", (int *)&DDB_TF->tf_r9, FCN_NULL, },
+ { "r10", (int *)&DDB_TF->tf_r10, FCN_NULL, },
+ { "r11", (int *)&DDB_TF->tf_r11, FCN_NULL, },
+ { "r12", (int *)&DDB_TF->tf_r12, FCN_NULL, },
+ { "usr_sp", (int *)&DDB_TF->tf_usr_sp, FCN_NULL, },
+ { "svc_sp", (int *)&nil, db_access_svc_sp, },
+ { "usr_lr", (int *)&DDB_TF->tf_usr_lr, FCN_NULL, },
+ { "svc_lr", (int *)&DDB_TF->tf_svc_lr, FCN_NULL, },
+ { "pc", (int *)&DDB_TF->tf_pc, FCN_NULL, },
+};
+
+struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+
+extern label_t *db_recover;
+
+int db_active = 0;
+
+int db_access_svc_sp(vp, valp, rw)
+ struct db_variable *vp;
+ db_expr_t *valp;
+ int rw;
+{
+ if(rw == DB_VAR_GET)
+ *valp = get_stackptr(PSR_SVC32_MODE);
+ return(0);
+}
+
+#if 0
+extern char *trap_type[];
+#endif
+
+/*
+ * Received keyboard interrupt sequence.
+ */
+kdb_kbd_trap(tf)
+ struct trapframe *tf;
+{
+ if (db_active == 0 && (boothowto & RB_KDB)) {
+ printf("\n\nkernel: keyboard interrupt\n");
+ kdb_trap(-1, tf);
+ }
+}
+
+/*
+ * kdb_trap - field a TRACE or BPT trap
+ */
+kdb_trap(type, tf)
+ int type;
+ register struct trapframe *tf;
+{
+
+#if 0
+ fb_unblank();
+#endif
+
+ switch (type) {
+ case T_BREAKPOINT: /* breakpoint */
+ case -1: /* keyboard interrupt */
+ break;
+ default:
+ db_printf("kernel: trap");
+ if (db_recover != 0) {
+ db_error("Faulted in DDB; continuing...\n");
+ /*NOTREACHED*/
+ }
+ }
+
+ /* Should switch to kdb`s own stack here. */
+
+ ddb_regs.ddb_tf = *tf;
+ ddb_regs.ddb_tf.tf_pc -= 4;
+
+ db_active++;
+ cnpollc(TRUE);
+ db_trap(type, 0/*code*/);
+ cnpollc(FALSE);
+ db_active--;
+
+ *tf = ddb_regs.ddb_tf;
+
+ return (1);
+}
+
+/*
+ * Read bytes from kernel address space for debugger.
+ */
+void
+db_read_bytes(addr, size, data)
+ vm_offset_t addr;
+ register int size;
+ register char *data;
+{
+ register char *src;
+
+ src = (char *)addr;
+ while (--size >= 0)
+ *data++ = *src++;
+}
+
+#define splpmap() splimp()
+
+static void
+db_write_text(dst, ch)
+ unsigned char *dst;
+ int ch;
+{
+ pt_entry_t *ptep, pte, pteo;
+ int s;
+ vm_offset_t va;
+
+ s = splpmap();
+ va = (unsigned long)dst & (~PGOFSET);
+ ptep = vtopte(va);
+
+ if ((*ptep & L2_MASK) == L2_INVAL) {
+ db_printf(" address 0x%x not a valid page\n", dst);
+ splx(s);
+ return;
+ }
+
+ pteo = ReadWord(ptep);
+ pte = pteo | PT_AP(AP_KRW);
+ WriteWord(ptep, pte);
+ tlbflush();
+
+ *dst = (unsigned char)ch;
+
+ WriteWord(ptep, pteo);
+ tlbflush();
+ splx(s);
+}
+
+/*
+ * Write bytes to kernel address space for debugger.
+ */
+void
+db_write_bytes(addr, size, data)
+ vm_offset_t addr;
+ register int size;
+ register char *data;
+{
+ extern char etext[];
+ register char *dst;
+
+ dst = (char *)addr;
+ while (--size >= 0) {
+ if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS) && (dst < etext))
+ db_write_text(dst, *data);
+ else
+ *dst = *data;
+ dst++, data++;
+ }
+}
+
+void
+Debugger()
+{
+ asm(".word 0xe7ffffff");
+}
+
+void db_show_vmstat_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif));
+void db_show_fs_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif));
+void db_show_vnode_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif));
+
+struct db_command arm32_db_command_table[] = {
+ { "vmstat", db_show_vmstat_cmd, 0, NULL },
+ { "fs", db_show_fs_cmd, 0, NULL },
+ { "vnode", db_show_vnode_cmd, 0, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+int
+db_trapper(addr, inst, frame)
+ u_int addr;
+ u_int inst;
+ trapframe_t *frame;
+{
+/* db_printf("db_trapper\n");*/
+ kdb_trap(1, frame);
+ return(0);
+}
+
+extern u_int esym;
+extern u_int end;
+
+void
+db_machine_init()
+{
+ struct exec *kernexec = (struct exec *)KERNEL_BASE;
+ u_int *ptr;
+ int len;
+
+/*
+ * The boot loader currently loads the kernel with the a.out header still attached.
+ */
+
+ if (kernexec->a_syms == 0) {
+ printf("[No symbol table]\n");
+ } else {
+ esym = (int)&end + kernexec->a_syms + sizeof(int);
+ len = *((u_int *)esym);
+ esym += (len + (sizeof(u_int) - 1)) & ~(sizeof(u_int) - 1);
+ }
+
+ install_coproc_handler(0, db_trapper);
+ db_machine_commands_install(arm32_db_command_table);
+}
+
+
+u_int
+branch_taken(insn, pc, reg, db_regs)
+ u_int insn;
+ u_int pc;
+ u_int reg;
+ db_regs_t *db_regs;
+{
+ int branch;
+
+ branch = ((insn << 2) & 0x03ffffff);
+ if (branch & 0x02000000)
+ branch |= 0xfc000000;
+ return(pc + 8 + branch);
+}
--- /dev/null
+/* $NetBSD: db_machdep.c,v 1.1 1996/03/06 23:08:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+
+void
+db_show_fs_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ int have_addr;
+ db_expr_t count;
+ char *modif;
+{
+ struct vfsops **vfsp;
+ int s;
+
+ s = splhigh();
+
+ db_printf("Registered filesystems (%d)\n", nvfssw);
+
+ for (vfsp = &vfssw[0]; vfsp < &vfssw[nvfssw]; vfsp++) {
+ if (*vfsp == NULL)
+ continue;
+ db_printf(" %s\n", (*vfsp)->vfs_name);
+ }
+ (void)splx(s);
+}
+
+
+/*
+ * Print out a description of a vnode.
+ * Some parts borrowed from kern/vfs_subr.c
+ */
+
+static char *typename[] =
+ { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
+
+void
+db_show_vnode_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ int have_addr;
+ db_expr_t count;
+ char *modif;
+{
+ char buf[64];
+ struct vnode *vp;
+
+ if (!have_addr) {
+ db_printf("vnode address must be specified\n");
+ return;
+ }
+
+ vp = (struct vnode *)addr;
+
+/* Decode the one argument */
+
+ db_printf("vp : %08x\n", (u_int)vp);
+ db_printf("vp->v_type = %d\n", vp->v_type);
+ db_printf("vp->v_flag = %ld\n", vp->v_flag);
+ db_printf("vp->v_numoutput = %ld\n", vp->v_numoutput);
+
+ db_printf("type %s, usecount %d, writecount %d, refcount %d,",
+ typename[vp->v_type], vp->v_usecount, vp->v_writecount,
+ vp->v_holdcnt);
+ buf[0] = '\0';
+ if (vp->v_flag & VROOT)
+ strcat(buf, "|VROOT");
+ if (vp->v_flag & VTEXT)
+ strcat(buf, "|VTEXT");
+ if (vp->v_flag & VSYSTEM)
+ strcat(buf, "|VSYSTEM");
+ if (vp->v_flag & VXLOCK)
+ strcat(buf, "|VXLOCK");
+ if (vp->v_flag & VXWANT)
+ strcat(buf, "|VXWANT");
+ if (vp->v_flag & VBWAIT)
+ strcat(buf, "|VBWAIT");
+ if (vp->v_flag & VALIASED)
+ strcat(buf, "|VALIASED");
+ if (buf[0] != '\0')
+ db_printf(" flags (%s)", &buf[1]);
+ db_printf("\n");
+ if (vp->v_data != NULL) {
+ db_printf("data=%08x\n", vp->v_data);
+ }
+}
+
+
+void
+db_show_vmstat_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ int have_addr;
+ db_expr_t count;
+ char *modif;
+{
+ struct vmmeter sum;
+
+ sum = cnt;
+ db_printf("%9u cpu context switches\n", sum.v_swtch);
+ db_printf("%9u device interrupts\n", sum.v_intr);
+ db_printf("%9u software interrupts\n", sum.v_soft);
+ db_printf("%9u traps\n", sum.v_trap);
+ db_printf("%9u system calls\n", sum.v_syscall);
+ db_printf("%9u total faults taken\n", sum.v_faults);
+ db_printf("%9u swap ins\n", sum.v_swpin);
+ db_printf("%9u swap outs\n", sum.v_swpout);
+ db_printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
+ db_printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
+ db_printf("%9u page ins\n", sum.v_pageins);
+ db_printf("%9u page outs\n", sum.v_pageouts);
+ db_printf("%9u pages paged in\n", sum.v_pgpgin);
+ db_printf("%9u pages paged out\n", sum.v_pgpgout);
+ db_printf("%9u pages reactivated\n", sum.v_reactivated);
+ db_printf("%9u intransit blocking page faults\n", sum.v_intrans);
+ db_printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
+ db_printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
+ db_printf("%9u pages examined by the clock daemon\n", sum.v_scan);
+ db_printf("%9u revolutions of the clock hand\n", sum.v_rev);
+ db_printf("%9u VM object cache lookups\n", sum.v_lookups);
+ db_printf("%9u VM object hits\n", sum.v_hits);
+ db_printf("%9u total VM faults taken\n", sum.v_vm_faults);
+ db_printf("%9u copy-on-write faults\n", sum.v_cow_faults);
+ db_printf("%9u pages freed by daemon\n", sum.v_dfree);
+ db_printf("%9u pages freed by exiting processes\n", sum.v_pfree);
+ db_printf("%9u pages free\n", sum.v_free_count);
+ db_printf("%9u pages wired down\n", sum.v_wire_count);
+ db_printf("%9u pages active\n", sum.v_active_count);
+ db_printf("%9u pages inactive\n", sum.v_inactive_count);
+ db_printf("%9u bytes per page\n", sum.v_page_size);
+}
--- /dev/null
+/* $NetBSD: db_trace.c,v 1.2 1996/03/06 22:49:51 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Scott K. Stevens
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+
+#define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK)
+
+void
+db_stack_trace_cmd(addr, have_addr, count, modif)
+ db_expr_t addr;
+ int have_addr;
+ db_expr_t count;
+ char *modif;
+{
+ struct frame *frame;
+ boolean_t kernel_only = TRUE;
+
+ {
+ register char c, *cp = modif;
+ while ((c = *cp++) != 0)
+ if (c == 'u')
+ kernel_only = FALSE;
+ }
+
+ if (count == -1)
+ count = 65535;
+
+/*
+ * The frame pointer points to the top word of the stack frame so we
+ * need to adjust it by sizeof(struct frame) - sizeof(u_int))
+ * to get the address of the start of the frame structure.
+ */
+
+ if (!have_addr)
+ frame = (struct frame *)(DDB_TF->tf_r11 - (sizeof(struct frame) - sizeof(u_int)));
+ else
+ frame = (struct frame *)(addr - (sizeof(struct frame) - sizeof(u_int)));
+
+ while (count--) {
+ int i;
+ db_expr_t offset;
+ db_sym_t sym;
+ char *name;
+ db_addr_t pc;
+
+/* db_printf("fp=%08x: fp=%08x sp=%08x lr=%08x pc=%08x\n", (u_int)frame, frame->fr_fp, frame->fr_sp, frame->fr_lr, frame->fr_pc);*/
+
+ pc = frame->fr_pc;
+ if (!INKERNEL(pc))
+ break;
+
+ db_find_sym_and_offset(pc, &name, &offset);
+ if (name == NULL)
+ name = "?";
+
+ db_printf("%s(", name);
+
+ /*
+ * Switch to next frame up
+ */
+ frame = (struct frame *)(frame->fr_fp - (sizeof(struct frame) - sizeof(u_int)));
+
+ db_printsym(pc, DB_STGY_PROC);
+ db_printf(")");
+ db_printf("\n");
+ if (frame == NULL)
+ break;
+ }
+}
--- /dev/null
+/* $NetBSD: debug.c,v 1.2 1996/03/08 20:14:48 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Melvin Tang-Richardson (Nut)
+ * Copyright (c) 1994 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * debug.c
+ *
+ * Debugging functions
+ *
+ * Created : 11/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/callout.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+int
+debug_count_processes_on_q(queue)
+ int queue;
+{
+ struct proc *lastproc, *queue_head;
+ int counter;
+ int s;
+
+ counter = 0;
+ s = splhigh();
+ queue_head=(struct proc *)&qs[queue];
+ for (lastproc=qs[queue].ph_link;lastproc!=queue_head;lastproc=lastproc->p_forw) {
+ if (lastproc != queue_head)
+ printf("Process queue=%8x proc=%08x p_addr=%8x, comm=%s\n",
+ queue, (u_int) lastproc, (u_int) lastproc->p_addr,
+ lastproc->p_comm);
+ counter++;
+ }
+ (void)splx(s);
+ return(counter);
+}
+
+void
+debug_show_q_details()
+{
+ int counter=0;
+ int s;
+
+ s = splhigh();
+ for (counter=0; counter<32; counter++ )
+ debug_count_processes_on_q(counter);
+
+ if (whichqs == 0)
+ printf("queues empty\n");
+ (void)splx(s);
+}
+
+void
+debug_show_all_procs(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int np;
+ struct proc *ap, *p, *pp;
+ int s;
+
+ s = splhigh();
+
+ np = nprocs;
+ p = ap = (struct proc *)allproc.lh_first;
+ if (argc > 1)
+ printf(" pid proc addr map pcb pmap comm wchan\n");
+ else
+ printf(" pid proc addr uid ppid pgrp flag stat comm cputime \n");
+ while (--np >= 0) {
+ pp = p->p_pptr;
+ if (pp == 0)
+ pp = p;
+ if (p->p_stat) {
+ if (argc > 1)
+ printf("%5d %08x %08x %08x %08x %08x %12s ",
+ p->p_pid, (u_int) ap, (u_int)p->p_addr,
+ (u_int) p->p_vmspace,
+ (u_int) &p->p_addr->u_pcb, (p->p_vmspace ? (u_int)&p->p_vmspace->vm_pmap : 0),
+ ((p->p_comm == 0) ? "..." : p->p_comm));
+ else
+ printf("%5d %08x %08x %5d %5d %5d %08x %d %12s %5u.%02d ",
+ p->p_pid, (u_int) ap, (u_int) p->p_addr,
+ p->p_cred->p_ruid,
+ pp->p_pid, p->p_pgrp->pg_id, p->p_flag,
+ p->p_stat, p->p_comm,
+ (u_int)p->p_rtime.tv_sec,
+ (u_int)p->p_rtime.tv_usec / 10000);
+ if (p->p_wchan && argc > 1) {
+ if (p->p_wmesg)
+ printf("%12s ", p->p_wmesg);
+ printf("%x", (u_int)p->p_wchan);
+ }
+ printf("\n");
+ }
+ ap = p->p_list.le_next;
+ if (ap == 0 && np > 0)
+ ap = (struct proc*)zombproc.lh_first;
+ p = ap;
+ }
+ (void)splx(s);
+}
+
+
+void
+debug_show_callout(argc, argv)
+ int argc;
+ char *argv[];
+{
+ register struct callout *p1;
+ register int cum;
+ register int s;
+ register int t;
+
+ s = splhigh();
+ printf(" cum ticks func arg\n");
+ for (cum = 0, p1 = calltodo.c_next; p1; p1 = p1->c_next) {
+ t = p1->c_time;
+ if (t > 0)
+ cum += t;
+ printf("%9d %9d %08x %08x\n", cum, t, (u_int) p1->c_func,
+ (u_int) p1->c_arg);
+ }
+ (void)splx(s);
+}
+
+void
+debug_show_fs(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct vfsops **vfsp;
+ int s;
+
+ s = splhigh();
+
+ printf("Registered filesystems (%d)\n", nvfssw);
+
+ for (vfsp = &vfssw[0]; vfsp < &vfssw[nvfssw]; vfsp++) {
+ if (*vfsp == NULL)
+ continue;
+ printf(" %s\n", (*vfsp)->vfs_name);
+ }
+ (void)splx(s);
+}
+
+
+void
+debug_show_vm_map(map, text)
+ vm_map_t map;
+ char *text;
+{
+ vm_map_entry_t mapentry;
+ int s;
+
+ s = splhigh();
+
+ printf("vm_map dump : %s\n", text);
+
+ mapentry = &map->header;
+
+ do {
+ printf("vm_map_entry: start = %08x end = %08x\n",
+ (u_int) mapentry->start, (u_int) mapentry->end);
+ mapentry = mapentry->next;
+ } while (mapentry != &map->header);
+ (void)splx(s);
+}
+
+
+void
+debug_show_pmap(pmap)
+ pmap_t pmap;
+{
+ u_int loop;
+ u_int loop1;
+ u_int start;
+ pt_entry_t *pt;
+ pd_entry_t *pd;
+ int s;
+
+ s = splhigh();
+
+ pd = (pd_entry_t *)pmap;
+
+ printf("pdir=%08x\n", (u_int) pd);
+ for (loop = 0; loop < 4096; ++loop) {
+ if (pd[loop] == 0)
+ continue;
+ printf("%08x : %08x\n", loop * 1024*1024, pd[loop]);
+ if ((pd[loop] & 0xff) == 0x11) {
+ pt = (pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+ + loop * 1024);
+ loop1 = 0;
+ while (loop1 < 256) {
+ if (pt[loop1]) {
+ start = loop1;
+ ++loop1;
+ while (loop1 < 256 && pt[loop1])
+ ++loop1;
+ printf(" %08x -> %08x\n",
+ loop * 1024*1024 + start * 4096,
+ loop * 1024*1024 + loop1 * 4096 - 1);
+ }
+ ++loop1;
+ }
+ }
+ }
+ (void)splx(s);
+}
+
+/* End of debug.c */
--- /dev/null
+/* $NetBSD: disassem.c,v 1.3 1996/03/16 00:13:09 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * disassem.c
+ *
+ * Debug / Monitor disassembler
+ *
+ * Created : 09/10/94
+ */
+
+/* Include standard header files */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/* Local header files */
+
+#include <machine/katelib.h>
+
+typedef u_int (*instruction_decoder) (u_int addr, u_int word);
+
+typedef struct _opcodes {
+ u_int mask;
+ u_int pattern;
+ u_int colour;
+ instruction_decoder decoder;
+} opcodes_struct;
+
+u_int instruction_swi(u_int addr, u_int word);
+u_int instruction_branch(u_int addr, u_int word);
+u_int instruction_mul(u_int addr, u_int word);
+u_int instruction_mla(u_int addr, u_int word);
+u_int instruction_ldrstr(u_int addr, u_int word);
+u_int instruction_ldmstm(u_int addr, u_int word);
+u_int instruction_dataproc(u_int addr, u_int word);
+u_int instruction_swap(u_int addr, u_int word);
+u_int instruction_mrs(u_int addr, u_int word);
+u_int instruction_msr(u_int addr, u_int word);
+u_int instruction_msrf(u_int addr, u_int word);
+u_int instruction_mrcmcr(u_int addr, u_int word);
+u_int instruction_cdp(u_int addr, u_int word);
+u_int instruction_cdt(u_int addr, u_int word);
+u_int instruction_fpabinop(u_int addr, u_int word);
+u_int instruction_fpaunop(u_int addr, u_int word);
+u_int instruction_ldfstf(u_int addr, u_int word);
+
+/* Declare global variables */
+
+opcodes_struct opcodes[] = {
+ { 0x0f000000, 0x0f000000, 7, instruction_swi },
+ { 0x0e000000, 0x0a000000, 7, instruction_branch },
+ { 0x0fe000f0, 0x00000090, 7, instruction_mul },
+ { 0x0fe000f0, 0x00200090, 7, instruction_mla },
+ { 0x0e000000, 0x04000000, 7, instruction_ldrstr },
+ { 0x0c000010, 0x04000000, 7, instruction_ldrstr },
+ { 0x0e000000, 0x08000000, 6, instruction_ldmstm },
+ { 0x0FB00FF0, 0x01000090, 7, instruction_swap },
+ { 0x0FBF0FFF, 0x010F0000, 1, instruction_mrs },
+ { 0x0DBFFFF0, 0x0129F000, 1, instruction_msr },
+ { 0x0DBFFFF0, 0x0128F000, 1, instruction_msrf },
+ { 0x0C000000, 0x00000000, 7, instruction_dataproc },
+ { 0x0F008F10, 0x0E000100, 3, instruction_fpabinop },
+ { 0x0F008F10, 0x0E008100, 3, instruction_fpaunop },
+ { 0x0E000F00, 0x0C000100, 3, instruction_ldfstf },
+ { 0x0F000010, 0x0E000010, 2, instruction_mrcmcr },
+ { 0x0F000010, 0x0E000000, 2, instruction_cdp },
+ { 0x0E000000, 0x0C000000, 2, instruction_cdt },
+ { 0x00000000, 0x00000000, 0, NULL }
+};
+
+char *opcode_conditions[] = {
+ "EQ",
+ "NE",
+ "CS",
+ "CC",
+ "MI",
+ "PL",
+ "VS",
+ "VC",
+ "HI",
+ "LS",
+ "GE",
+ "LT",
+ "GT",
+ "LE",
+ "",
+ "NV"
+};
+
+char *opcode_data_procs[] = {
+ "AND",
+ "EOR",
+ "SUB",
+ "RSB",
+ "ADD",
+ "ADC",
+ "SBC",
+ "RSC",
+ "TST",
+ "TEQ",
+ "CMP",
+ "CMN",
+ "ORR",
+ "MOV",
+ "BIC",
+ "MVN"
+};
+
+char *opcode_shifts[] = {
+ "LSL",
+ "LSR",
+ "ASR",
+ "ROR"
+};
+
+char *opcode_block_transfers[] = {
+ "DA",
+ "IA",
+ "DB",
+ "IB"
+};
+
+char *opcode_stack_block_transfers[] = {
+ "FA",
+ "EA",
+ "FD",
+ "FA"
+};
+
+char *opcode_fpabinops[] = {
+ "ADF",
+ "MUF",
+ "SUF",
+ "RSF",
+ "DVF",
+ "RDF",
+ "POW",
+ "RPW",
+ "RMF",
+ "FML",
+ "FDV",
+ "FRD",
+ "POL",
+ "???",
+ "???",
+ "???",
+ "???"
+};
+
+char *opcode_fpaunops[] = {
+ "MVF",
+ "MNF",
+ "ABS",
+ "RND",
+ "SQT",
+ "LOG",
+ "LGN",
+ "EXP",
+ "SIN",
+ "COS",
+ "TAN",
+ "ASN",
+ "ACS",
+ "ATN",
+ "???",
+ "???",
+ "???"
+};
+
+char *opcode_fpaconstants[] = {
+ "0.0",
+ "1.0",
+ "2.0",
+ "3.0",
+ "4.0",
+ "5.0",
+ "0.5",
+ "10.0"
+};
+
+char *opcode_fpa_rounding[] = {
+ "",
+ "P",
+ "M",
+ "Z"
+};
+
+char *opcode_fpa_precision[] = {
+ "S",
+ "D",
+ "E",
+ "P"
+};
+
+#define opcode_condition(x) opcode_conditions[x >> 28]
+
+#define opcode_s(x) ((x & 0x00100000) ? "S" : "")
+
+#define opcode_b(x) ((x & 0x00400000) ? "B" : "")
+
+#define opcode_t(x) ((x & 0x01200000) == 0x00200000 ? "T" : "")
+
+#define opcode_dataproc(x) opcode_data_procs[(x >> 21) & 0x0f]
+
+#define opcode_shift(x) opcode_shifts[(x >> 5) & 3]
+
+#define opcode_blktrans(x) opcode_block_transfers[(x >> 23) & 3]
+
+#define opcode_stkblktrans(x) opcode_stack_block_transfers[(x >> 23) & 3]
+
+#define opcode_fpabinop(x) opcode_fpabinops[(x >> 20) & 0x0f]
+
+#define opcode_fpaunop(x) opcode_fpaunops[(x >> 20) & 0x0f]
+
+#define opcode_fpaimm(x) opcode_fpaconstants[x & 0x07]
+
+#define opcode_fparnd(x) opcode_fpa_rounding[(x >> 5) & 0x03]
+
+#define opcode_fpaprec(x) opcode_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 3]
+
+/* Declare external variables */
+
+extern caddr_t shell_ident;
+
+/* Local function prototypes */
+
+u_int disassemble(u_char *addr);
+
+/* Now for the main code */
+
+void
+printascii(byte)
+ int byte;
+{
+ if (byte < 0x20)
+ printf("\x1b[31m%c\x1b[0m", byte + '@');
+ else if (byte == 0x7f)
+ printf("\x1b[31m?\x1b[0m");
+ else
+ printf("%c", byte);
+}
+
+
+u_int disassemble(u_char *addr)
+ {
+ int loop;
+ u_int word;
+ u_int result = 0;
+
+ printf("%08x : ", (u_int)addr);
+
+ word = *((u_int *)addr);
+
+ for (loop = 0; loop < 4; ++loop)
+ printascii(addr[loop]);
+
+ printf(" : %08x : ", word);
+
+ loop = 0;
+
+ while (opcodes[loop].mask != 0)
+ {
+ if ((word & opcodes[loop].mask) == opcodes[loop].pattern)
+ {
+ printf("\x1b[3%dm", opcodes[loop].colour);
+ result = (*opcodes[loop].decoder)((u_int )addr, word);
+ printf("\x1b[0m");
+ break;
+ }
+ ++loop;
+ }
+
+ if (opcodes[loop].mask == 0)
+ printf("Undefined instruction");
+
+ printf("\n\r");
+ return(result);
+ }
+
+
+u_int instruction_swi(u_int addr, u_int word)
+ {
+ printf("SWI%s\t0x%08x", opcode_condition(word), (word & 0x00ffffff));
+ return(addr);
+ }
+
+
+u_int instruction_branch(u_int addr, u_int word)
+ {
+ u_int branch;
+
+ branch = ((word << 2) & 0x03ffffff);
+ if (branch & 0x02000000)
+ branch |= 0xfc000000;
+
+ branch += addr + 8;
+
+ if (word & 0x01000000)
+ printf("BL%s\t0x%08x", opcode_condition(word), branch);
+ else
+ printf("B%s\t0x%08x", opcode_condition(word), branch);
+
+ return(branch);
+ }
+
+
+u_int instruction_mul(u_int addr, u_int word)
+ {
+ printf("MUL%s%s\t", opcode_condition(word), opcode_s(word));
+
+ printf("r%d, r%d, r%d", (word >> 16) & 0x0f, word & 0x0f,
+ (word >> 8) & 0x0f);
+ return(addr);
+ }
+
+
+u_int instruction_mla(u_int addr, u_int word)
+ {
+ printf("MLA%s%s\t", opcode_condition(word), opcode_s(word));
+
+ printf("r%d, r%d, r%d, r%d", (word >> 16) & 0x0f, word & 0x0f,
+ (word >> 8) & 0x0f, (word >> 12) & 0x0f);
+ return(addr);
+ }
+
+
+void register_shift(u_int word)
+ {
+ printf("r%d", (word & 0x0f));
+ if ((word & 0x00000ff0) == 0)
+ ;
+ else if ((word & 0x00000ff0) == 0x00000060)
+ printf(", RRX");
+ else
+ {
+ if (word & 0x10)
+ {
+ printf(", %s r%d", opcode_shift(word), (word >> 8) & 0x0f);
+ }
+ else
+ {
+ printf(", %s #%d", opcode_shift(word), (word >> 7) & 0x1f);
+ }
+ }
+ }
+
+
+u_int instruction_ldrstr(u_int addr, u_int word)
+ {
+ printf("%s%s%s%s\t", (word & 0x00100000) ? "LDR" : "STR",
+ opcode_condition(word), opcode_b(word), opcode_t(word));
+
+ printf("r%d, ", (word >> 12) & 0x0f);
+
+ if (((word >> 16) & 0x0f) == 16)
+ {
+/* u_int location;
+
+ location = addr + 8;
+
+ addr = */
+ }
+ else
+ {
+ printf("[r%d", (word >> 16) & 0x0f);
+
+ printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+ if (!(word & 0x00800000))
+ printf("-");
+
+ if (word & (1 << 25))
+ register_shift(word);
+ else
+ printf("#0x%04x", word & 0xfff);
+
+ if (word & (1 << 24))
+ printf("]");
+
+ if (word & (1 << 21))
+ printf("!");
+ }
+
+ return(addr);
+ }
+
+
+u_int instruction_ldmstm(u_int addr, u_int word)
+ {
+ int loop;
+ int start;
+
+ printf("%s%s%s\t", (word & 0x00100000) ? "LDM" : "STM",
+ opcode_condition(word), opcode_blktrans(word));
+
+ printf("r%d", (word >> 16) & 0x0f);
+
+ if (word & (1 << 21))
+ printf("!");
+
+ printf(", {");
+
+ start = -1;
+
+ for (loop = 0; loop < 17; ++loop)
+ {
+ if (start != -1)
+ {
+ if (!(word & (1 << loop)) || loop == 16)
+ {
+ if (start == loop - 1)
+ printf("r%d, ", start);
+ else
+ printf("r%d-r%d, ", start, loop - 1);
+ start = -1;
+ }
+ }
+ else
+ {
+ if (word & (1 << loop))
+ start = loop;
+ }
+
+ }
+ printf("\x7f\x7f}");
+
+ if (word & (1 << 22))
+ printf("^");
+ return(addr);
+ }
+
+
+u_int instruction_dataproc(u_int addr, u_int word)
+ {
+ if ((word & 0x01800000) == 0x01000000)
+ word = word & ~(1<<20);
+
+ printf("%s%s%s\t", opcode_dataproc(word), opcode_condition(word),
+ opcode_s(word));
+
+ if ((word & 0x01800000) != 0x01000000)
+ printf("r%d, ", (word >> 12) & 0x0f);
+
+ if ((word & 0x01a00000) != 0x01a00000)
+ printf("r%d, ", (word >> 16) & 0x0f);
+
+ if (word & 0x02000000)
+ {
+ printf("#&%08x", (word & 0xff) << (((word >> 7) & 0x1e)));
+ }
+ else
+ {
+ register_shift(word);
+ }
+ return(addr);
+ }
+
+
+u_int instruction_swap(u_int addr, u_int word)
+ {
+ printf("SWP%s%s\t", opcode_condition(word), opcode_b(word));
+
+ printf("r%d, r%d, [r%d]", (word >> 12) & 0x0f, (word & 0x0f),
+ (word >> 16) & 0x0f);
+ return(addr);
+ }
+
+
+u_int instruction_mrs(u_int addr, u_int word)
+ {
+ printf("MRS%s\tr%d, ", opcode_condition(word), (word >> 12) & 0x0f);
+
+ printf("%s", (word & 0x00400000) ? "SPSR" : "CPSR");
+ return(addr);
+ }
+
+
+u_int instruction_msr(u_int addr, u_int word)
+ {
+ printf("MSR%s\t", opcode_condition(word));
+
+ printf("%s, r%d", (word & 0x00400000) ? "SPSR" : "CPSR", word & 0x0f);
+
+ return(addr);
+ }
+
+
+u_int instruction_msrf(u_int addr, u_int word)
+ {
+ printf("MSR%s\t", opcode_condition(word));
+
+ printf("%s_flg, ", (word & 0x00400000) ? "SPSR" : "CPSR");
+
+ if (word & 0x02000000)
+ printf("#0x%08x", (word & 0xff) << (32 - ((word >> 7) & 0x1e)));
+ else
+ printf("r%d", word &0x0f);
+ return(addr);
+ }
+
+
+u_int instruction_mrcmcr(u_int addr, u_int word)
+ {
+ printf("%s%s\t", (word & (1 << 20)) ? "MRC" : "MCR",
+ opcode_condition(word));
+
+ printf("CP #%d, %d, ", (word >> 8) & 0x0f, (word >> 21) & 0x07);
+
+ printf("r%d, cr%d, cr%d", (word >> 12) & 0x0f, (word >> 16) & 0x0f,
+ word & 0x0f);
+
+ if (((word >> 5) & 0x07) != 0)
+ printf(", %d", (word >> 5) & 0x07);
+
+ return(addr);
+ }
+
+
+u_int instruction_cdp(u_int addr, u_int word)
+ {
+ printf("CDP%s\t", opcode_condition(word));
+
+ printf("CP #%d, %d, ", (word >> 8) & 0x0f, (word >> 20) & 0x0f);
+
+ printf("cr%d, cr%d, cr%d", (word >> 12) & 0x0f, (word >> 16) & 0x0f,
+ word & 0x0f);
+
+ printf(", %d", (word >> 5) & 0x07);
+
+ return(addr);
+ }
+
+
+u_int instruction_cdt(u_int addr, u_int word)
+ {
+ printf("%s%s%s\t", (word & (1 << 20)) ? "LDC" : "STC",
+ opcode_condition(word), (word & (1 << 22)) ? "L" : "");
+
+ printf("CP #%d, cr%d, ", (word >> 8) & 0x0f, (word >> 12) & 0x0f);
+
+ printf("[r%d", (word >> 16) & 0x0f);
+
+ printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+ if (!(word & (1 << 23)))
+ printf("-");
+
+ printf("#0x%02x", word & 0xff);
+
+ if (word & (1 << 24))
+ printf("]");
+
+ if (word & (1 << 21))
+ printf("!");
+
+ return(addr);
+ }
+
+
+u_int instruction_fpabinop(u_int addr, u_int word)
+ {
+ printf("%s%s%s%s\t", opcode_fpabinop(word), opcode_condition(word),
+ opcode_fpaprec(word), opcode_fparnd(word));
+
+ printf("f%d, f%d, ", (word >> 12) & 0x07, (word >> 16) & 0x07);
+
+ if (word & (1 << 3))
+ printf("#%s", opcode_fpaimm(word));
+ else
+ printf("f%d", word & 0x07);
+
+ return(addr);
+ }
+
+
+u_int instruction_fpaunop(u_int addr, u_int word)
+ {
+ printf("%s%s%s%s\t", opcode_fpaunop(word), opcode_condition(word),
+ opcode_fpaprec(word), opcode_fparnd(word));
+
+ printf("f%d, ", (word >> 12) & 0x07);
+
+ if (word & (1 << 3))
+ printf("#%s", opcode_fpaimm(word));
+ else
+ printf("f%d", word & 0x07);
+
+ return(addr);
+ }
+
+
+u_int instruction_ldfstf(u_int addr, u_int word)
+ {
+ printf("%s%s%s\t", (word & (1 << 20)) ? "LDF" : "STF",
+ opcode_condition(word), (word & (1 << 22)) ? "L" : "");
+
+ printf("f%d, [r%d", (word >> 12) & 0x07, (word >> 16) & 0x0f);
+
+ printf("%s, ", (word & (1 << 24)) ? "" : "]");
+
+ if (!(word & (1 << 23)))
+ printf("-");
+
+ printf("#0x%03x", (word & 0xff) << 2);
+
+ if (word & (1 << 24))
+ printf("]");
+
+ if (word & (1 << 21))
+ printf("!");
+
+ return(addr);
+ }
+
+/* End of disassem.c */
--- /dev/null
+/* $NetBSD: disksubr.c,v 1.2 1996/03/06 22:43:11 mark Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * Copyright (c) 1995 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/dkbad.h>
+#include <sys/disklabel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/disk.h>
+
+#define b_cylin b_resid
+
+/* int filecore_checksum(char *bootblock)
+ *
+ * Calculates the filecore boot block checksum. This is used to validate
+ * a filecore boot block on the disc. If a boot block is validated then
+ * it is used to locate the partition table. If the boot block is not
+ * validated, it is assumed that the whole disc is RiscBSD.
+ */
+
+/*
+ * This can be coded better using add with carry but as it is used rarely
+ * there is not much point writing it in assembly.
+ */
+
+u_int
+filecore_checksum(bootblock)
+ u_char *bootblock;
+{
+ register u_int sum;
+ register u_int loop;
+
+/* A boot block of zero has a zero checksum - clever thinking Acorn, NOT ! */
+
+ sum = 0;
+
+ for (loop = 0; loop < 512; ++loop)
+ sum += bootblock[loop];
+
+/* If the whole block is zero then it is invalid */
+
+ if (sum == 0) return(0xffff);
+
+ sum = 0;
+
+ for (loop = 0; loop < 511; ++loop) {
+ sum += bootblock[loop];
+ if (sum > 255)
+ sum -= 255;
+ }
+
+ return(sum);
+}
+
+
+/*
+ * Attempt to read a disk label from a device
+ * using the indicated stategy routine.
+ * The label must be partly set up before this:
+ * secpercyl, secsize and anything required for a block i/o read
+ * operation in the driver's strategy/start routines
+ * must be filled in before calling us.
+ *
+ * If dos partition table requested, attempt to load it and
+ * find disklabel inside a DOS partition. Also, if bad block
+ * table needed, attempt to extract it as well. Return buffer
+ * for use in signalling errors if requested.
+ *
+ * Returns null on success and an error string on failure.
+ */
+
+char *
+readdisklabel(dev, strat, lp, osdep)
+ dev_t dev;
+ void (*strat)();
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ struct riscbsd_partition *rp = osdep->partitions;
+ struct dkbad *bdp = &osdep->bad;
+ register struct buf *bp;
+ struct disklabel *dlp;
+ char *msg = NULL;
+ int cyl, riscbsdpartoff, i;
+
+/* printf("Reading disclabel for %04x\n", dev);*/
+
+/* minimal requirements for archtypal disk label */
+
+ if (lp->d_secsize == 0)
+ lp->d_secsize = DEV_BSIZE;
+
+ if (lp->d_secperunit == 0)
+ lp->d_secperunit = 0x1fffffff;
+
+ lp->d_npartitions = MAXPARTITIONS;
+ for (i = 0; i < MAXPARTITIONS; i++) {
+ if (i == RAW_PART) continue;
+ lp->d_partitions[i].p_offset = 0;
+ lp->d_partitions[i].p_fstype = FS_UNUSED;
+ lp->d_partitions[i].p_size = 0;
+ }
+
+ if (lp->d_partitions[RAW_PART].p_size == 0) {
+ lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
+ lp->d_partitions[RAW_PART].p_offset = 0;
+ lp->d_partitions[RAW_PART].p_size = 0x1fffffff;
+ }
+
+/* obtain buffer to probe drive with */
+
+ bp = geteblk((int)lp->d_secsize);
+
+/* request no partition relocation by driver on I/O operations */
+
+ bp->b_dev = dev;
+
+/* do riscbsd partitions in the process of getting disklabel? */
+
+ riscbsdpartoff = 0;
+ cyl = LABELSECTOR / lp->d_secpercyl;
+
+ if (rp) {
+ struct filecore_bootblock *bb;
+ int heads;
+ int sectors;
+
+/* read the filecore boot block */
+
+/* printf("readdisclabel: Reading boot block\n");*/
+
+ bp->b_blkno = FILECORE_BOOT_SECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
+ (*strat)(bp);
+
+/* if successful, validate boot block and locate parition table */
+
+ if (biowait(bp)) {
+ msg = "filecore boot block I/O error";
+ goto done;
+ }
+
+ bb = (struct filecore_bootblock *)bp->b_data;
+
+/* Validate boot block */
+
+ if (bb->checksum != filecore_checksum((u_char *)bb)) {
+
+/* Invalid boot block so lets assume the entire disc is RiscBSD */
+
+/* printf("readdisklabel: Invalid filecore boot block (incorrect checksum)\n");*/
+ goto readlabel;
+ }
+
+/* Get some information from the boot block */
+
+ cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8);
+
+ heads = bb->heads;
+ sectors = bb->secspertrack;
+
+/* Do we have a RiscBSD partition table ? */
+
+ if (bb->partition_type == PARTITION_FORMAT_RISCBSD) {
+/* printf("heads = %d nsectors = %d\n", heads, sectors);*/
+
+ riscbsdpartoff = cyl * heads * sectors;
+ } else if (bb->partition_type == PARTITION_FORMAT_RISCIX) {
+ struct riscix_partition_table *rpt;
+ int loop;
+
+/* We have a RISCiX partition table :-( groan */
+
+/* Ok read the RISCiX partition table and see if there is a RiscBSD partition */
+
+ bp->b_blkno = cyl * heads * sectors;
+ printf("Found RiscIX partition table @ %08x\n", bp->b_blkno);
+ bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+
+/* if successful, locate disk label within block and validate */
+
+ if (biowait(bp)) {
+ msg = "disk label I/O error";
+ goto done;
+ }
+
+ rpt = (struct riscix_partition_table *)bp->b_data;
+/* for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop)
+ printf("p%d: %16s %08x %08x %08x\n", loop,
+ rpt->partitions[loop].rp_name,
+ rpt->partitions[loop].rp_start,
+ rpt->partitions[loop].rp_length,
+ rpt->partitions[loop].rp_type);
+*/
+ for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) {
+ if (strcmp(rpt->partitions[loop].rp_name, "RiscBSD") == 0
+ || strcmp(rpt->partitions[loop].rp_name, "NetBSD") == 0) {
+ riscbsdpartoff = rpt->partitions[loop].rp_start;
+ break;
+ }
+ }
+ if (loop == NRISCIX_PARTITIONS) {
+ msg = "RiscBSD partition identifier string not found.";
+ goto done;
+ }
+ } else {
+ msg = "Invalid partition format";
+ goto done;
+ }
+ }
+
+/* next, dig out disk label */
+
+readlabel:
+/* printf("Reading disklabel addr=%08x\n", riscbsdpartoff * DEV_BSIZE);*/
+
+ bp->b_blkno = riscbsdpartoff + LABELSECTOR;
+ bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+
+/* if successful, locate disk label within block and validate */
+
+ if (biowait(bp)) {
+ msg = "disk label I/O error";
+ goto done;
+ }
+ for (dlp = (struct disklabel *)bp->b_data;
+ dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp));
+ dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+ if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
+ if (msg == NULL)
+ msg = "no disk label";
+ } else if (dlp->d_npartitions > MAXPARTITIONS ||
+ dkcksum(dlp) != 0)
+ msg = "disk label corrupted";
+ else {
+ *lp = *dlp;
+ msg = NULL;
+ break;
+ }
+ }
+
+ if (msg)
+ goto done;
+
+ /* obtain bad sector table if requested and present */
+ if (bdp && (lp->d_flags & D_BADSECT)) {
+ struct dkbad *db;
+
+ i = 0;
+ do {
+ /* read a bad sector table */
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
+ if (lp->d_secsize > DEV_BSIZE)
+ bp->b_blkno *= lp->d_secsize / DEV_BSIZE;
+ else
+ bp->b_blkno /= DEV_BSIZE / lp->d_secsize;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_cylin = lp->d_ncylinders - 1;
+ (*strat)(bp);
+
+ /* if successful, validate, otherwise try another */
+ if (biowait(bp)) {
+ msg = "bad sector table I/O error";
+ } else {
+ db = (struct dkbad *)(bp->b_data);
+#define DKBAD_MAGIC 0x4321
+ if (db->bt_mbz == 0
+ && db->bt_flag == DKBAD_MAGIC) {
+ msg = NULL;
+ *bdp = *db;
+ break;
+ } else
+ msg = "bad sector table corrupted";
+ }
+ } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
+ i < lp->d_nsectors);
+ }
+
+done:
+ bp->b_flags = B_INVAL | B_AGE | B_READ;
+ brelse(bp);
+ return (msg);
+}
+
+
+/*
+ * Check new disk label for sensibility
+ * before setting it.
+ */
+
+int
+setdisklabel(olp, nlp, openmask, osdep)
+ struct disklabel *olp;
+ struct disklabel *nlp;
+ u_long openmask;
+ struct cpu_disklabel *osdep;
+{
+ register i;
+ register struct partition *opp, *npp;
+
+/* sanity clause */
+
+ if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0
+ || (nlp->d_secsize % DEV_BSIZE) != 0)
+ return(EINVAL);
+
+/* special case to allow disklabel to be invalidated */
+
+ if (nlp->d_magic == 0xffffffff) {
+ *olp = *nlp;
+ return (0);
+ }
+
+ if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC
+ || dkcksum(nlp) != 0)
+ return (EINVAL);
+
+/* XXX missing check if other dos partitions will be overwritten */
+
+ while (openmask != 0) {
+ i = ffs(openmask) - 1;
+ openmask &= ~(1 << i);
+ if (nlp->d_npartitions <= i)
+ return (EBUSY);
+ opp = &olp->d_partitions[i];
+ npp = &nlp->d_partitions[i];
+ if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
+ return (EBUSY);
+ /*
+ * Copy internally-set partition information
+ * if new label doesn't include it. XXX
+ */
+ if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
+ npp->p_fstype = opp->p_fstype;
+ npp->p_fsize = opp->p_fsize;
+ npp->p_frag = opp->p_frag;
+ npp->p_cpg = opp->p_cpg;
+ }
+ }
+
+ nlp->d_checksum = 0;
+ nlp->d_checksum = dkcksum(nlp);
+ *olp = *nlp;
+ return (0);
+}
+
+
+/*
+ * Write disk label back to device after modification.
+ */
+
+int
+writedisklabel(dev, strat, lp, osdep)
+ dev_t dev;
+ void (*strat)();
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ struct riscbsd_partition *rp = osdep->partitions;
+ register struct buf *bp;
+ struct disklabel *dlp;
+ int cyl, riscbsdpartoff;
+ int error = 0;
+
+/* get a buffer and initialize it */
+
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+/* do riscbsd partitions in the process of getting disklabel? */
+
+ riscbsdpartoff = 0;
+ cyl = LABELSECTOR / lp->d_secpercyl;
+
+ if (rp) {
+ struct filecore_bootblock *bb;
+ int heads;
+ int sectors;
+
+/* read the filecore boot block */
+
+ printf("writedisklabel: Reading boot block\n");
+
+ bp->b_blkno = FILECORE_BOOT_SECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylin = bp->b_blkno / lp->d_secpercyl;
+ (*strat)(bp);
+
+/* if successful, validate boot block and locate parition table */
+
+ if (biowait(bp)) {
+ printf("writedisklabel: filecore boot block I/O error\n");
+ goto done;
+ }
+
+ bb = (struct filecore_bootblock *)bp->b_data;
+
+/* Validate boot block */
+
+ if (bb->checksum != filecore_checksum((u_char *)bb)) {
+/* Invalid boot block so lets assume the entire disc is RiscBSD */
+
+ printf("writedisklabel: Invalid filecore boot block (incorrect checksum)\n");
+ goto writelabel;
+ }
+
+/* Do we have a RiscBSD partition ? */
+
+ if (bb->partition_type != PARTITION_FORMAT_RISCBSD) {
+ printf("writedisklabel: Invalid partition format\n");
+ goto done;
+ }
+
+ cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8);
+
+ heads = bb->heads;
+ sectors = bb->secspertrack;
+
+ /*printf("heads = %d nsectors = %d\n", heads, sectors);*/
+
+ riscbsdpartoff = cyl * heads * sectors;
+ }
+
+writelabel:
+
+/* printf("writedisklabel: Reading disklabel addr=%08x\n", riscbsdpartoff * DEV_BSIZE);*/
+
+/* next, dig out disk label */
+
+ bp->b_blkno = riscbsdpartoff + LABELSECTOR;
+ bp->b_cylin = cyl;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+
+/* if successful, locate disk label within block and validate */
+
+ if ((error = biowait(bp)))
+ goto done;
+ for (dlp = (struct disklabel *)bp->b_data;
+ dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp));
+ dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+ if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
+ dkcksum(dlp) == 0) {
+ *dlp = *lp;
+ bp->b_flags = B_BUSY | B_WRITE;
+ (*strat)(bp);
+ error = biowait(bp);
+ goto done;
+ }
+ }
+
+ error = ESRCH;
+
+done:
+ bp->b_flags |= B_INVAL;
+ brelse(bp);
+ return (error);
+}
+
+
+/*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition. Adjust transfer
+ * if needed, and signal errors or early completion.
+ */
+int
+bounds_check_with_label(bp, lp, wlabel)
+ struct buf *bp;
+ struct disklabel *lp;
+ int wlabel;
+{
+ struct partition *p = lp->d_partitions + DISKPART(bp->b_dev);
+ int labelsector = lp->d_partitions[0].p_offset + LABELSECTOR;
+ int sz;
+
+ sz = howmany(bp->b_bcount, lp->d_secsize);
+
+ if (bp->b_blkno + sz > p->p_size) {
+ sz = p->p_size - bp->b_blkno;
+ if (sz == 0) {
+ /* If exactly at end of disk, return EOF. */
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ if (sz < 0) {
+ /* If past end of disk, return EINVAL. */
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ /* Otherwise, truncate request. */
+ bp->b_bcount = sz << DEV_BSHIFT;
+ }
+
+ /* Overwriting disk label? */
+ if (bp->b_blkno + p->p_offset <= labelsector &&
+#if LABELSECTOR != 0
+ bp->b_blkno + p->p_offset + sz > labelsector &&
+#endif
+ (bp->b_flags & B_READ) == 0 && !wlabel) {
+ bp->b_error = EROFS;
+ goto bad;
+ }
+
+ /* calculate cylinder for disksort to order transfers with */
+ bp->b_cylin = (bp->b_blkno + p->p_offset) /
+ (lp->d_secsize / DEV_BSIZE) / lp->d_secpercyl;
+ return (1);
+
+bad:
+ bp->b_flags |= B_ERROR;
+done:
+ return (0);
+}
+
+
+int
+dk_establish(dk, dev)
+ struct dkdevice *dk;
+ struct device *dev;
+{
+ return(-1);
+}
+
+/* End of disksubr.c */
--- /dev/null
+/* $NetBSD: exception.S,v 1.5 1996/03/13 21:00:26 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * exception.S
+ *
+ * Low level handlers for exception vectors
+ *
+ * Created : 24/09/94
+ *
+ * Based on kate/display/abort.s
+ */
+
+#include <machine/cpu.h>
+#include "assym.h"
+
+/*
+ * PUSHFRAME - macro to push a trap frame on the stack in the current mode
+ * Since the current mode is used, the SVC R14 field is not defined.
+ */
+
+#define PUSHFRAME \
+ str lr, [sp, #-4]!; /* Push the return address */ \
+ sub sp, sp, #0x00000004; /* Skip SVC R14 */ \
+ stmdb sp, {r0-r14}^; /* Push the user mode registers */ \
+ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ mrs r0, spsr_all; /* Put the SPSR on the stack */ \
+ str r0, [sp, #-4]!;
+
+/*
+ * PULLFRAME - macro to pull a trap frame from the stack in the current mode
+ * Since the current mode is used, the SVC R14 field is ignored.
+ */
+
+#define PULLFRAME \
+ ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \
+ msr spsr_all, r0; \
+ add sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ add sp, sp, #0x00000004; /* Skip SVC R14 */ \
+ ldr lr, [sp], #0x0004; /* Pull the return address */
+
+/*
+ * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode
+ * This should only be used if the processor is not currently in SVC32
+ * mode. The processor mode is switched to SVC mode and the trap frame is
+ * stored. The SVC R14 field is used to store the previous value of
+ * R14 in SVC mode.
+ */
+
+#define PUSHFRAMEINSVC \
+ stmdb sp, {r0-r3}; /* Save 4 registers */ \
+ mov r0, lr; /* Save xxx32 r14 */ \
+ mov r1, sp; /* Save xxx32 sp */ \
+ mrs r3, spsr_all; /* Save xxx32 spsr */ \
+ mrs r2, cpsr_all; /* Get the CPSR */ \
+ bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \
+ orr r2, r2, #(PSR_SVC32_MODE); \
+ msr cpsr_all, r2; /* Punch into SVC mode */ \
+ str r0, [sp, #-4]!; /* Push return address */ \
+ str lr, [sp, #-4]!; /* Push SVC r14 */ \
+ msr spsr_all, r3; /* Restore correct spsr */ \
+ ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \
+ stmdb sp, {r0-r14}^; /* Push the user mode registers */ \
+ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ mrs r0, spsr_all; /* Put the SPSR on the stack */ \
+ str r0, [sp, #-4]!
+
+/*
+ * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack
+ * in SVC32 mode and restore the saved processor mode and PC.
+ * This should be used when the SVC R14 register needs to be restored on
+ * exit.
+ */
+
+#define PULLFRAMEFROMSVCANDEXIT \
+ ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \
+ msr spsr_all, r0; /* restore SPSR */ \
+ add sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ ldmia sp!, {lr, pc}^ /* Restore lr and exit */
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+ .text
+ .align 0
+
+/* entry point for CPU data abort */
+
+ .global data_abort_entry
+
+data_abort_entry:
+ sub lr, lr, #0x00000008 /* Adjust the lr */
+
+ PUSHFRAMEINSVC /* Push trap frame and switch */
+ /* to SVC32 mode */
+
+ mov r0, sp /* pass the stack pointer as r0 */
+
+ add lr, pc, #Ldata_abort_return - . - 8
+ ldr r1, Ldata_abort_handler_address
+ ldr pc, [r1]
+
+Ldata_abort_return:
+#if 0 /* For now only handle ast's after interrupts */
+ ldr r0, [sp] /* Get the SPSR from stack */
+ and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the ABT */
+ teq r0, #(PSR_USR32_MODE)
+ ldreq r0, Lastpending /* Do we have an AST pending ? */
+ ldreq r1, [r0]
+ teqeq r1, #0x00000001
+ moveq r1, #0x00000000 /* Clear it */
+ streq r1, [r0]
+
+ moveq r0, sp /* arg 0 = irq frame */
+ bleq _ast /* call the AST handler */
+#endif
+
+/* Kill IRQ's */
+ mrs r0, cpsr_all
+ orr r0, r0, #(I32_bit)
+ msr cpsr_all, r0
+
+ PULLFRAMEFROMSVCANDEXIT /* Restore the trap frame and exit */
+
+Ldata_abort_handler_address:
+ .word _data_abort_handler_address
+
+ .data
+ .global _data_abort_handler_address
+
+_data_abort_handler_address:
+ .word abortdata
+
+ .text
+abortdata:
+ add r0, pc, #abortdatamsg - . - 8
+ b _panic
+
+abortdatamsg:
+ .asciz "abortdata"
+ .align 0
+
+
+ .global prefetch_abort_entry
+
+prefetch_abort_entry:
+ sub lr, lr, #0x00000004 /* Adjust the lr */
+
+ PUSHFRAMEINSVC
+
+ mov r0, sp /* pass the stack pointer as r0 */
+
+ add lr, pc, #Lprefetch_abort_return - . - 8
+ ldr r1, Lprefetch_abort_handler_address
+ ldr pc, [r1]
+
+Lprefetch_abort_return:
+#if 0 /* For the moment ast's are only handled by irq handler */
+ ldr r0, [sp] /* Get the SPSR from stack */
+ and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the IRQ */
+ teq r0, #(PSR_USR32_MODE)
+ ldreq r0, Lastpending /* Do we have an AST pending ? */
+ ldreq r1, [r0]
+ teqeq r1, #0x00000001
+ moveq r1, #0x00000000 /* Clear it */
+ streq r1, [r0]
+
+ moveq r0, sp /* arg 0 = irq frame */
+ bleq _ast /* call the AST handler */
+#endif
+
+/* Kill IRQ's */
+ mrs r0, cpsr_all
+ orr r0, r0, #(I32_bit)
+ msr cpsr_all, r0
+
+ PULLFRAMEFROMSVCANDEXIT
+
+Lprefetch_abort_handler_address:
+ .word _prefetch_abort_handler_address
+
+ .data
+ .global _prefetch_abort_handler_address
+
+_prefetch_abort_handler_address:
+ .word abortprefetch
+
+ .text
+abortprefetch:
+ add r0, pc, #abortprefetchmsg - . - 8
+ b _panic
+
+abortprefetchmsg:
+ .asciz "abortprefetch"
+ .align 0
+
+
+/*
+ * swi_entry
+ *
+ * Main entry point for the SWI vector
+ */
+
+ .global swi_entry
+swi_entry:
+ PUSHFRAME
+
+ sub r0, lr, #0x00000004 /* Get the address of the SWI */
+ ldr r4, [r0] /* Get the instruction */
+
+ bic r1, r4, #0xff000000 /* Extract the comment field */
+
+ mov r0, sp /* Pass the frame to any function */
+
+ bl _syscall /* It's a syscall ! */
+
+#if 0 /* Ast's only from the irqhandler .... */
+ ldr r0, Lastpending /* Do we have an AST pending ? */
+ ldr r1, [r0]
+ teq r1, #0x00000001
+ moveq r1, #0x00000000 /* Clear it */
+ streq r1, [r0]
+
+ moveq r0, sp /* arg 0 = irq frame */
+ bleq _ast /* call the AST handler */
+#endif
+
+/* Kill irq's */
+
+ mrs r0, cpsr_all
+ orr r0, r0, #(I32_bit)
+ msr cpsr_all, r0
+
+ PULLFRAME
+
+ movs pc, lr /* Exit */
+
+Lastpending:
+ .word _astpending
+
+ .text
+ .align 0
+
+/*
+ * We indirect the undefined vector via the handler address
+ * in the data area.
+ * Entry to the undefined handler must look like direct
+ * entry from the vector.
+ */
+
+ .global undefined_entry
+undefined_entry:
+ stmfd sp!, {r0, r1}
+ ldr r0, Lundefined_handler_indirection
+ ldr r1, [sp], #0x0004
+ str r1, [r0, #0x0000]
+ ldr r1, [sp], #0x0004
+ str r1, [r0, #0x0004]
+ ldmia r0, {r0, r1, pc}
+
+Lundefined_handler_indirection:
+ .word Lundefined_handler_indirection_data
+
+/*
+ * assembly bounce code for calling the kernel
+ * undefined instruction handler. This uses
+ * a standard trap frame and is called in SVC mode.
+ */
+
+ .global _undefinedinstruction_bounce
+_undefinedinstruction_bounce:
+ PUSHFRAMEINSVC
+ mov r0, sp
+ bl _undefinedinstruction
+
+/* Kill irq's */
+ mrs r0, cpsr_all
+ orr r0, r0, #(I32_bit)
+ msr cpsr_all, r0
+
+ PULLFRAMEFROMSVCANDEXIT
+
+
+ .data
+ .align 0
+
+/*
+ * Indirection data
+ * 2 words use for preserving r0 and r1
+ * 3rd word contains the undefined handler address.
+ */
+
+Lundefined_handler_indirection_data:
+ .word 0
+ .word 0
+
+ .global _undefined_handler_address
+_undefined_handler_address:
+ .word _undefinedinstruction_bounce
+
+/* End of exception.S */
--- /dev/null
+/* $NetBSD: fault.c,v 1.3 1996/03/13 21:41:41 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fault.c
+ *
+ * Fault handlers
+ *
+ * Created : 28/11/94
+ */
+
+/*
+ * Special compilation symbols
+ *
+ * DEBUG_FAULT_CORRECTION - Add debug code used to develop the register
+ * correction following a data abort.
+ *
+ * CONTINUE_AFTER_SVC_PREFETCH - Do not panic following a prefetch abort
+ * in SVC mode. Used during developement.
+ */
+
+#define DEBUG_FAULT_CORRECTION
+/*#define CONTINUE_AFTER_SVC_PREFETCH*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/kernel.h>
+
+#include <vm/vm_kern.h>
+
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+
+#include <machine/irqhandler.h>
+#include <machine/frame.h>
+
+extern int pmap_debug_level;
+extern int nopagefault;
+static int onfault_count = 0;
+int nopagefault = 0; /* gross hack, has to go anyway */
+
+int pmap_modified_emulation __P((pmap_t, vm_offset_t));
+int pmap_handled_emulation __P((pmap_t, vm_offset_t));
+
+u_int disassemble __P((u_int));
+u_int ReadWordWithChecks __P((u_int, u_int *));
+
+/* Abort code */
+
+/* Define text descriptions of the different aborts */
+
+static char *aborts[16] = {
+ "Write buffer fault",
+ "Alignment fault",
+ "Write buffer fault",
+ "Alignment fault",
+ "Bus error (LF section)",
+ "Translation fault (section)",
+ "Bus error (page)",
+ "Translation fault (page)",
+ "Bus error (section)",
+ "Domain error (section)",
+ "Bus error (page)",
+ "Domain error (page)",
+ "Bus error trans (L1)",
+ "Permission error (section)",
+ "Bus error trans (L2)",
+ "Permission error (page)"
+};
+
+/*
+ * void data_abort_handler(trapframe_t *frame)
+ *
+ * Abort handler called when read/write occurs at an address of
+ * a non existant or restricted (access permissions) memory page.
+ * We first need to identify the type of page fault.
+ */
+
+void
+data_abort_handler(frame)
+ trapframe_t *frame;
+{
+ struct proc *p;
+ struct pcb *pcb;
+ u_int fault_address;
+ u_int fault_status;
+ u_int fault_pc;
+ u_int fault_instruction;
+ u_int s;
+ int fault_code;
+ u_quad_t sticks;
+ int saved_lr;
+
+/*
+ * OK you did not see this :-) This is worse than your worst nightmare
+ * This bug was found when implementing LDR/STR late abort fixes
+ * Don't know why I did not spot it before.
+ * I really need to rethink the trapframe structure ...
+ */
+
+ if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
+
+/* Ok an abort in SVC mode */
+
+/* CHEAT CHEAT CHEAT - SHUT YOUR EYES NOW ! */
+
+/* Copy the SVC r14 into the usr r14 - The usr r14 is garbage as the fault
+ * happened in svc mode but we need it in the usr slot so we can
+ * treat the registers as an array of ints during fixing.
+ * NOTE: This PC is in the position but writeback is not allowed on r15.
+ */
+ saved_lr = frame->tf_usr_lr;
+ frame->tf_usr_lr = frame->tf_svc_lr;
+
+/* Note the trapframe does not have the SVC r13 so a fault from an
+ * instruction with writeback to r13 in SVC mode is not allowed.
+ * This should not happen as the kstack is always valid.
+ */
+ }
+
+
+/*
+ * Enable IRQ's and FIQ's (disabled by CPU on abort) if trapframe shows
+ * they were enabled.
+ */
+
+#ifndef BLOCK_IRQS
+ if (!(frame->tf_spsr & I32_bit))
+ enable_interrupts(I32_bit);
+#endif
+
+/* Update vmmeter statistics */
+
+ cnt.v_trap++;
+
+/* Get fault address and status from the CPU */
+
+ fault_address = cpu_faultaddress();
+ fault_status = cpu_faultstatus();
+ fault_pc = frame->tf_pc;
+
+ fault_instruction = ReadWord(fault_pc);
+
+/* More debug stuff */
+
+ s = splhigh();
+ if (pmap_debug_level >= 0) {
+ printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+ aborts[fault_status & 0xf], fault_status & 0xfff,
+ fault_address, fault_pc);
+
+ printf("Instruction @V%08x = %08x\n",
+ fault_pc, fault_instruction);
+ }
+
+/* Decode the fault instruction and fix the registers as needed */
+
+/* Was is a swap instruction ? */
+
+ if ((fault_instruction & 0x0fb00ff0) == 0x01000090) {
+ if (pmap_debug_level >= 0) {
+ printf("SWP\n");
+ disassemble(fault_pc);
+ }
+ } else if ((fault_instruction & 0x0c000000) == 0x04000000) {
+
+/* Was is a ldr/str instruction */
+
+#ifdef CPU_LATE_ABORT
+
+/* This is for late abort only */
+
+ int base;
+ int offset;
+ int *registers = &frame->tf_r0;
+#endif
+
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >= 0) {
+/* printf("LDR/STR\n");*/
+ disassemble(fault_pc);
+ }
+#endif
+
+#ifdef CPU_LATE_ABORT
+
+/* This is for late abort only */
+
+ if ((fault_instruction & (1 << 24)) == 0
+ || (fault_instruction & (1 << 21)) != 0) {
+ base = (fault_instruction >> 16) & 0x0f;
+ if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
+ disassemble(fault_pc);
+ panic("Abort handler cannot fix this :-(\n");
+ }
+ if (base == 15) {
+ disassemble(fault_pc);
+ panic("Abort handler cannot fix this :-(\n");
+ }
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >=0)
+ printf("late abt fix: r%d=%08x ", base, registers[base]);
+#endif
+ if ((fault_instruction & (1 << 25)) == 0) {
+/* Immediate offset - easy */
+ offset = fault_instruction & 0xfff;
+ if ((fault_instruction & (1 << 23)))
+ offset = -offset;
+ registers[base] += offset;
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >=0)
+ printf("imm=%08x ", offset);
+#endif
+ } else {
+ int shift;
+
+ offset = fault_instruction & 0x0f;
+ if (offset == base) {
+ disassemble(fault_pc);
+ panic("Abort handler cannot fix this :-(\n");
+ }
+
+/* Register offset - hard we have to cope with shifts ! */
+ offset = registers[offset];
+
+ if ((fault_instruction & (1 << 4)) == 0)
+ shift = (fault_instruction >> 7) & 0x1f;
+ else {
+ if ((fault_instruction & (1 << 7)) != 0) {
+ disassemble(fault_pc);
+ panic("Abort handler cannot fix this :-(\n");
+ }
+ shift = ((fault_instruction >> 8) & 0xf);
+ if (base == shift) {
+ disassemble(fault_pc);
+ panic("Abort handler cannot fix this :-(\n");
+ }
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >=0)
+ printf("shift reg=%d ", shift);
+#endif
+ shift = registers[shift];
+ }
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >=0)
+ printf("shift=%08x ", shift);
+#endif
+ switch (((fault_instruction >> 5) & 0x3)) {
+ case 0 : /* Logical left */
+ offset = (int)(((u_int)offset) << shift);
+ break;
+ case 1 : /* Logical Right */
+ if (shift == 0) shift = 32;
+ offset = (int)(((u_int)offset) >> shift);
+ break;
+ case 2 : /* Arithmetic Right */
+ if (shift == 0) shift = 32;
+ offset = (int)(((int)offset) >> shift);
+ break;
+ case 3 : /* Rotate right */
+ disassemble(fault_pc);
+ panic("Abort handler cannot fix this yet :-(\n");
+ break;
+ }
+
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >=0)
+ printf("abt: fixed LDR/STR with register offset\n");
+#endif
+ if ((fault_instruction & (1 << 23)))
+ offset = -offset;
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >=0)
+ printf("offset=%08x ", offset);
+#endif
+ registers[base] += offset;
+ }
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >=0)
+ printf("r%d=%08x\n", base, registers[base]);
+#endif
+ }
+#endif
+ }
+ else if ((fault_instruction & 0x0e000000) == 0x08000000) {
+ int base;
+ int loop;
+ int count;
+ int *registers = &frame->tf_r0;
+
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >= 0) {
+ printf("LDM/STM\n");
+ disassemble(fault_pc);
+ }
+#endif
+ if (fault_instruction & (1 << 21)) {
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >= 0)
+ printf("This instruction must be corrected\n");
+#endif
+ base = (fault_instruction >> 16) & 0x0f;
+ if (base == 15) {
+ disassemble(fault_pc);
+ panic("Abort handler cannot fix this :-(\n");
+ }
+ count = 0;
+ for (loop = 0; loop < 16; ++loop) {
+ if (fault_instruction & (1<<loop))
+ ++count;
+ }
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >= 0) {
+ printf("%d registers used\n", count);
+ printf("Corrected r%d by %d bytes ", base, count * 4);
+ }
+#endif
+ if (fault_instruction & (1 << 23)) {
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >= 0)
+ printf("down\n");
+#endif
+ registers[base] -= count * 4;
+ } else {
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >= 0)
+ printf("up\n");
+#endif
+ registers[base] += count * 4;
+ }
+ }
+ } else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
+ int base;
+ int offset;
+ int *registers = &frame->tf_r0;
+
+/* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */
+
+#ifdef DEBUG_FAULT_CORRECTION
+ if (pmap_debug_level >= 0) {
+ printf("LDC/STC\n");
+ disassemble(fault_pc);
+ }
+#endif
+
+/* Only need to fix registers if write back is turned on */
+
+ if ((fault_instruction & (1 << 21)) != 0) {
+ base = (fault_instruction >> 16) & 0x0f;
+ if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
+ disassemble(fault_pc);
+ panic("Abort handler cannot fix this :-(\n");
+ }
+ if (base == 15) {
+ disassemble(fault_pc);
+ panic("Abort handler cannot fix this :-(\n");
+ }
+
+ offset = (fault_instruction & 0xff) << 2;
+ if (pmap_debug_level >= 0)
+ printf("r%d=%08x\n", base, registers[base]);
+ if ((fault_instruction & (1 << 23)) != 0)
+ offset = -offset;
+ registers[base] += offset;
+ if (pmap_debug_level >= 0)
+ printf("r%d=%08x\n", base, registers[base]);
+ }
+ } else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
+ disassemble(fault_pc);
+ panic("How did this happen ...\nWe have faulted on a non data transfer instruction");
+ }
+
+/*
+ * OK you did not see this :-) This is worse than your worst nightmare
+ * This bug was found when implementing LDR/STR late abort fixes
+ * Don't know why I did not spot it before.
+ * I really need to rethink the trapframe structure ...
+ */
+
+ if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
+
+/* Ok an abort in SVC mode */
+
+/* CHEAT CHEAT CHEAT - SHUT YOUR EYES NOW ! */
+
+/* Copy the SVC r14 into the usr r14 - The usr r14 is garbage as the fault
+ * happened in svc mode but we need it in the usr slot so we can
+ * treat the registers as an array of ints during fixing.
+ * NOTE: This PC is in the position but writeback is not allowed on r15.
+ */
+
+ frame->tf_svc_lr = frame->tf_usr_lr;
+ frame->tf_usr_lr = saved_lr;
+
+/* Note the trapframes does not have the SVC r13 so a fault from an
+ * instruction with writeback to r13 in SVC mode is not allowed.
+ * This should not happen as the kstack is always valid.
+ */
+ }
+
+ (void)splx(s);
+
+/* Extract the fault code from the fault status */
+
+ fault_code = fault_status & FAULT_TYPE_MASK;
+
+/* Get the current proc structure or proc0 if there is none */
+
+ if ((p = curproc) == 0)
+ p = &proc0;
+
+ if (pmap_debug_level >= 0)
+ printf("fault in process %08x\n", (u_int)p);
+
+/* can't use curpcb, as it might be NULL; and we have p in a register anyway */
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb == 0) {
+ vm_offset_t va;
+
+ va = trunc_page((vm_offset_t)fault_address);
+ if (pmap_handled_emulation(kernel_pmap, va))
+ return;
+ if (pmap_modified_emulation(kernel_pmap, va))
+ return;
+ panic("no pcb ... we're toast !\n");
+ }
+
+ if (pcb != curpcb) {
+ printf("data_abort: Alert ! pcb(%08x) != curpcb(%08x)\n", (u_int)pcb,
+ (u_int)curpcb);
+ printf("data_abort: Alert ! proc(%08x), curproc(%08x)\n", (u_int)p,
+ (u_int)curproc);
+ }
+
+/* fusubail is used by [fs]uswintr to avoid page faulting */
+
+/*
+ * To get this correct I need to talk to the person coding the
+ * fubyte and subyte routines etc.
+ * There appear to be cases where a fault should be swallowed.
+ * The 386 does this by checking the error handler being used.
+ */
+/*
+ * Well it looks like I am doing this so I will talk to myself.
+ * Need to allow perm faults in case of modified bit emulation.
+ */
+
+ if (nopagefault != 0)
+ printf("fault occured with no_page_fault == %d\n", nopagefault);
+
+ if (pcb->pcb_onfault
+ && ((fault_code != FAULT_TRANS_S && fault_code != FAULT_TRANS_P)
+/* || pcb->pcb_onfault == fusubailout*/)) {
+copyfault:
+ printf("Using pcb_onfault=%08x addr=%08x st=%08x\n",
+ (u_int)pcb->pcb_onfault, fault_address, fault_status);
+ frame->tf_pc = (u_int)pcb->pcb_onfault;
+ if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
+ printf("Yikes pcb_onfault=%08x during USR mode fault\n",
+ (u_int)pcb->pcb_onfault);
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 1);
+#endif
+ ++onfault_count;
+ if (onfault_count > 10) {
+ traceback();
+ panic("Eaten by zombies\n");
+ }
+ return;
+ }
+
+/* Were we in user mode when the abort occurred ? */
+
+ if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
+ sticks = p->p_sticks;
+
+/* Modify the fault_code to reflect the USR/SVC state at time of fault */
+
+ fault_code |= FAULT_USER;
+ p->p_md.md_regs = frame;
+ }
+
+/* Now act of the fault type */
+
+ switch (fault_code) {
+ case FAULT_WRTBUF_0 | FAULT_USER: /* Write Buffer Fault */
+ case FAULT_WRTBUF_1 | FAULT_USER: /* Write Buffer Fault */
+ case FAULT_WRTBUF_0: /* Write Buffer Fault */
+ case FAULT_WRTBUF_1: /* Write Buffer Fault */
+/* If this happens forget it no point in continuing */
+
+ panic("Write Buffer Fault - Halting\n");
+ break;
+
+ case FAULT_ALIGN_0 | FAULT_USER: /* Alignment Fault */
+ case FAULT_ALIGN_1 | FAULT_USER: /* Alignment Fault */
+ case FAULT_ALIGN_0: /* Alignment Fault */
+ case FAULT_ALIGN_1: /* Alignment Fault */
+
+/*
+ * Really this should just kill the process. Alignment faults are turned
+ * off in the kernel in order to get better performance from shorts with
+ * GCC so an alignment fault means somebody has played with the control
+ * register in the CPU. Might as well panic as the kernel was not compiled
+ * for aligned accesses.
+ */
+ panic("Alignment fault - Halting\n");
+/* trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);*/
+ break;
+
+ case FAULT_BUSERR_0 | FAULT_USER: /* Bus Error LF Section */
+ case FAULT_BUSERR_1 | FAULT_USER: /* Bus Error Page */
+ case FAULT_BUSERR_2 | FAULT_USER: /* Bus Error Section */
+ case FAULT_BUSERR_3 | FAULT_USER: /* Bus Error Page */
+ case FAULT_BUSERR_0: /* Bus Error LF Section */
+ case FAULT_BUSERR_1: /* Bus Error Page */
+ case FAULT_BUSERR_2: /* Bus Error Section */
+ case FAULT_BUSERR_3: /* Bus Error Page */
+
+/* What will accutally cause a bus error ? */
+/* Real bus errors are not a process problem but hardware */
+
+ panic("Bus Error - Halting\n");
+/* trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);*/
+ break;
+
+ case FAULT_DOMAIN_S | FAULT_USER: /* Section Domain Error Fault */
+ case FAULT_DOMAIN_P | FAULT_USER: /* Page Domain Error Fault*/
+ case FAULT_DOMAIN_S: /* Section Domain Error Fault */
+ case FAULT_DOMAIN_P: /* Page Domain Error Fault*/
+
+/*
+ * Right well we dont use domains, everything is always a client and thus
+ * subject to access permissions.
+ * If we get a domain error then we have corrupts PTE's so we might
+ * as well die !
+ * I suppose eventually this should just kill the process who owns the
+ * PTE's but if this happens it implies a kernel problem.
+ */
+
+ panic("Domain Error - Halting\n");
+/* trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);*/
+ break;
+
+ case FAULT_PERM_P: /* Page Permission Fault*/
+ case FAULT_PERM_P | FAULT_USER: /* Page Permission Fault*/
+/* Ok we have a permission fault in user or kernel mode */
+ {
+ register vm_offset_t va;
+ register struct vmspace *vm = p->p_vmspace;
+ register vm_map_t map;
+ int rv;
+ vm_prot_t ftype;
+
+/*
+ * Ok we have a permission fault in user mode. The only cause must be
+ * that a read only page has been written to. This may be genuine or it
+ * may be a bad access. In the future it may also be cause by the software
+ * emulation of the modified flag.
+ */
+
+ va = trunc_page((vm_offset_t)fault_address);
+
+ if (pmap_debug_level >= 0)
+ printf("ok we have a page permission fault - addr=V%08x ",
+ (u_int)va);
+
+/*
+ * It is only a kernel address space fault iff:
+ * 1. (fault_code & FAULT_USER) == 0 and
+ * 2. pcb_onfault not set or
+ * 3. pcb_onfault set but supervisor space fault
+ * The last can occur during an exec() copyin where the
+ * argument space is lazy-allocated.
+ */
+
+ if ((fault_code & FAULT_USER) == 0
+ && (va >= KERNEL_BASE || va <= VM_MIN_ADDRESS)) {
+ /* Was the fault due to the FPE ? */
+
+ if ((frame->tf_spsr & PSR_MODE) == PSR_UND32_MODE) {
+ printf("FPE Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+ aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+ fault_pc);
+ postmortem(frame);
+ trapsignal(p, SIGBUS, FAULT_PERM_P);
+ goto out;
+ }
+
+ printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+ aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+ fault_pc);
+ postmortem(frame);
+ panic("permission fault in kernel by kernel\n");
+ } else
+ map = &vm->vm_map;
+
+#ifdef DIAGNOSTIC
+ if (va == 0 && map == kernel_map) {
+ printf("fault: bad kernel access at %x\n", (u_int)va);
+ goto we_re_toast;
+ }
+#endif
+
+ if (pmap_debug_level >= 0)
+ printf("vmmap=%08x ", (u_int)map);
+
+/*
+ * We need to know whether the page should be mapped as R or R/W.
+ * The MMU does not give us the info as to whether the fault was caused
+ * by a read or a write. This means we need to disassemble the instruction
+ * responcible and determine if it was a read or write instruction.
+ */
+
+ ftype = VM_PROT_READ;
+
+ if ((fault_instruction & 0x0c100000) == 0x04000000)
+ ftype |= VM_PROT_WRITE;
+ else if ((fault_instruction & 0x0a100000) == 0x08000000)
+ ftype |= VM_PROT_WRITE;
+ else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
+ ftype |= VM_PROT_WRITE;
+
+/* if (!(ftype & VM_PROT_WRITE)) {
+ panic("permission fault on a read !\n");
+ }*/
+
+ if (pmap_modified_emulation(map->pmap, va))
+ goto out;
+ else {
+
+/* The page must be mapped to cause a permission fault. */
+
+ rv = vm_fault(map, va, ftype, FALSE);
+ if (pmap_debug_level >= 0)
+ printf("fault result=%d\n", rv);
+ if (rv == KERN_SUCCESS)
+ goto out;
+ printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+ aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+ fault_pc);
+ postmortem(frame);
+ trapsignal(p, (rv == KERN_PROTECTION_FAILURE)
+ ? SIGBUS : SIGSEGV, FAULT_PERM_P);
+ break;
+ }
+ }
+/* panic("Page Permission Fault - Halting\n");*/
+ break;
+
+#if 0
+ case FAULT_PERM_P: /* Page Permission Fault is non USR mode */
+
+/*
+ * Kernel permission faults should not happen. The kernel should never
+ * access memory it does not have permission for. Since the kernel has
+ * read access on all mapped pages it means the kernel has written to
+ * a read only kernel page. e.g. page 0
+ *
+ * Erg: Major cock up time. The kernel can take permission faults during
+ * the emulation of FP instructions. How comes I have not hit this problem ?
+ * ok out with the superglue ... This condition needs to be integrated with
+ * the FAULT_PERM_P | FAULT_USER case similarly to FAULT_TRANS_P
+ */
+
+ printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+ aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+ fault_pc);
+ postmortem(frame);
+ panic("Page Permission Fault - (in SVC mode) Halting\n");
+ break;
+#endif
+
+ case FAULT_PERM_S | FAULT_USER: /* Section Permission Fault */
+/*
+ * Section permission fault should not happen yet.
+ * However I have had this panic once so it can occor
+ * Yes they do ... Writing to -1 in user space does it ...
+ */
+ printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+ aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+ fault_pc);
+ disassemble(fault_pc);
+ postmortem(frame);
+ trapsignal(p, SIGBUS, FAULT_PERM_S);
+ break;
+
+/* panic("Section Permission Fault - Halting\n");
+ trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);
+ break;*/
+
+ case FAULT_BUSTRNL1 | FAULT_USER: /* Bus Error Trans L1 Fault */
+ case FAULT_BUSTRNL2 | FAULT_USER: /* Bus Error Trans L2 Fault */
+ case FAULT_BUSTRNL1: /* Bus Error Trans L1 Fault */
+ case FAULT_BUSTRNL2: /* Bus Error Trans L2 Fault */
+/*
+ * These faults imply that the PTE is corrupt. Likely to be a kernel
+ * fault so we had better stop.
+ */
+ panic("Bus Error Translation - Halting\n");
+ break;
+/* trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);
+ break;*/
+
+ case FAULT_TRANS_P: /* Page Translation Fault */
+ case FAULT_TRANS_P | FAULT_USER: /* Page Translation Fault */
+/* Ok page translation fault - The page does not exist */
+ {
+ register vm_offset_t va;
+ register struct vmspace *vm = p->p_vmspace;
+ register vm_map_t map;
+ int rv;
+ vm_prot_t ftype;
+ extern vm_map_t kernel_map;
+ u_int nss;
+
+ va = trunc_page((vm_offset_t)fault_address);
+
+ if (pmap_debug_level >= 0)
+ printf("ok we have a page fault - addr=V%08x ", (u_int)va);
+
+/*
+ * It is only a kernel address space fault iff:
+ * 1. (fault_code & FAULT_USER) == 0 and
+ * 2. pcb_onfault not set or
+ * 3. pcb_onfault set but supervisor space fault
+ * The last can occur during an exec() copyin where the
+ * argument space is lazy-allocated.
+ */
+
+ if (fault_code == FAULT_TRANS_P
+ && (va >= KERNEL_BASE || va < VM_MIN_ADDRESS))
+ map = kernel_map;
+ else
+ map = &vm->vm_map;
+
+ if (pmap_debug_level >= 0)
+ printf("vmmap=%08x ", (u_int)map);
+
+ if (pmap_handled_emulation(map->pmap, va))
+ goto out;
+
+/* debug_show_vm_map(map, "fault");*/
+
+/* We need to know whether the page should be mapped as R or R/W.
+ * The MMU does not give us the info as to whether the fault was caused
+ * by a read or a write. This means we need to disassemble the instruction
+ * responcible and determine if it was a read or write instruction.
+ * For the moment we will cheat and make it read only. If it was a write
+ * When the instruction is re-executed we will get a permission fault
+ * instead.
+ */
+
+ ftype = VM_PROT_READ;
+
+/* STR instruction ? */
+ if ((fault_instruction & 0x0c100000) == 0x04000000)
+ ftype |= VM_PROT_WRITE;
+/* STM instruction ? */
+ else if ((fault_instruction & 0x0a100000) == 0x08000000)
+ ftype |= VM_PROT_WRITE;
+/* SWP instruction ? */
+ else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
+ ftype |= VM_PROT_WRITE;
+
+ if (pmap_debug_level >= 0)
+ printf("fault protection = %d\n", ftype);
+
+#ifdef DIAGNOSTIC
+ if (va == 0 && map == kernel_map) {
+ printf("trap: bad kernel access at %x\n", (u_int)va);
+ goto we_re_toast;
+ }
+#endif
+
+ nss = 0;
+ if ((caddr_t)va >= vm->vm_maxsaddr
+ && (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS
+ && map != kernel_map) {
+ nss = clrnd(btoc(USRSTACK-(u_int)va));
+ if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
+ rv = KERN_FAILURE;
+ goto nogo;
+ }
+ }
+
+/* check if page table is mapped, if not, fault it first */
+
+/*
+ if (*(((pt_entry_t **)(PROCESS_PAGE_TBLS_BASE + va >> (PD_SHIFT+2)))[]) == 0)
+ panic("vm_fault: Page table is needed first\n")
+*/
+
+ rv = vm_fault(map, va, ftype, FALSE);
+/*printf("fault result=%d\n", rv);*/
+ if (rv == KERN_SUCCESS) {
+ if (nss > vm->vm_ssize)
+ vm->vm_ssize = nss;
+ va = trunc_page(vtopte(va));
+/*
+ * for page table, increment wiring as long as not a page
+ * table fault as well
+ */
+ if (map != kernel_map)
+ vm_map_pageable(map, va, round_page(va+1), FALSE);
+ if (fault_code == FAULT_TRANS_P)
+ return;
+ goto out;
+ }
+nogo:
+ if (fault_code == FAULT_TRANS_P) {
+ printf("Failed page fault in kernel\n");
+ if (pcb->pcb_onfault)
+ goto copyfault;
+ printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+ (u_int)map, (u_int)va, ftype, rv);
+ goto we_re_toast;
+ }
+ printf("nogo, Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+ aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+ fault_pc);
+ disassemble(fault_pc);
+ postmortem(frame);
+ trapsignal(p, (rv == KERN_PROTECTION_FAILURE)
+ ? SIGBUS : SIGSEGV, FAULT_TRANS_P);
+ break;
+ }
+/* panic("Page Fault - Halting\n");*/
+ break;
+
+ case FAULT_TRANS_S: /* Section Translation Fault */
+ case FAULT_TRANS_S | FAULT_USER: /* Section Translation Fault */
+/* Section translation fault - the L1 page table does not exist */
+ {
+ register vm_offset_t va;
+ register struct vmspace *vm = p->p_vmspace;
+ register vm_map_t map;
+ int rv;
+ vm_prot_t ftype;
+ u_int nss, v;
+
+ va = trunc_page((vm_offset_t)fault_address);
+
+ if (pmap_debug_level >= 0)
+ printf("ok we have a section fault page addr=V%08x\n",
+ (u_int)va);
+
+/*
+ * It is only a kernel address space fault iff:
+ * 1. (fault_code & FAULT_USER) == 0 and
+ * 2. pcb_onfault not set or
+ * 3. pcb_onfault set but supervisor space fault
+ * The last can occur during an exec() copyin where the
+ * argument space is lazy-allocated.
+ */
+
+ if (fault_code == FAULT_TRANS_S && va >= KERNEL_BASE)
+ map = kernel_map;
+ else
+ map = &vm->vm_map;
+
+/*
+ debug_show_vm_map(map, "fault");
+ debug_show_vm_map(kernel_map, "kernel");
+*/
+
+/* We are mapping a page table so this must be kernel r/w */
+
+ ftype = VM_PROT_READ | VM_PROT_WRITE;
+#ifdef DIAGNOSTIC
+ if (map == kernel_map && va == 0) {
+ printf("trap: bad kernel access at %x\n", (u_int)va);
+ goto we_re_toast;
+ }
+#endif
+
+ nss = 0;
+ if ((caddr_t)va >= vm->vm_maxsaddr
+ && (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS
+ && map != kernel_map) {
+/* printf("Address is in the stack\n");*/
+ nss = clrnd(btoc(USRSTACK-(u_int)va));
+ if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
+ printf("Stack limit exceeded %08x %08x\n",
+ nss, btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur));
+ rv = KERN_FAILURE;
+ goto nogo1;
+ }
+ }
+
+/* check if page table is mapped, if not, fault it first */
+
+ v = trunc_page(vtopte(va));
+ if (pmap_debug_level >= 0)
+ printf("v=%08x\n", v);
+ rv = vm_fault(map, v, ftype, FALSE);
+ if (rv != KERN_SUCCESS)
+ goto nogo1;
+
+ if (pmap_debug_level >= 0)
+ printf("vm_fault succeeded\n");
+
+/* update increment wiring as this is a page table fault */
+
+ vm_map_pageable(map, v, round_page(v+1), FALSE);
+
+ if (pmap_debug_level >= 0)
+ printf("faulting in page %08x\n", (u_int)va);
+
+ ftype = VM_PROT_READ;
+
+ rv = vm_fault(map, va, ftype, FALSE);
+ if (rv == KERN_SUCCESS) {
+ if (nss > vm->vm_ssize)
+ vm->vm_ssize = nss;
+ va = trunc_page(vtopte(va));
+/*
+ * for page table, increment wiring as long as not a page
+ * table fault as well
+ */
+ if (!v && map != kernel_map)
+ vm_map_pageable(map, va, round_page(va+1), FALSE);
+ if (fault_code == FAULT_TRANS_S)
+ return;
+ goto out;
+ }
+nogo1:
+ printf("nogo1, Data abort: '%s' status = %03x address = %08x PC = %08x\n",
+ aborts[fault_status & 0xf], fault_status & 0xfff, fault_address,
+ fault_pc);
+ disassemble(fault_pc);
+ if (fault_code == FAULT_TRANS_S) {
+ printf("Section fault in SVC mode\n");
+ if (pcb->pcb_onfault)
+ goto copyfault;
+ printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+ (u_int)map, (u_int)va, ftype, rv);
+ goto we_re_toast;
+ }
+ postmortem(frame);
+ trapsignal(p, (rv == KERN_PROTECTION_FAILURE)
+ ? SIGBUS : SIGSEGV, FAULT_TRANS_S);
+ break;
+ }
+/* panic("Section Fault - Halting\n");
+ break;*/
+
+ default :
+/* Are there any combinations I have missed ? */
+
+ printf("fault status = %08x fault code = %08x\n",
+ fault_status, fault_code);
+
+we_re_toast:
+/* Were are dead, try and provide some debug infomation before dying */
+
+ postmortem(frame);
+
+ panic("Fault cannot be handled\n");
+ break;
+ }
+
+out:
+ if ((fault_code & FAULT_USER) == 0)
+ return;
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 1);
+#endif
+ userret(p, frame->tf_pc, sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 1);
+#endif
+}
+
+
+/*
+ * void prefetch_abort_handler(trapframe_t *frame)
+ *
+ * Abort handler called when instruction execution occurs at
+ * a non existant or restricted (access permissions) memory page.
+ * If the address is invalid and we were in SVC mode then panic as
+ * the kernel should never prefetch abort.
+ * If the address is invalid and the page is mapped then the user process
+ * does no have read permission so send it a signal.
+ * Otherwise fault the page in and try again.
+ */
+
+void
+prefetch_abort_handler(frame)
+ trapframe_t *frame;
+{
+ register u_int fault_pc;
+ register struct proc *p;
+ register struct pcb *pcb;
+ u_int fault_instruction;
+ u_int s;
+ int fault_code;
+ u_quad_t sticks;
+
+/* Debug code */
+
+ if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) {
+ s = splhigh();
+ printf("fault being handled in non SVC32 mode\n");
+ postmortem(frame);
+ pmap_debug_level = 0;
+ (void)splx(s);
+ panic("Fault handler not in SVC mode\n");
+ }
+
+
+/*
+ * Enable IRQ's & FIQ's (disabled by the abort) This always comes
+ * from user mode so we know interrupts were not disabled.
+ * But we check anyway.
+ */
+
+#ifndef BLOCK_IRQS
+ if (!(frame->tf_spsr & I32_bit))
+ enable_interrupts(I32_bit);
+#endif
+
+/* Update vmmeter statistics */
+
+ cnt.v_trap++;
+
+/* Get the current proc structure or proc0 if there is none */
+
+ if ((p = curproc) == 0) {
+ p = &proc0;
+ printf("Prefetch about with curproc == 0\n");
+ }
+
+ if (pmap_debug_level >= 0)
+ printf("prefetch fault in process %08x\n", (u_int)p);
+
+/* can't use curpcb, as it might be NULL; and we have p in a register anyway */
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb == 0)
+ panic("no pcb ... we're toast !\n");
+
+ if (pcb != curpcb) {
+ printf("data_abort: Alert ! pcb(%08x) != curpcb(%08x)\n", (u_int)pcb,
+ (u_int)curpcb);
+ printf("data_abort: Alert ! proc(%08x), curproc(%08x)\n", (u_int)p,
+ (u_int)curproc);
+ }
+
+ if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
+ sticks = p->p_sticks;
+
+/* Modify the fault_code to reflect the USR/SVC state at time of fault */
+
+ fault_code |= FAULT_USER;
+ p->p_md.md_regs = frame;
+ } else {
+/* All the kernel code pages are loaded at boot and do not get paged */
+
+ s = splhigh();
+ printf("Prefetch address = %08x\n", frame->tf_pc);
+
+ postmortem(frame);
+
+#ifdef CONTINUE_AFTER_SVC_PREFETCH
+
+ printf("prefetch abort in SVC mode !\n");
+ printf("The system should now be considered very unstable :-)\n");
+ sigexit(curproc, SIGILL);
+/* Not reached */
+ (void)splx(s);
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 4);
+#endif
+ userret(p, frame->tf_pc, sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 4);
+#endif
+#else
+ panic("Prefetch abort in SVC mode\n");
+#endif
+ }
+
+/* Get fault address */
+
+ fault_pc = frame->tf_pc;
+
+ if (pmap_debug_level >= 0)
+ printf("Prefetch abort: PC = %08x\n", fault_pc);
+
+/* Ok validate the address, can only execute in USER space */
+
+ if (fault_pc < VM_MIN_ADDRESS || fault_pc >= VM_MAXUSER_ADDRESS) {
+ s = splhigh();
+ printf("prefetch: pc (%08x) not in user process space\n", fault_pc);
+ postmortem(frame);
+ trapsignal(p, SIGBUS, FAULT_PERM_P);
+ (void)splx(s);
+ userret(p, frame->tf_pc, sticks);
+ return;
+ }
+
+/* Ok read the fault address. This will fault the page in for us */
+
+ if (ReadWordWithChecks(fault_pc, &fault_instruction) != 0) {
+ s = splhigh();
+ printf("prefetch: faultin failed for address %08x!!\n", fault_pc);
+ postmortem(frame);
+ trapsignal(p, SIGSEGV, fault_pc);
+ (void)splx(s);
+ } else {
+
+/* More debug stuff */
+
+ if (pmap_debug_level >= 0) {
+ s = splhigh();
+ printf("Instruction @V%08x = %08x\n", fault_pc, fault_instruction);
+ disassemble(fault_pc);
+ printf("return addr=%08x\n", frame->tf_pc);
+
+ (void)splx(s);
+ }
+ }
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 4);
+#endif
+
+ userret(p, frame->tf_pc, sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 2);
+#endif
+}
+
+
+void
+validate_trapframe(frame, where)
+ trapframe_t *frame;
+ int where;
+{
+ char *ptr;
+ u_int mode;
+
+ if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE)
+ printf("VTF Warning : validate_trapframe : Not in SVC32 mode\n");
+
+ mode = frame->tf_spsr & PSR_MODE;
+
+ switch (where) {
+ case 1:
+ ptr = "data abort handler";
+ break;
+ case 2:
+ ptr = "prefetch abort handler";
+ if (mode != PSR_USR32_MODE)
+ printf("VTF Warning : %s : not USR32 mode\n", ptr);
+ break;
+ case 3:
+ ptr = "ast handler";
+ if (mode != PSR_USR32_MODE)
+ printf("VTF Warning : %s : not USR32 mode\n", ptr);
+ break;
+ case 4:
+ ptr = "syscall handler";
+ if (mode != PSR_USR32_MODE)
+ printf("VTF Warning : %s : not USR32 mode\n", ptr);
+ break;
+ case 5:
+ ptr = "undefined handler";
+ if (mode != PSR_USR32_MODE)
+ printf("VTF Warning : %s : not USR32 mode\n", ptr);
+ break;
+ case 6:
+ ptr = "sigreturn handler";
+ if (mode != PSR_USR32_MODE)
+ printf("VTF Warning : %s : not USR32 mode\n", ptr);
+ break;
+ default:
+ ptr = "unknown handler";
+ break;
+ }
+
+ if (frame->tf_usr_sp >= VM_MAXUSER_ADDRESS)
+ printf("VTF WARNING: %s : frame->tf_usr_sp >= VM_MAXUSER_ADDRESS [%08x]\n", ptr, frame->tf_usr_sp);
+ if (frame->tf_svc_lr >= 0xf1000000)
+ printf("VTF WARNING: %s : frame->tf_svc_lr >= 0xf1000000 [%08x]\n", ptr, frame->tf_svc_lr);
+ if (frame->tf_pc >= 0xf1000000)
+ printf("VTF WARNING: %s: frame->tf_pc >= 0xf1000000 [%08x]\n", ptr, frame->tf_pc);
+ if (frame->tf_pc < VM_MIN_ADDRESS)
+ printf("VTF WARNING: %s: frame->tf_pc >= VM_MIN_ADDRESS [%08x]\n", ptr, frame->tf_pc);
+ if (mode != PSR_USR32_MODE) {
+ if (frame->tf_svc_lr < 0xf0000000)
+ printf("VTF WARNING: %s : frame->tf_svc_lr < 0xf0000000 [%08x]\n", ptr, frame->tf_svc_lr);
+ if (frame->tf_pc < 0xf0000000)
+ printf("VTF WARNING: %s: frame->tf_pc < 0xf0000000 [%08x]\n", ptr, frame->tf_pc);
+ }
+}
+
+/* End of fault.c */
--- /dev/null
+/* $NetBSD: fiq.S,v 1.1 1996/01/31 23:15:55 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fiq.S
+ *
+ * Low level fiq handlers
+ *
+ * Created : 27/09/94
+ * Last updated : 28/11/94
+ *
+ * $Id: fiq.S,v 1.1.1.1 1996/04/24 11:08:26 deraadt Exp $
+ */
+
+#include <machine/cpu.h>
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+
+ .global _floppy_read_fiq
+ .global _floppy_read_fiq_end
+
+_floppy_read_fiq:
+ subs r11, r11, #0x00000001
+ addeq r13, r13, #0x00018000
+ ldrb r10, [r13]
+ strb r10, [r12], #0x0001
+ subs pc, lr, #0x00000004
+_floppy_read_fiq_end:
+
+ .global _floppy_write_fiq
+ .global _floppy_write_fiq_end
+
+_floppy_write_fiq:
+ subs r11, r11, #0x00000001
+ addeq r13, r13, #0x00018000
+ ldrb r10, [r12], #0x0001
+ strb r10, [r13]
+ subs pc, lr, #0x00000004
+
+_floppy_write_fiq_end:
--- /dev/null
+/* $NetBSD: fusu.c,v 1.2 1996/03/27 22:42:08 mark Exp $ */
+
+/*
+ * Copyright (C) 1993 Wolfgang Solfrank.
+ * Copyright (C) 1993 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Emulate fubyte.
+ */
+
+int
+fubyte(addr)
+char *addr;
+{
+ unsigned char c;
+
+ if (copyin(addr,&c,sizeof(c)))
+ return -1;
+ return c;
+}
+
+/*
+ * Emulate fuibyte.
+ * Note: This is the same as fubyte.
+ * In case of separate I&D space this MUST be replaced.
+ */
+
+int
+fuibyte(addr)
+char *addr;
+{
+ unsigned char c;
+
+ if (copyin(addr,&c,sizeof(c)))
+ return -1;
+ return c;
+}
+
+/*
+ * Emulate fuiword
+ * Note: This is the same as fuword.
+ * In case of separate I&D space this MUST be replaced.
+ */
+
+int
+fuiword(addr)
+char *addr;
+{
+ unsigned long l;
+
+ if (copyin(addr,&l,sizeof(l)))
+ return -1;
+ return l;
+}
+
+/*
+ * Emulate fuswintr
+ */
+
+int
+fuswintr(addr)
+char *addr;
+{
+ unsigned short s;
+ extern int nopagefault;
+ int ret;
+
+ nopagefault++;
+ if (copyin(addr,&s,sizeof(s)))
+ ret = -1;
+ else
+ ret = s;
+ nopagefault--;
+ return ret;
+}
+
+/*
+ * Emulate fusword
+ */
+
+int
+fusword(addr)
+char *addr;
+{
+ unsigned short s;
+
+ if (copyin(addr,&s,sizeof(s)))
+ return -1;
+ return s;
+}
+
+/*
+ * Emulate fuword
+ */
+
+int
+fuword(addr)
+char *addr;
+{
+ unsigned long l;
+
+ if (copyin(addr,&l,sizeof(l)))
+ return -1;
+ return l;
+}
+
+/*
+ * Emulate subyte.
+ */
+
+int
+subyte(addr,c)
+char *addr;
+unsigned char c;
+{
+ if (copyout(&c,addr,sizeof(c)))
+ return -1;
+ return 0;
+}
+
+/*
+ * Emulate suibyte.
+ * Note: This is the same as subyte.
+ * In case of separate I&D space this MUST be replaced.
+ */
+
+int
+suibyte(addr,c)
+char *addr;
+unsigned char c;
+{
+ if (copyout(&c,addr,sizeof(c)))
+ return -1;
+ return 0;
+}
+
+/*
+ * Emulate suiword
+ * Note: This is the same as suword.
+ * In case of separate I&D space this MUST be replaced.
+ */
+
+int
+suiword(addr,l)
+char *addr;
+unsigned long l;
+{
+ if (copyout(&l,addr,sizeof(l)))
+ return -1;
+ return 0;
+}
+
+/*
+ * Emulate suswintr
+ */
+
+int
+suswintr(addr,s)
+char *addr;
+unsigned short s;
+{
+ extern int nopagefault;
+ int ret;
+
+ nopagefault++;
+ ret = copyout(&s,addr,sizeof(s)) ? -1 : 0;
+ nopagefault--;
+ return ret;
+}
+
+/*
+ * Emulate susword
+ */
+
+int
+susword(addr,s)
+char *addr;
+unsigned short s;
+{
+ if (copyout(&s,addr,sizeof(s)))
+ return -1;
+ return 0;
+}
+
+/*
+ * Emulate suword
+ */
+
+int
+suword(addr,l)
+char *addr;
+unsigned long l;
+{
+ if (copyout(&l,addr,sizeof(l)))
+ return -1;
+ return 0;
+}
--- /dev/null
+/* $NetBSD: genassym.c,v 1.4 1996/03/13 21:22:32 mark Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/device.h>
+#include <sys/user.h>
+#include <sys/signal.h>
+
+#include <vm/vm.h>
+
+#include <machine/pmap.h>
+#include <machine/frame.h>
+#include <machine/vmparam.h>
+#include <machine/irqhandler.h>
+
+main()
+{
+ struct proc *p = 0;
+ struct vmmeter *vm = 0;
+ struct pcb *pcb = 0;
+ struct trapframe *tf = 0;
+ struct sigframe *sigf = 0;
+ struct uprof *uprof = 0;
+ irqhandler_t *ih = 0;
+ struct vconsole *vc = 0;
+ struct vidc_info *vi = 0;
+ struct vmspace *vms = 0;
+
+#define def(N,V) printf("#define\t%s %d\n", N, V)
+
+ def("UPAGES", UPAGES);
+ def("PGSHIFT", PGSHIFT);
+ def("PDSHIFT", PDSHIFT);
+
+ def("P_ADDR", &p->p_addr);
+ def("P_BACK", &p->p_back);
+ def("P_FORW", &p->p_forw);
+ def("P_PRIORITY", &p->p_priority);
+ def("P_STAT", &p->p_stat);
+ def("P_WCHAN", &p->p_wchan);
+ def("P_VMSPACE", &p->p_vmspace);
+ def("P_SPARE", &p->p_md.__spare);
+
+ def("PCB_PAGEDIR", &pcb->pcb_pagedir);
+ def("PCB_FLAGS", &pcb->pcb_flags);
+ def("PCB_R0", &pcb->pcb_r0);
+ def("PCB_R1", &pcb->pcb_r1);
+ def("PCB_R2", &pcb->pcb_r2);
+ def("PCB_R3", &pcb->pcb_r3);
+ def("PCB_R4", &pcb->pcb_r4);
+ def("PCB_R5", &pcb->pcb_r5);
+ def("PCB_R6", &pcb->pcb_r6);
+ def("PCB_R7", &pcb->pcb_r7);
+ def("PCB_R8", &pcb->pcb_r8);
+ def("PCB_R9", &pcb->pcb_r9);
+ def("PCB_R10", &pcb->pcb_r10);
+ def("PCB_R11", &pcb->pcb_r11);
+ def("PCB_R12", &pcb->pcb_r12);
+ def("PCB_SP", &pcb->pcb_sp);
+ def("PCB_LR", &pcb->pcb_lr);
+ def("PCB_PC", &pcb->pcb_pc);
+ def("PCB_UND_SP", &pcb->pcb_und_sp);
+ def("PCB_ONFAULT", &pcb->pcb_onfault);
+
+ def("USER_SIZE", sizeof(struct user));
+
+ def("V_TRAP", &vm->v_trap);
+ def("V_INTR", &vm->v_intr);
+ def("V_SOFT", &vm->v_soft);
+
+ def("VM_MAP", &vms->vm_map);
+ def("VM_PMAP", &vms->vm_pmap);
+
+ def("PR_BASE", &uprof->pr_base);
+ def("PR_SIZE", &uprof->pr_size);
+ def("PR_OFF", &uprof->pr_off);
+ def("PR_SCALE", &uprof->pr_scale);
+
+ def("IH_FUNC", &ih->ih_func);
+ def("IH_ARG", &ih->ih_arg);
+ def("IH_LEVEL", &ih->ih_level);
+ def("IH_NUM", &ih->ih_num);
+ def("IH_FLAGS", &ih->ih_flags);
+ def("IH_MASK", &ih->ih_irqmask);
+ def("IH_BIT", &ih->ih_irqbit);
+ def("IH_NEXT", &ih->ih_next);
+
+ def("SIGF_HANDLER", &sigf->sf_handler);
+ def("SIGF_SC", &sigf->sf_sc);
+
+ def("SIGTRAP", SIGTRAP);
+ def("SIGEMT", SIGEMT);
+
+ def("TF_R0", &tf->tf_r0);
+ def("TF_R10", &tf->tf_r10);
+ def("TF_PC", &tf->tf_pc);
+
+ def("PROCSIZE", sizeof(struct proc));
+ def("TRAPFRAMESIZE", sizeof(struct trapframe));
+ exit(0);
+}
--- /dev/null
+/* $NetBSD: irq.S,v 1.4 1996/03/27 20:42:53 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * irq.S
+ *
+ * Low level irq and fiq handlers
+ *
+ * Created : 27/09/94
+ */
+
+#include "assym.h"
+#include <machine/cpu.h>
+#include <machine/iomd.h>
+
+#define PUSHFRAME \
+ str lr, [sp, #-4]!; /* Push the return address */ \
+ sub sp, sp, #0x00000004; /* Skip SVC R14 */ \
+ stmdb sp, {r0-r14}^; /* Push the user mode registers */ \
+ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ mrs r0, spsr_all; /* Put the SPSR on the stack */ \
+ str r0, [sp, #-4]!;
+
+#define PULLFRAME \
+ ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \
+ msr spsr_all, r0; \
+ add sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ add sp, sp, #0x00000004; /* Skip SVC R14 */ \
+ ldr lr, [sp], #0x0004; /* Pull the return address */
+
+#define PULLFRAMEANDEXIT \
+ ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \
+ msr spsr_all, r0; \
+ add sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ add sp, sp, #0x00000004; /* Skip SVC R14 */ \
+ ldmia sp!, {pc}^ /* Pull the return address */
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+
+/*
+ *
+ * irq_entry
+ *
+ * Main entry point for the IRQ vector
+ *
+ * This function reads the irq request bits in the IOMD registers
+ * IRQRQA, IRQRQB and DMARQ
+ * It then calls an installed handler for each bit that is set.
+ * The function stray_irqhandler is called if a handler is not defined
+ * for a particular interrupt.
+ * If a interrupt handler is found then it is called with r0 containing
+ * the argument defined in the handler structure. If the field ih_arg
+ * is zero then a pointer to the IRQ frame on the stack is passed instead.
+ */
+
+Ldisabled_mask:
+ .word _disabled_mask
+
+Lcurrent_spl_level:
+ .word _current_spl_level
+
+ .global irq_entry
+
+/*
+ * Regsister usage
+ *
+ * r6 - Address of current handler
+ * r7 - Pointer to handler pointer list
+ * r8 - Current IRQ requests.
+ * r9 - Used to count through possible IRQ bits.
+ * r10 - Base address of IOMD
+ */
+
+irq_entry:
+ sub lr, lr, #0x00000004 /* Adjust the lr */
+
+ PUSHFRAME
+
+/* Raise the spl level and re-enable interrupts */
+
+#if 0
+ ldr r1, Lcurrent_spl_level
+ ldr r0, [r1]
+ add r0, r0, #1
+ bl _raisespl
+#endif
+#if 0
+ mrs r0, cpsr_all /* Enable IRQ's */
+ bic r0, r0, #I32_bit
+ msr cpsr_all, r0
+#endif
+
+/*
+ * If we did not raise the spl level high enough we will get another
+ * interrupt here.
+ */
+
+ mov r11, #0x00000000
+ mov r10, #(IOMD_BASE) /* Point to the IOMD */
+ ldrb r8, [r10, #(IOMD_IRQRQA - IOMD_BASE)] /* Get IRQ request A */
+/* strb r8, [r10, #(IOMD_IRQRQA - IOMD_BASE)]*/
+ ldrb r9, [r10, #(IOMD_IRQRQB - IOMD_BASE)] /* Get IRQ request B */
+ orr r8, r8, r9, lsl #8
+ ldrb r9, [r10, #(IOMD_DMARQ - IOMD_BASE)] /* Get DMA Request */
+ orr r8, r8, r9, lsl #16
+
+/*#if 0*/
+ mov r0, #0x7d /* Clear IOMD IRQ bits */
+ strb r0, [r10, #(IOMD_IRQRQA - IOMD_BASE)]
+/*#endif*/
+
+/* ldr r1, Ldisabled_mask
+ ldr r0, [r1]
+ orr r0, r0, r8
+ str r0, [r1]
+
+ bl _irq_setmasks*/
+
+#if 0
+ mrs r0, cpsr_all /* Enable IRQ's */
+ bic r0, r0, #I32_bit
+ msr cpsr_all, r0
+#endif
+ mov r0, sp
+ mov r1, r8
+ bl _validate_irq_address
+
+ ldr r7, [pc, #irqhandlers - . - 8]
+ mov r9, #0x00000001
+
+ stmfd sp!, {r8}
+
+irqloop:
+ tst r8, r9 /* Is a bit set ? */
+
+ beq nextirq /* No ? try next bit */
+
+ ldr r6, [r7] /* Get address of first handler structure */
+
+ teq r6, #0x00000000 /* Do we have a handler */
+ moveq r0, r8 /* IRQ requests as arg 0 */
+ beq _stray_irqhandler /* call special handler */
+
+ ldr r0, Lcnt
+ ldr r1, [r0, #(V_INTR)]
+ add r1, r1, #0x00000001
+ str r1, [r0, #(V_INTR)]
+
+irqchainloop:
+ add lr, pc, #nextinchain - . - 8 /* return address */
+
+#ifdef IRQSTATS
+ ldr r0, Lintrcnt
+ ldr r1, [r6, #(IH_NUM)]
+
+ add r0, r0, r1, lsl #2
+ ldr r1, [r0]
+ add r1, r1, #0x00000001
+ str r1, [r0]
+#endif
+
+ ldr r0, [r6, #(IH_ARG)] /* Get argument pointer */
+ teq r0, #0x00000000 /* If arg is zero pass stack frame */
+ addeq r0, sp, #4 /* ... stack frame */
+ ldr pc, [r6, #(IH_FUNC)] /* Call handler */
+
+nextinchain:
+/* ldr r1, Ldisabled_mask
+ ldr r2, [r1]
+ bic r2, r2, r9
+ str r2, [r1]
+ bl _irq_setmasks*/
+
+ teq r0, #0x00000001 /* Was the irq serviced ? */
+ beq nextirq
+
+ ldr r6, [r6, #(IH_NEXT)]
+ teq r6, #0x00000000
+/* bne irqchainloop*/
+
+nextirq:
+ add r7, r7, #0x00000004 /* update pointer to handlers */
+ mov r9, r9, lsl #1 /* move on to next bit */
+ teq r9, #(1 << 24) /* done the last bit ? */
+ bne irqloop /* no - loop back. */
+
+ ldmfd sp!, {r8}
+
+
+#if 0
+ mrs r0, cpsr_all /* Enable IRQ's */
+ orr r0, r0, #I32_bit
+ msr cpsr_all, r0
+#endif
+
+ bl _dosoftints /* Handle the soft interrupts */
+
+/* Disable interrupts and lower the spl level */
+
+#if 0
+ mrs r0, cpsr_all /* Enable IRQ's */
+ orr r0, r0, #I32_bit
+ msr cpsr_all, r0
+#endif
+#if 0
+ ldr r1, Lcurrent_spl_level
+ ldr r0, [r1]
+ sub r0, r0, #1
+ bl _lowerspl
+#endif
+
+ ldr r0, [sp] /* Get the SPSR from stack */
+
+ and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the IRQ */
+ teq r0, #(PSR_USR32_MODE)
+ ldreq r0, Lastpending /* Do we have an AST pending ? */
+ ldreq r1, [r0]
+ teqeq r1, #0x00000001
+ moveq r1, #0x00000000 /* Clear it */
+ streq r1, [r0]
+
+ moveq r0, sp /* arg 0 = irq frame */
+ beq _irqast /* exit via the AST handler */
+
+ PULLFRAME
+
+ movs pc, lr /* Exit */
+
+
+ .global _irqast
+_irqast:
+/* Punch into SVC32 mode (R0 points to the irqframe) */
+/* We can trash all the registers we like :-) */
+
+/* Debug message */
+
+/* stmfd sp!, {r0-r3}
+ add r0, pc, #Lirqtext0 - . - 8
+ bl _printf
+ ldmfd sp!, {r0-r3}*/
+
+ mrs r2, cpsr_all
+ tst r2, #(I32_bit)
+ bne Lis
+
+ orr r2, r2, #(I32_bit)
+ msr cpsr_all, r2
+
+ stmfd sp!, {r0-r3, lr}
+ add r0, pc, #Lirqtext0 - . - 8
+ bl _printf
+ ldmfd sp!, {r0-r3, lr}
+Lis:
+ add sp, sp, #72 /* Correct IRQ32 sp */
+
+/*
+ * We have now put IRQ mode back correct so we never need to return to
+ * IRQ mode we can just exit via SVC mode. We must copy the trap frame
+ * which still lies on the IRQ stack over to the SVC stack.
+ */
+
+/* Punch into SVC 32 mode (IRQ's still disabled) */
+
+ mrs r2, cpsr_all
+ bic r2, r2, #(PSR_MODE)
+ eor r2, r2, #(PSR_SVC32_MODE)
+ orr r2, r2, #(I32_bit) /* Overkill */
+ msr cpsr_all, r2
+
+ sub sp, sp, #72 /* Correct SVC32 sp */
+ mov r12, sp
+
+/* r0 points to the trap frame on the IRQ stack (SP corrected) */
+/* r12 points to the trap frame on the SVC stack */
+
+ ldmia r0!, {r1-r9} /* Pull 9 regs off the IRQ stack */
+ stmia r12!, {r1-r9} /* Store on the SVC stack */
+ ldmia r0!, {r1-r9} /* Pull 9 regs off the IRQ stack */
+ stmia r12!, {r1-r9} /* Store on the SVC stack */
+
+/* Ok the IRQ trapframe is now the SVC trapframe */
+
+/* IRQ's could be enabled here */
+
+/* Debug message */
+
+/* stmfd sp!, {r0-r3}
+ add r0, pc, #Lirqtext1 - . - 8
+ bl _printf
+ ldmfd sp!, {r0-r3}
+*/
+/* r0 points to trap frame on entry to ast() */
+
+ mov r0, sp
+ stmfd sp!, {lr} /* Is this needed ? */
+
+ bl _ast
+
+ ldmfd sp!, {lr} /* Is this needed ? */
+
+/* Remember the address of the trap frame */
+
+/* stmfd sp!, {r0-r3}
+ add r0, pc, #Lirqtext2 - . - 8
+ bl _printf
+ ldmfd sp!, {r0-r3}
+*/
+
+/* Pull the frame from the SVC stack and return */
+
+/* mov lr, #0*/
+
+/* Kill IRQ's incase ast as somehow re-enabled them ... */
+
+ mrs r0, cpsr_all
+ orr r0, r0, #(I32_bit)
+ msr cpsr_all, r0
+
+ PULLFRAMEANDEXIT
+
+ mov r4, #0x000000A0
+ mov pc, #0x00000000
+
+Lirqtext0:
+ .asciz "irqs enabled during ast\n"
+ .align 0
+
+Lirqtext1:
+ .asciz "irqframe copied to SVC stack\n"
+ .align 0
+
+Lirqtext2:
+ .asciz "irqframe restored from SVC stack\n"
+ .align 0
+
+Lspl_mask:
+ .word _spl_mask
+
+Lcurrent_mask:
+ .word _current_mask
+
+ .global _irq_setmasks
+
+_irq_setmasks:
+ ldr r1, Lcurrent_mask
+ ldr r1, [r1]
+ ldr r2, Lspl_mask
+ ldr r2, [r2]
+ and r1, r1, r2
+ ldr r2, Ldisabled_mask
+ ldr r2, [r2]
+ bic r1, r1, r2
+
+ mov r0, #(IOMD_BASE) /* Point to the IOMD */
+ strb r1, [r0, #(IOMD_IRQMSKA - IOMD_BASE)] /* Set IRQ mask A */
+ mov r1, r1, lsr #8
+ strb r1, [r0, #(IOMD_IRQMSKB - IOMD_BASE)] /* Set IRQ mask B */
+ mov r1, r1, lsr #8
+ strb r1, [r0, #(IOMD_DMAMSK - IOMD_BASE)] /* Set DMA mask */
+ mov pc, r14
+
+
+Lcnt:
+ .word _cnt
+
+Lintrcnt:
+ .word _intrcnt
+
+
+irqhandlers:
+ .word _irqhandlers /* Pointer to array of irqhandlers */
+
+Lastpending:
+ .word _astpending
+
+#ifdef IRQSTATS
+/* These symbols are used by vmstat */
+
+ .text
+ .global __intrnames
+__intrnames:
+ .word _intrnames
+
+ .data
+
+ .globl _intrnames, _eintrnames, _intrcnt, _eintrcnt
+_intrnames:
+ .asciz "interrupt 0 "
+ .asciz "softnet " /* reserved0 */
+ .asciz "interrupt 2 "
+ .asciz "interrupt 3 "
+ .asciz "interrupt 4 "
+ .asciz "interrupt 5 "
+ .asciz "interrupt 6 "
+ .asciz "softclock " /* reserved1 */
+ .asciz "reserved 2 "
+ .asciz "interrupt 9 "
+ .asciz "interrupt 10 "
+ .asciz "interrupt 11 "
+ .asciz "interrupt 12 "
+ .asciz "interrupt 13 "
+ .asciz "interrupt 14 "
+ .asciz "interrupt 15 "
+ .asciz "dma channel 0"
+ .asciz "dma channel 1"
+ .asciz "dma channel 2"
+ .asciz "dma channel 3"
+ .asciz "interrupt 20 "
+ .asciz "interrupt 21 "
+ .asciz "reserved 3 "
+ .asciz "reserved 4 "
+ .asciz "exp card 0 "
+ .asciz "exp card 1 "
+ .asciz "exp card 2 "
+ .asciz "exp card 3 "
+ .asciz "exp card 4 "
+ .asciz "exp card 5 "
+ .asciz "exp card 6 "
+ .asciz "exp card 7 "
+_eintrnames:
+
+ .bss
+ .align 0
+_intrcnt:
+ .space 32*4
+_eintrcnt:
+
+#else
+/* Dummy entries to keep vmstat happy */
+
+ .text
+ .globl _intrnames, _eintrnames, _intrcnt, _eintrcnt
+_intrnames:
+ .long 0
+_eintrnames:
+
+_intrcnt:
+ .long 0
+_eintrcnt:
+#endif
+
+/* FIQ code */
+
+ .text
+ .align 0
+ .global _fiq_setregs /* Sets up the FIQ handler */
+
+_fiq_setregs:
+ mrs r2, cpsr_all
+ mov r3, r2
+ bic r2, r2, #(PSR_MODE)
+ orr r2, r2, #(PSR_FIQ32_MODE)
+ msr cpsr_all, r2
+
+ ldr r8, [r0, #0x000c] /* Update FIQ registers*/
+ ldr r9, [r0, #0x0010]
+ ldr r10, [r0, #0x0014]
+ ldr r11, [r0, #0x0018]
+ ldr r12, [r0, #0x001c]
+ ldr r13, [r0, #0x0020]
+
+ msr cpsr_all, r3 /* Back to old mode */
+
+ mov pc, lr /* Exit */
+
+/* End of irq.S */
--- /dev/null
+/* $NetBSD: irqhandler.c,v 1.4 1996/03/28 21:43:52 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * irqhandler.c
+ *
+ * IRQ/FIQ initialisation, claim, release and handler routines
+ *
+ * NOTE: Although the irqhandlers support chaining and the claim
+ * and release routines install handlers at the top of the chain
+ * The low level IRQ handler will only call the top handler in a
+ * chain.
+ *
+ * Created : 30/09/94
+ */
+
+/* Note: Need to remove IRQ_FLAG_ACTIVE as it is not used */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <sys/syslog.h>
+
+#include <machine/irqhandler.h>
+#include <machine/cpu.h>
+#include <machine/iomd.h>
+#include <machine/katelib.h>
+#include <machine/pte.h>
+
+irqhandler_t *irqhandlers[NIRQS];
+fiqhandler_t *fiqhandlers;
+
+u_int irqmasks[IRQ_LEVELS];
+u_int current_mask;
+u_int actual_mask;
+u_int disabled_mask;
+u_int spl_mask;
+u_int soft_interrupts;
+extern u_int intrcnt[];
+
+typedef struct {
+ vm_offset_t physical;
+ vm_offset_t virtual;
+} pv_addr_t;
+
+extern pv_addr_t systempage;
+
+/* Prototypes */
+
+int podule_irqhandler __P((void));
+int irq_claim __P((int /*irq*/, irqhandler_t */*handler*/));
+void zero_page_readonly __P((void));
+void zero_page_readwrite __P((void));
+
+int fiq_setregs __P((fiqhandler_t *));
+
+/*
+ * void irq_init(void)
+ *
+ * Initialise the IRQ/FIQ sub system
+ */
+
+void
+irq_init()
+{
+ int loop;
+
+/* Clear all the IRQ handlers */
+
+ for (loop = 0; loop < NIRQS; ++loop)
+ irqhandlers[loop] = NULL;
+
+/* Clear the FIQ handler */
+
+ fiqhandlers = NULL;
+
+/* Clear the IRQ/FIQ masks in the IOMD */
+
+ WriteByte(IOMD_IRQMSKA, 0x00);
+ WriteByte(IOMD_IRQMSKB, 0x00);
+ WriteByte(IOMD_FIQMSK, 0x00);
+ WriteByte(IOMD_DMAMSK, 0x00);
+
+/*
+ * Setup the irqmasks for the different Interrupt Priority Levels
+ * We will start with no bits set and these will be updated as handlers
+ * are installed at different IPL's.
+ */
+
+ irqmasks[IPL_BIO] = 0x00000000;
+ irqmasks[IPL_NET] = 0x00000000;
+ irqmasks[IPL_TTY] = 0x00000000;
+ irqmasks[IPL_CLOCK] = 0x00000000;
+ irqmasks[IPL_IMP] = 0x00000000;
+
+ current_mask = 0x00000000;
+ actual_mask = 0x00000000;
+ spl_mask = 0x00000000;
+ soft_interrupts = 0x00000000;
+
+ set_spl_masks();
+
+/* Enable IRQ's and FIQ's */
+
+ enable_interrupts(I32_bit | F32_bit);
+}
+
+
+/*
+ * int irq_claim(int irq, irqhandler_t *handler)
+ *
+ * Enable an IRQ and install a handler for it.
+ */
+
+int
+irq_claim(irq, handler)
+ int irq;
+ irqhandler_t *handler;
+{
+ int level;
+
+/* IRQ_INSTRUCT indicates that we should get the irq number from the irq structure */
+
+ if (irq == IRQ_INSTRUCT)
+ irq = handler->ih_num;
+
+/* Make sure the irq number is valid */
+
+ if (irq < 0 || irq >= NIRQS)
+ return(-1);
+
+/* Install the handler at the top of the chain */
+
+ handler->ih_next = irqhandlers[irq];
+ irqhandlers[irq] = handler;
+
+/* if (irq == IRQ_VSYNC)
+ {
+ irqhandler_t *x;
+ x = irqhandlers[irq];
+ while (x) {
+ printf("handler = %08x %08x\n", x, handler);
+ x = x->ih_next;
+ }
+ }*/
+
+/*
+ * Reset the flags for this handler. As it is at the top of the list it
+ * must be the active handler.
+ */
+/* amb - no needed these days */
+ handler->ih_flags = 0 | IRQ_FLAG_ACTIVE;
+
+/*
+ * Record the interrupt number for accounting.
+ * Done here as the accounting number may not be the same as the IRQ number
+ * though for the moment they are
+ */
+
+ handler->ih_num = irq;
+
+/* If this is the first interrupt to be attached make a not of any name */
+
+#ifdef IRQSTATS
+ if (handler->ih_next == NULL && handler->ih_name) {
+ extern char *_intrnames;
+ char *ptr = _intrnames + (irq * 14);
+/* printf("intrnames=%08x ptr=%08x irq=%d\n", (u_int)_intrnames, (u_int)ptr, irq);*/
+ strcpy(ptr, " ");
+ strncpy(ptr, handler->ih_name, min(strlen(handler->ih_name), 13));
+ }
+#endif
+
+/*
+ * Update the irq masks.
+ * This IRQ is allowable at all lower Interrupt Priority Levels.
+ */
+ if (handler->ih_level >= 0 && handler->ih_level < IRQ_LEVELS) {
+ level = handler->ih_level - 1;
+ while (level >= 0) {
+ irqmasks[level] |= (1 << irq);
+ --level;
+ }
+
+#include "sl.h"
+#include "ppp.h"
+#if NSL > 0 || NPPP > 0
+/* In the presence of SLIP or PPP, splimp > spltty. */
+ irqmasks[IPL_NET] &= irqmasks[IPL_TTY];
+#endif
+ }
+
+/*
+ for (level = 0; level < IRQ_LEVELS; ++level)
+ printf("irqmask[%d] = %08x\n", level, irqmasks[level]);
+*/
+
+/*
+ * Is this an expansion card IRQ and is there a PODULE IRQ handler
+ * installed ?
+ * If not panic as the podulebus irq handler should have been installed
+ * when the podulebus was attached.
+ */
+
+ if (irq >= IRQ_EXPCARD0 && irqhandlers[IRQ_PODULE] == NULL)
+ panic("Podule IRQ %d claimed but no podulebus handler installed\n",
+ irq);
+
+ enable_irq(irq);
+ set_spl_masks();
+
+ return(0);
+}
+
+
+/*
+ * int irq_release(int irq, irqhandler_t *handler)
+ *
+ * Disable an IRQ and remove a handler for it.
+ */
+
+int
+irq_release(irq, handler)
+ int irq;
+ irqhandler_t *handler;
+{
+ int level;
+
+ irqhandler_t *irqhand;
+ irqhandler_t **prehand;
+
+/* IRQ_INSTRUCT indicates that we should get the irq number from the irq structure */
+
+ if (irq == IRQ_INSTRUCT)
+ irq = handler->ih_num;
+
+/* Make sure the irq number is valid */
+
+ if (irq < 0 || irq >= NIRQS)
+ return(-1);
+
+/*
+ * Update the irq masks.
+ * Remove the IRQ from all the approriate IPL's
+ */
+
+ if (handler->ih_level >= 0 && handler->ih_level < IRQ_LEVELS) {
+ level = handler->ih_level - 1;
+ while (level >= 0) {
+ irqmasks[level] &= ~(1 << irq);
+ --level;
+ }
+ }
+
+/* Locate the handler */
+
+ irqhand = irqhandlers[irq];
+ prehand = &irqhandlers[irq];
+
+ while (irqhand && handler != irqhand) {
+ prehand = &irqhand;
+ irqhand = irqhand->ih_next;
+ }
+
+/* Remove the handler if located */
+
+ if (irqhand)
+ *prehand = irqhand->ih_next;
+ else
+ return(-1);
+
+/* Flag the handler being removed as non active (in case it was) */
+/* Not needed these days - AMB */
+ irqhand->ih_flags &= ~IRQ_FLAG_ACTIVE;
+
+/* Make sure the head of the handler list is active */
+
+ if (irqhandlers[irq])
+ irqhandlers[irq]->ih_flags |= IRQ_FLAG_ACTIVE;
+
+/*
+ * Disable the appropriate mask bit if there are no handlers left for
+ * this IRQ.
+ */
+
+ if (irqhandlers[irq] == NULL)
+ disable_irq(irq);
+
+ set_spl_masks();
+
+ return(0);
+}
+
+
+u_int
+disable_interrupts(mask)
+ u_int mask;
+{
+ register u_int cpsr;
+
+ cpsr = SetCPSR(mask, mask);
+ if ((GetCPSR() & I32_bit) == 0)
+ printf("Alert ! disable_interrupts has failed\n");
+
+ return(cpsr);
+}
+
+
+u_int
+restore_interrupts(old_cpsr)
+ u_int old_cpsr;
+{
+ register int mask = I32_bit | F32_bit;
+ return(SetCPSR(mask, old_cpsr & mask));
+}
+
+
+u_int
+enable_interrupts(mask)
+ u_int mask;
+{
+ return(SetCPSR(mask, 0));
+}
+
+
+/*
+ * void disable_irq(int irq)
+ *
+ * Disables a specific irq. The irq is removed from the master irq mask
+ */
+
+void
+disable_irq(irq)
+ int irq;
+{
+ register int oldirqstate;
+
+ oldirqstate = disable_interrupts(I32_bit);
+ current_mask &= ~(1 << irq);
+ irq_setmasks();
+ restore_interrupts(oldirqstate);
+}
+
+
+/*
+ * void enable_irq(int irq)
+ *
+ * Enables a specific irq. The irq is added to the master irq mask
+ * This routine should be used with caution. A handler should already
+ * be installed.
+ */
+
+void
+enable_irq(irq)
+ int irq;
+{
+ register u_int oldirqstate;
+
+ oldirqstate = disable_interrupts(I32_bit);
+ current_mask |= (1 << irq);
+ irq_setmasks();
+ restore_interrupts(oldirqstate);
+}
+
+
+/*
+ * void stray_irqhandler(u_int mask)
+ *
+ * Handler for stray interrupts. This gets called if a handler cannot be
+ * found for an interrupt.
+ */
+
+void
+stray_irqhandler(mask)
+ u_int mask;
+{
+/* panic("Stray IRQ received (%08x)\n", mask);*/
+ static u_int stray_irqs = 0;
+
+ if (++stray_irqs <= 8)
+ log(LOG_ERR, "Stray interrupt %08x%s\n", mask,
+ stray_irqs >= 8 ? ": stopped logging" : "");
+}
+
+
+void
+dosoftints()
+{
+ register u_int softints;
+
+ softints = soft_interrupts & spl_mask;
+ if (softints & IRQMASK_SOFTCLOCK) {
+ int s;
+
+ ++cnt.v_soft;
+ ++intrcnt[IRQ_SOFTCLOCK];
+ soft_interrupts &= ~IRQMASK_SOFTCLOCK;
+ s = lowerspl(SPL_SOFT);
+ softclock();
+ (void)splx(s);
+ }
+ if (softints & IRQMASK_SOFTNET) {
+ ++cnt.v_soft;
+ ++intrcnt[IRQ_SOFTNET];
+ soft_interrupts &= ~IRQMASK_SOFTNET;
+#ifdef INET
+#include "ether.h"
+#if NETHER > 0
+ arpintr();
+#endif
+ ipintr();
+#endif
+#ifdef IMP
+ impintr();
+#endif
+#ifdef NS
+ nsintr();
+#endif
+#ifdef ISO
+ clnlintr();
+#endif
+#ifdef CCITT
+ ccittintr();
+#endif
+#include "ppp.h"
+#if NPPP > 0
+ pppintr();
+#endif
+ }
+}
+
+extern vgone();
+extern vfinddev();
+extern idle();
+extern cpu_switch();
+extern switch_exit();
+
+void
+validate_irq_address(irqf, mask)
+ irqframe_t *irqf;
+ u_int mask;
+{
+ return;
+ if (irqf->if_pc > (int)idle && irqf->if_pc < (int)switch_exit)
+ return;
+ if (irqf->if_pc > (int)SetCPSR && irqf->if_pc < (int)GetCPSR)
+ return;
+ if ((irqf->if_spsr & PSR_MODE) != PSR_USR32_MODE) {
+ printf("Alert! IRQ while in non USR mode (%08x) pc=%08x\n",
+ irqf->if_spsr, irqf->if_pc);
+ }
+ if ((GetCPSR() & I32_bit) == 0) {
+ printf("Alert! IRQ's enabled during IRQ handler\n");
+ }
+ if (irqf->if_pc >= (int)vgone && irqf->if_pc < (int)vfinddev)
+ printf("Alert! IRQ between vgone & vfinddev : pc=%08x\n",
+ irqf->if_pc);
+}
+
+
+/*
+ * int fiq_claim(fiqhandler_t *handler)
+ *
+ * Claim FIQ's and install a handler for them.
+ */
+
+int
+fiq_claim(handler)
+ fiqhandler_t *handler;
+{
+/* Fail if the FIQ's are already claimed */
+
+ if (fiqhandlers)
+ return(-1);
+
+ if (handler->fh_size > 0xc0)
+ return(-1);
+
+/* Install the handler */
+
+ fiqhandlers = handler;
+
+/* Now we have to actually install the FIQ handler */
+
+/* Eventually we will copy this down but for the moment ... */
+
+ zero_page_readwrite();
+
+ WriteWord(0x0000003c, (u_int) handler->fh_func);
+
+ zero_page_readonly();
+
+/* bcopy(handler->fh_func, 0x0000001c, handler->fh_size);*/
+
+/* We must now set up the FIQ registers */
+
+ fiq_setregs(handler);
+
+/* Set up the FIQ mask */
+
+ WriteWord(IOMD_FIQMSK, handler->fh_mask);
+
+/* Make sure that the FIQ's are enabled */
+
+ enable_interrupts(F32_bit);
+ return(0);
+}
+
+
+/*
+ * int fiq_release(fiqhandler_t *handler)
+ *
+ * Release FIQ's and remove a handler for them.
+ */
+
+int
+fiq_release(handler)
+ fiqhandler_t *handler;
+{
+/* Fail if the handler is wrong */
+
+ if (fiqhandlers != handler)
+ return(-1);
+
+/* Disable FIQ interrupts */
+
+ disable_interrupts(F32_bit);
+
+/* Clear up the FIQ mask */
+
+ WriteWord(IOMD_FIQMSK, 0x00);
+
+/* Remove the handler */
+
+ fiqhandlers = NULL;
+ return(0);
+}
+
+/* End of irqhandler.c */
--- /dev/null
+/* $NetBSD: kgdb_glue.c,v 1.2 1996/03/27 22:42:16 mark Exp $ */
+
+/*
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+
+#include <kgdb/kgdb.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/kgdb.h>
+
+int kgdbregs[NREG];
+
+dump(p, l)
+ u_char *p;
+{
+ int i, j, n;
+
+ while (l > 0) {
+ printf("%08x: ", p);
+ n = l > 16 ? 16 : l;
+ for (i = 4; --i >= 0;) {
+ for (j = 4; --j >= 0;)
+ printf(--n >= 0 ? "%02x " : " ", *p++);
+ printf(" ");
+ }
+ p -= 16;
+ n = l > 16 ? 16 : l;
+ n = (n + 3) & ~3;
+ for (i = 4; --i >= 0;)
+ printf((n -= 4) >= 0 ? "%08x " : "", *((long *)p)++);
+ printf("\n");
+ l -= 16;
+ }
+}
+
+#define NDBGSTKS 8 /* number of debugstacks */
+#define SZDBGSTK 512 /* size of one debugstack */
+static int debugstack[NDBGSTKS * SZDBGSTK];
+static int dbgstkused;
+
+int *
+kgdb_find_stack()
+{
+ int i;
+
+ for (i = 0; i < NDBGSTKS; i++)
+ if (!(dbgstkused&(1 << i))) {
+ dbgstkused |= 1 << i;
+ return debugstack + (i + 1) * SZDBGSTK;
+ }
+ panic("KGDB: no stack");
+}
+
+void
+kgdb_free_stack(sp)
+ int *sp;
+{
+ int i;
+
+ for (i = 0; i < NDBGSTKS; i++)
+ if (sp == debugstack + (i + 1) * SZDBGSTK) {
+ if (!(dbgstkused&(1 << i)))
+ panic("KGDB: free free stack");
+ dbgstkused &= ~(1 << i);
+ return;
+ }
+ panic("KGDB: free non-stack");
+}
+
+void
+kgdbinit()
+{
+ /* initialize undefined mode & setup trap vector */
+ initmode(PSR_UND32_MODE|F32_bit|I32_bit, kgdb_find_stack());
+}
+
+void
+kgdb_connect(when)
+ int when;
+{
+ boothowto |= RB_KDB;
+ if (when == 0)
+ printf("waiting for remote GDB\n");
+ __asm(".word 0xe6000010");
+}
+
+int
+kgdb_poll()
+{
+ return 0;
+}
+
+void
+kgdb_panic()
+{
+ kgdbpanic = 1;
+ __asm(".word 0xe6000010");
+}
+
+int
+kgdb_trap_glue(regs)
+ int *regs;
+{
+ int inst;
+ int cnt;
+
+ inst = fetchinst(regs[PC] - 4);
+ switch (inst) {
+ default:
+ /* unexpected */
+#ifdef __notyet__
+ return 0;
+#endif
+ case 0xe6000011: /* KGDB installed breakpoint */
+ regs[PC] -= 4;
+ break;
+ case 0xe6000010: /* breakpoint in kgdb_connect */
+ break;
+ }
+ while (1) {
+ kgdbcopy(regs, kgdbregs, sizeof kgdbregs);
+ switch (kgdbcmds()) {
+ case 1:
+ kgdbcopy(kgdbregs, regs, sizeof kgdbregs);
+ if ((cnt = singlestep(regs)) < 0)
+ panic("singlestep");
+ regs[PC] += cnt;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+ kgdbcopy(kgdbregs, regs, sizeof kgdbregs);
+ if (PSR_USER(regs[PSR]) || !PSR_32(regs[PSR]))
+ panic("KGDB: invalid mode %x", regs[PSR]);
+ return 1;
+}
+
+void
+kgdbcopy(vs, vd, n)
+ void *vs, *vd;
+ int n;
+{
+ char *s = vs, *d = vd;
+ long *ls, *ld;
+ int ln;
+
+ if (((int)s&(sizeof(long)-1)) == ((int)d&(sizeof(long)-1))
+ && n >= 2 * sizeof(long)) {
+ while (((int)s&(sizeof(long)-1)) && --n >= 0)
+ *d++ = *s++;
+ ln = n / sizeof(long);
+ n -= ln * sizeof(long);
+ ls = (long *)s;
+ ld = (long *)d;
+ while (--ln >= 0)
+ *ld++ = *ls++;
+ s = (char *)ls;
+ d = (char *)ld;
+ }
+ while (--n >= 0)
+ *d++ = *s++;
+}
+
+void
+kgdbzero(vd, n)
+ void *vd;
+ int n;
+{
+ char *d = vd;
+ long *ld;
+ int ln;
+
+ if (n >= 2 * sizeof(long)) {
+ while (--n >= 0) {
+ if (!((int)d&sizeof(long)-1))
+ break;
+ *d++ = 0;
+ }
+ ln = n / sizeof(long);
+ n -= ln * sizeof(long);
+ ld = (long *)d;
+ while (--ln >= 0)
+ *ld++ = 0;
+ d = (char *)ld;
+ }
+ while (--n >= 0)
+ *d++ = 0;
+}
+
+int
+kgdbcmp(vs, vd, n)
+ void *vs, *vd;
+ int n;
+{
+ char *s = vs, *d = vd;
+ long *ls, *ld;
+ int ln;
+
+ if (((int)s&(sizeof(long)-1)) == ((int)d&(sizeof(long)-1))
+ && n >= 2 * sizeof(long)) {
+ while (--n >= 0) {
+ if (!((int)s&(sizeof(long)-1)))
+ break;
+ if (*d++ != *s++)
+ return *--d - *--s;
+ }
+ ln = n / sizeof(long);
+ n -= ln * sizeof(long);
+ ls = (long *)s;
+ ld = (long *)d;
+ while (--ln >= 0)
+ if (*ld++ != *ls++) {
+ n += ++ln * sizeof(long);
+ break;
+ }
+ s = (char *)ls;
+ d = (char *)ld;
+ }
+ while (--n >= 0)
+ if (*d++ != *s++)
+ return *--d - *--s;
+ return 0;
+}
--- /dev/null
+/* $NetBSD: kgdb_step.c,v 1.2 1996/03/27 22:42:20 mark Exp $ */
+
+/*
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/kgdb.h>
+
+/*
+ * Faults during instruction fetch? XXX
+ */
+int
+fetchinst(pc)
+ void *pc;
+{
+ int inst, byte, n;
+
+ inst = 0;
+ pc += sizeof(int);
+ for (n = sizeof(int); --n >= 0;) {
+ inst <<= 8;
+ byte = kgdbfbyte(--pc);
+ if (byte < 0)
+ return 0xe7ffffff; /* special hack! */
+ inst |= byte;
+ }
+ return inst;
+}
+
+static __inline void
+execute(inst, args, regs)
+ int inst;
+ int *args;
+ int *regs;
+{
+ int *sp;
+
+ /*
+ * For now, no user level emulation
+ */
+ if (PSR_USER(regs[PSR]) || !PSR_32(regs[PSR]))
+ panic("execute");
+ sp = kgdb_find_stack();
+ regs[PSR] = Execute(inst, regs[PSR], args, sp);
+ kgdb_free_stack(sp);
+}
+
+static __inline int
+condition(inst, args, regs)
+ int inst;
+ int *args;
+ int *regs;
+{
+ args[0] = 0;
+ /* mov{cond} r0, #1 */
+ execute((inst&0xf0000000)|0x03a00001, args, regs);
+ return args[0];
+}
+
+static __inline int
+immediate(inst)
+ int inst;
+{
+ int imm = inst&0xff;
+ int rot = (inst >> 8)&0xf;
+
+ rot *= 2;
+ return (imm >> rot)|(imm << (32 - rot));
+}
+
+static __inline int
+getreg(reg, ahead, regs)
+ int reg;
+ int ahead;
+ int *regs;
+{
+ if (reg == PC)
+ return regs[PC] + (ahead ? 12 : 8);
+ return regs[reg];
+}
+
+static __inline void
+setreg(reg, val, regs)
+ int reg;
+ int val;
+ int *regs;
+{
+ if (reg == PC)
+ val &= ~3;
+ regs[reg] = val;
+}
+
+int
+singlestep(regs)
+ int *regs;
+{
+ int inst;
+ int args[5];
+ int dst, idx;
+ int val;
+
+ inst = fetchinst(regs[PC]);
+ switch (inst&0x0c000000) {
+ case 0x00000000:
+ if ((inst&0x0fb00ff0) == 0x01000090) {
+ /* swp */
+ dst = (inst >> 12)&0xf;
+ if (dst == PC)
+ return -1;
+ idx = inst&0xf;
+ if (idx == PC)
+ return -1;
+ args[0] = getreg(idx, 0, regs);
+ args[1] = getreg(dst, 0, regs);
+ idx = (inst >> 16)&0xf;
+ if (idx == PC)
+ return -1;
+ args[2] = getreg(idx, 0, regs);
+ execute((inst&0xf0400000)|0x01021090, args, regs);
+ setreg(dst, args[1], regs);
+ return 4;
+ }
+ if ((inst&0x0fbf0fff) == 0x01000090) {
+ /* mrs */
+ if ((regs[PSR]&0xf) == 0
+ && (inst&0x00400000))
+ /* mrs xx, spsr in user mode */
+ return 4; /* ??? */
+ dst = (inst >> 12)&0xf;
+ if (dst == PC)
+ return -1;
+ if (condition(inst, args, regs))
+ setreg(dst, regs[(inst&0x00400000) ? SPSR : PSR], regs);
+ return 4;
+ }
+ if ((inst&0x0fbffff0) == 0x0129f000) {
+ /* msr */
+ if (condition(inst, args, regs)) {
+ idx = inst&0xf;
+ if (idx == PC)
+ return -1;
+ val = getreg(idx, 0, regs);
+ if ((regs[PSR]&0xf) == 0) {
+ if (inst&0x00400000)
+ /* msr spsr, xx in user mode */
+ return 4; /* ??? */
+ val &= 0xf0000000;
+ val |= regs[PSR]&0x0fffffff;
+ }
+ regs[(inst&0x00400000) ? SPSR : PSR] = val;
+ }
+ return 4;
+ }
+ if ((inst&0x0dbff000) == 0x0128f000) {
+ /* msrf */
+ if (condition(inst, args, regs)) {
+ if ((regs[PSR]&0xf) == 0
+ && (inst&0x00400000))
+ /* msr spsr_flg, xx in user mode */
+ return 4; /* ??? */
+ if (inst&0x02000000)
+ val = immediate(inst);
+ else if (inst&0x00000ff0)
+ return -1;
+ else {
+ idx = inst&0xf;
+ if (idx == PC)
+ return -1;
+ val = getreg(idx, 0, regs);
+ }
+ val &= 0xf0000000;
+ val |= regs[PSR]&0x0fffffff;
+ regs[(inst&0x00400000) ? SPSR : PSR] = val;
+ }
+ return 4;
+ }
+ if ((inst&0x0fc000f0) == 0x00000090) {
+ /* mul/mla */
+ dst = (inst >> 16)&0xf;
+ if (dst == PC)
+ return -1;
+ idx = inst&0xf;
+ if (idx == dst || idx == PC)
+ return -1;
+ args[1] = getreg(idx, 0, regs);
+ idx = (inst >> 8)&0xf;
+ if (idx == PC)
+ return -1;
+ args[2] = getreg(idx, 0, regs);
+ idx = (inst >> 12)&0xf;
+ if (idx == PC)
+ return -1;
+ if (idx && !(inst&0x00200000))
+ /* mul with rn != 0 */
+ return -1;
+ args[0] = getreg(idx, 0, regs);
+ args[3] = getreg(dst, 0, regs);
+ execute((inst&0xfff00000)|0x30291, args, regs);
+ setreg(dst, args[3], regs);
+ return 4;
+ }
+ {
+ /* data processing */
+ if (condition(inst, args, regs)) {
+ dst = (inst >> 12)&0xf;
+ if (inst&0x00100000) {
+ /* S-Bit set */
+ if (dst == PC)
+ /* S-Bit set and destination is R15 */
+ return -1; /* not yet */
+ } else
+ /* S-Bit not set */
+ switch ((inst >> 21)&0xf) {
+ case 0x8: /* TST */
+ case 0x9: /* TEQ */
+ case 0xa: /* CMP */
+ case 0xb: /* CMN */
+ return -1;
+ }
+ val = ((inst&0x02000010) == 0x00000010);
+ args[0] = getreg((inst >> 16)&0xf, val, regs);
+ if (!(inst&0x02000000)) {
+ args[2] = getreg(inst&0xf, val, regs);
+ if (inst&0x00000010) {
+ if (inst&0x00000080)
+ return -1;
+ args[3] = getreg((inst >> 8)&0xf, val, regs);
+ inst = (inst&0xfff000f0)|0x00001302;
+ } else
+ inst = (inst&0xfff00ff0)|0x00001002;
+ } else
+ inst = (inst&0xfff00fff)|0x00001000;
+ execute(inst, args, regs);
+ switch ((inst >> 21)&0xf) {
+ case 0x8: /* TST */
+ case 0x9: /* TEQ */
+ case 0xa: /* CMP */
+ case 0xb: /* CMN */
+ break;
+ default:
+ setreg(dst, args[1], regs);
+ break;
+ }
+ return dst == PC ? 0 : 4;
+ }
+ return 4;
+ }
+ break;
+ case 0x04000000:
+ if ((inst&0x0e000010) == 0x06000010)
+ /* undefined */
+ return -1;
+ {
+ /* ldr/str */
+ if (condition(inst, args, regs)) {
+ dst = (inst >> 12)&0xf;
+ if (inst&0x00100000)
+ args[1] = regs[dst];
+ else
+ args[1] = getreg(dst, 1, regs);
+ val = (inst >> 16)&0xf;
+ if ((inst&0x00200000) && val == PC)
+ /* write back with pc as base */
+ return -1;
+ args[2] = getreg(val, 0, regs);
+ if (inst&0x02000000) {
+ if (inst&0x00000010)
+ /* shift amount in register */
+ return -1;
+ idx = inst&0xf;
+ if (idx == PC)
+ /* offset in PC */
+ return -1;
+ args[0] = getreg(idx, 0, regs);
+ inst = (inst&0xfff00ff0)|0x21000;
+ } else
+ inst = (inst&0xfff00fff)|0x21000;
+ execute(inst, args, regs);
+ if (inst&0x00200000)
+ regs[val] = args[2];
+ if (inst&0x00100000)
+ setreg(dst, args[1], regs);
+ return dst == PC ? 0 : 4;
+ }
+ return 4;
+ }
+ break;
+ case 0x08000000:
+ switch (inst&0x0e000000) {
+ case 0x08000000:
+ /* ldm/stm */
+ if (condition(inst, args, regs)) {
+ int cnt;
+ int val, is1;
+ int final;
+
+ if (inst&0x00400000)
+ /* S-bit not yet supported */
+ return -1;
+ dst = (inst >> 16)&0xf;
+ if (dst == PC)
+ return -1;
+ args[0] = final = val = getreg(dst, 0, regs);
+ cnt = 0;
+ is1 = 0;
+ for (idx = 0; idx < 16; idx++)
+ if ((inst&(1 << idx))
+ && (cnt += 4) <= 4 /* count the registers */
+ && idx == dst)
+ /* indicate unmodified store */
+ is1 = 1;
+ if ((inst&0x00300000) == 0x00200000
+ && (inst&(1 << dst))
+ && !is1) {
+ /*
+ * The destination is in the list of a stm
+ * with write-back and is not the first
+ * register
+ */
+ if (inst&0x00800000)
+ val -= cnt;
+ else
+ val += cnt;
+ }
+ if (!(inst&0x00800000)) {
+ /* lowest address involved */
+ args[0] -= cnt;
+ if (!(inst&0x01000000))
+ /* post-decrement */
+ args[0] += 4;
+ if (inst&0x00200000)
+ final -= cnt;
+ } else {
+ if (inst&0x01000000)
+ /* pre-increment */
+ args[0] += 4;
+ if (inst&0x00200000)
+ final += cnt;
+ }
+ for (idx = 0; idx < 16; idx++)
+ if (inst&(1 << idx)) {
+ args[1] = dst == idx
+ ? val
+ : getreg(idx, 1, regs);
+ execute((inst&0xfe100000)|0x00a00002, args, regs);
+ if (inst&0x00100000)
+ regs[idx] = args[1];
+ }
+ switch (inst&0x00300000) {
+ case 0x00300000: /* ldm! */
+ if (inst&(1 << dst))
+ break;
+ case 0x00200000: /* stm! */
+ regs[dst] = final;
+ break;
+ }
+ return (inst&(1 << PC)) && (inst&0x00100000) ? 0 : 4;
+ }
+ return 4;
+ case 0x0a000000:
+ /* branch */
+ if (condition(inst, args, regs)) {
+ if (inst&0x01000000)
+ regs[LR] = regs[PC] + 4;
+ if (inst&0x00800000)
+ inst |= 0xff000000;
+ else
+ inst &= ~0xff000000;
+ regs[PC] += 8 + (inst << 2);
+ return 0;
+ }
+ return 4;
+ }
+ break;
+ case 0x0c000000:
+ switch (inst&0x0f000000) {
+ case 0x0c000000:
+ case 0x0d000000:
+ /* ldc/stc */
+ return -1;
+ case 0x0f000000:
+ /* swi */
+ return -1;
+ case 0x0e000000:
+ /* cdp/mrc/mcr */
+ if ((regs[PSR]&0xf) == 0)
+ /* user mode */
+ return -1;
+ if ((inst&0x00e00fff) != 0x00000f10)
+ /* cdp, different cp# or unknown operation */
+ return -1;
+ dst = (inst >> 12)&0xf;
+ if (dst == PC)
+ args[0] = regs[PSR];
+ else
+ args[0] = getreg(dst, 1, regs);
+ execute(inst&0xffff0fff, args, regs);
+ if (!(inst&0x00100000))
+ if (dst == PC)
+ regs[PSR] = (regs[PSR]&0x0fffffff)
+ |(args[0]&0xf0000000);
+ else
+ regs[dst] = args[0];
+ return 4;
+ }
+ break;
+ }
+ return -1;
+}
--- /dev/null
+/* $NetBSD: locore.S,v 1.8 1996/03/20 18:57:58 mark Exp $ */
+
+/*
+ * Copyright (C) 1994 Mark Brinicombe
+ * Copyright (C) 1994 Brini
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of Brini may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "assym.h"
+#include <machine/asm.h>
+#include <machine/cpu.h>
+#include <machine/param.h>
+#include <sys/syscall.h>
+
+/* What size shoudl this really be ? It is only used by init_arm() */
+
+#define INIT_ARM_STACK_SIZE 2048
+
+#define PUSHFRAME \
+ str lr, [sp, #-4]!; /* Push the return address */ \
+ sub sp, sp, #0x00000004; /* Skip SVC R14 */ \
+ stmdb sp, {r0-r14}^; /* Push the user mode registers */ \
+ sub sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ mrs r0, spsr_all; /* Put the SPSR on the stack */ \
+ str r0, [sp, #-4]!;
+
+#define PULLFRAME \
+ ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \
+ msr spsr_all, r0; \
+ add sp, sp, #(4*15); /* Adjust the stack pointer */ \
+ ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \
+ mov r0, r0; /* NOP for previous instruction */ \
+ add sp, sp, #0x00000004; /* Skip SVC R14 */ \
+ ldr lr, [sp], #0x0004; /* Pull the return address */
+
+/* register equates */
+fp .req r11
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+ .align 0
+ .global start
+start:
+ add r1, pc, #(Lstart - . - 8)
+ ldmia r1, { r1, r2, r13 } /* Set initial stack and */
+ sub r2, r2, r1 /* get zero init data */
+ mov r3, #0
+
+L1:
+ str r3, [r1], #0x0004 /* Zero the bss */
+ subs r2, r2, #4
+ bgt L1
+
+ mov fp, #0x00000000 /* trace back starts here */
+ bl _initarm /* Off we go */
+
+/* init arm will return the new stack pointer. */
+
+ mov sp, r0
+
+/* Debug code */
+
+/* mov r1, sp
+ add r0, pc, #(Ltext9 - . - 8)
+ bl _printf
+*/
+
+/* Setup an initial trap frame for start_init to use */
+
+ PUSHFRAME
+
+ mov fp, #0x00000000 /* trace back starts here */
+ mov r0, sp /* parameter to main is trap frame*/
+
+/* Debug */
+
+#if 0
+stmfd r13!, {r0-r3}
+ ldr r1, Lproc0
+ ldr r2, [r1]
+/* mov r1, r0*/
+ add r0, pc, #(Ltext7 - . - 8)
+ bl _printf
+ldmfd r13!, {r0-r3}
+#endif
+
+ bl _main /* Lets light the flame and start her up */
+
+ PULLFRAME /* Pull the trap frame, now valid */
+
+ movs pc, lr /* Exit to user process */
+
+/* Never gets here */
+
+ b .
+
+Lstart:
+ .word _edata
+ .word _end
+ .word svcstk + INIT_ARM_STACK_SIZE
+
+Lproc0:
+ .word _proc0
+
+/*
+Ltext7:
+ .asciz "proc0=%08x %08x\n"
+ .align 0
+
+
+Ltext9:
+ .asciz "proc0 stack at V%08x %08x\n"
+ .align 0
+*/
+
+/* What size shoudl this really be ? It is only used by init_arm() */
+
+ .bss
+svcstk: .space INIT_ARM_STACK_SIZE
+
+/*
+ * Instructions to copy to the bottom of zero page
+ * These are the entry point to the system exception routines
+ */
+
+ .text
+ .align 0
+ .global _page0, _page0_end
+_page0:
+ ldr pc, [pc, #Lreset - . - 8]
+ ldr pc, [pc, #Lundefined - . - 8]
+ ldr pc, [pc, #Lswi - . - 8]
+ ldr pc, [pc, #Labortpre - . - 8]
+ ldr pc, [pc, #Labortdata - . - 8]
+ ldr pc, [pc, #Laddrexc - . - 8]
+ ldr pc, [pc, #Lirq - . - 8]
+ ldr pc, [pc, #Lfiq - . - 8]
+
+Lreset:
+ .word reset_entry
+Lundefined:
+ .word undefined_entry
+Lswi:
+ .word swi_entry
+Labortpre:
+ .word prefetch_abort_entry
+Labortdata:
+ .word data_abort_entry
+Laddrexc:
+ .word addrexc
+Lirq:
+ .word irq_entry
+
+Lfiq:
+ .word fiq
+_page0_end = .
+
+#if 0
+reset:
+ add r0, pc, #Wreset - . - 8
+ ldmia r0, {r0, pc}
+resetmsg:
+ .asciz "reset"
+ .align 0
+Wreset:
+ .word resetmsg
+ .word _panic
+#endif
+
+reset_entry:
+ PUSHFRAME
+
+ mov r0, sp /* Pass the frame to any function */
+
+ bl _resethandler /* It's a branch throught zero ! */
+
+ PULLFRAME
+
+ movs pc, lr /* Exit */
+
+#if 0
+undefined:
+#ifndef KGDB
+ add r0, pc, #Wundefined - . - 8
+ ldmia r0, {r0, pc}
+undmsg:
+ .asciz "undefined"
+ .align 0
+Wundefined:
+ .word undmsg
+ .word _panic
+#else
+/*
+ * lr is the saved pc, and we make space for the saved psr
+ */
+ stmfd sp!, {lr, pc}
+/*
+ * now save all the rest of the registers (r13&r14) are redone later
+ */
+ stmfd sp!, {r0-lr}
+/*
+ * now switch to the old mode to get r13&r14, but disable interrupts
+*/
+/* stupid gas doesn't yet know about the psr transfers */
+ .word 0xe10f3000 @ mrs r3, cpsr
+ .word 0xe14f2000 @ mrs r2, spsr
+ str r2, [sp, #64]
+ orr r2, r2, #(PSR_FIQ32_MODE|PSR_IRQ32_MODE)
+ .word 0xe129f002 @ msr cpsr, r2
+ mov r0, r13
+ mov r1, r14
+ orr r3, r3, #(PSR_FIQ32_MODE|PSR_IRQ32_MODE)
+ .word 0xe129f003 @ msr cpsr, r3
+ str r0, [sp, #52]
+ str r1, [sp, #56]
+ mov r0, sp
+ mov lr, pc
+ ldr pc, [pc, #Wundefined - . - 8]
+ add sp, sp, #52 /* adjust stack to r13 */
+/*
+ * set saved psr and get r13&r14 to new (saved) mode first
+ */
+ ldr r2, [sp, #12]
+ ldr r0, [sp]
+ ldr r1, [sp, #4]
+/* stupid gas doesn't yet know about the psr transfers */
+ .word 0xe169f002 @ msr spsr, r2
+ .word 0xe10f3000 @ mrs r3, cpsr
+ orr r2, r2, #(PSR_FIQ32_MODE|PSR_IRQ32_MODE)
+ .word 0xe129f002 @ msr cpsr, r2
+ mov r13, r0
+ mov r14, r1
+ .word 0xe129f003 @ msr cpsr, r3
+ ldmea sp, {r0-r12} /* now the rest of the registers */
+ add sp, sp, #16 /* Adjust stack to top */
+ ldr lr, [sp, #-8] /* get link address */
+ movs pc, lr /* return */
+Wundefined:
+ .word _kgdb_trap_glue
+#endif
+#endif
+
+addrexc:
+ .word 0xe10f1000
+ .word 0xe14f2000
+ mov r3, lr
+ add r0, pc, #addrexcmsg - . - 8
+ bl _printf
+ b data_abort_entry
+
+addrexcmsg:
+ .asciz "address exception CPSR=%08x SPSR=%08x lr=%08x\n"
+ .align 0
+Waddrexc:
+ .word addrexcmsg
+ .word _panic
+
+irq:
+ add r0, pc, #Wirq - . - 8
+ ldmia r0, {r0, pc}
+irqmsg:
+ .asciz "irq"
+ .align 0
+Wirq:
+ .word irqmsg
+ .word _panic
+
+fiq:
+ add r0, pc, #Wfiq - . - 8
+ ldmia r0, {r0, pc}
+fiqmsg:
+ .asciz "fiq"
+ .align 0
+Wfiq:
+ .word fiqmsg
+ .word _panic
+
+ .global _initmode
+_initmode:
+/* stupid gas doesn't yet know about the psr transfers */
+ mrs r2, cpsr_all
+ msr cpsr_all, r0
+ mov sp, r1
+ msr cpsr_all, r2
+ mov pc, lr
+
+
+ .global _boot0
+_boot0:
+ mrs r2, cpsr_all
+ bic r2, r2, #(PSR_MODE)
+ orr r2, r2, #(PSR_SVC32_MODE)
+ orr r2, r2, #(I32_bit | F32_bit)
+ msr cpsr_all, r2
+
+ mov r0, #0
+ mcr 15, 0, r0, c1, c0, 0
+ mov pc, r0
+
+
+/* Debug routine to print trace back information from stack */
+
+ .global _traceback
+
+_traceback:
+ stmfd sp!, {r4, r5, r6, lr}
+ mov r4, r11
+ ldr r5, Ltracebackmin
+ ldr r6, Ltracebackmax
+
+tbloop:
+ mov r1, r4
+ ldr r2, [r4, #-12]
+ ldr r3, [r4, #-8]
+ add r0, pc, #Ltb1 - . - 8
+ bl _printf
+
+/* ldr r1, [r4, #-4]
+ ldr r2, [r4]
+ add r0, pc, #Ltb2 - . - 8
+ bl _printf*/
+ ldr r0, [r4, #-4]
+ ldr r1, [r4]
+ bl _traceback_sym
+
+ mov r3, r4
+ ldr r4, [r4, #-12]
+ teq r3, r4
+ beq tbexit
+ cmp r4, r5
+ bls tbexit
+ cmp r4, r6
+ bge tbexit
+ teq r4, #0x00000000
+ bne tbloop
+
+tbexit:
+ mov r0, r4
+ ldmfd sp!, {r4, r5, r6, pc}
+
+Ltracebackmin:
+ .word 0xefbfe000
+
+Ltracebackmax:
+ .word 0xefc00000
+
+Ltb1:
+ .asciz "traceback: fp=%08x fp->fp=%08x fp->sp=%08x "
+
+Ltb2:
+ .asciz "fp->lr=%08x fp->pc=%08x\n"
+
+ .align 0
+
+/* Debug routine to print trace back information from stack */
+
+ .global _simpletraceback
+
+_simpletraceback:
+ stmfd sp!, {r4, r5, r6, lr}
+ mov r4, r11
+ ldr r5, Ltracebackmin
+ ldr r6, Ltracebackmax
+
+stbloop:
+/* ldr r1, [r4, #-4]
+ ldr r2, [r4]
+ add r0, pc, #Ltb2 - . - 8
+ bl _printf*/
+ ldr r0, [r4, #-4]
+ ldr r1, [r4]
+ bl _traceback_sym
+
+ mov r3, r4
+ ldr r4, [r4, #-12]
+ teq r3, r4
+ beq stbexit
+ cmp r4, r5
+ bls stbexit
+ cmp r4, r6
+ bge stbexit
+ teq r4, #0x00000000
+ bne stbloop
+
+stbexit:
+ mov r0, r4
+ ldmfd sp!, {r4, r5, r6, pc}
+
+
+/* Debug routine to print trace back information from stack */
+
+ .global _irqtraceback
+
+_irqtraceback:
+ stmfd sp!, {r4, r5, r6, lr}
+ mov r4, r0
+ mov r5, r1
+ add r6, r5, #(NBPG)
+
+itbloop:
+ mov r1, r4
+ ldr r2, [r4, #-12]
+ ldr r3, [r4, #-8]
+ add r0, pc, #Ltb1 - . - 8
+ bl _printf
+
+/* ldr r1, [r4, #-4]
+ ldr r2, [r4]
+ add r0, pc, #Ltb2 - . - 8
+ bl _printf*/
+ ldr r0, [r4, #-4]
+ ldr r1, [r4]
+ bl _traceback_sym
+
+ mov r3, r4
+ ldr r4, [r4, #-12]
+ teq r3, r4
+ beq itbexit
+ cmp r4, r5
+ bls itbexit
+ cmp r4, r6
+ bge itbexit
+ teq r4, #0x00000000
+ bne itbloop
+
+itbexit:
+ mov r0, r4
+ ldmfd sp!, {r4, r5, r6, pc}
+
+
+ .global _user_traceback
+
+_user_traceback:
+ stmfd sp!, {r4, r5, r6, lr}
+ mov r4, r0
+ ldr r5, Lusertracebackmin
+ ldr r6, Lusertracebackmax
+
+usertbloop:
+ mov r1, r4
+ ldr r2, [r4, #-12]
+ ldr r3, [r4, #-8]
+ add r0, pc, #Lusertb1 - . - 8
+ bl _printf
+
+ ldr r1, [r4, #-4]
+ ldr r2, [r4]
+ add r0, pc, #Lusertb2 - . - 8
+ bl _printf
+
+ mov r3, r4
+ ldr r4, [r4, #-12]
+ teq r3, r4
+ beq usertbexit
+ cmp r4, r5
+ bls tbexit
+ cmp r4, r6
+ bge usertbexit
+ teq r4, #0x00000000
+ bne usertbloop
+
+usertbexit:
+ mov r0, r4
+ ldmfd sp!, {r4, r5, r6, pc}
+
+Lusertracebackmin:
+ .word 0x00001000
+
+Lusertracebackmax:
+ .word 0xefbfe000
+
+Lusertb1:
+ .asciz "traceback: fp=%08x fp->fp=%08x fp->sp=%08x "
+
+Lusertb2:
+ .asciz "fp->lr=%08x fp->pc=%08x\n"
+
+ .align 0
+
+
+
+/*
+ * Signal trampoline; copied to top of user stack.
+ */
+ .global _sigcode
+ENTRY(sigcode)
+/*
+ * r0-r2 are our signal handler parameters
+ * r3 is the handler address
+ */
+
+ add lr, pc, #0 /* Set return address */
+ mov pc, r3 /* Call the handler */
+
+/*
+ * Call sig_return with address of the signal context
+ * Note: Don't use SIG_SCP as this make have been trashed by the program
+ */
+ add r0, sp, #SIGF_SC
+ swi SYS_sigreturn
+
+/* Well if that failed we better exit quick ! */
+
+ add r0, pc, #Lsigerr - . - 8
+ swi 0x1002
+
+ swi SYS_exit
+
+Lsigerr:
+ .asciz "sigreturn syscall failed\n"
+ .align 0
+ .globl _esigcode
+_esigcode:
+
+/*
+ * setjump + longjmp
+ */
+ .global _setjmp
+ENTRY(setjmp)
+ stmia r0, {r4-r14}
+ mov r0, #0x00000000
+ mov r15, r14
+
+ .global _longjmp
+ENTRY(longjmp)
+ ldmia r2, {r4-r14}
+ mov r0, #0x00000001
+ mov r15, r14
+
+ .global _esym
+_esym: .word _end
+
+ .global _abort
+_abort:
+ b _abort
--- /dev/null
+/* $NetBSD: machdep.c,v 1.6 1996/03/13 21:32:39 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * machdep.c
+ *
+ * Machine dependant functions for kernel setup
+ *
+ * This file needs a lot of work.
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/callout.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/buf.h>
+#include <sys/map.h>
+#include <sys/exec.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/device.h>
+#include <sys/sysctl.h>
+#include <sys/syscallargs.h>
+
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+#ifdef SYSVSEM
+#include <sys/sem.h>
+#endif
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+
+#include <vm/vm_kern.h>
+
+#include <machine/signal.h>
+#include <machine/frame.h>
+#include <machine/bootconfig.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#include <machine/vidc.h>
+#include <machine/iomd.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/undefined.h>
+#include <machine/rtc.h>
+
+#include "hydrabus.h"
+
+/* Describe different actions to take when boot() is called */
+
+#define ACTION_HALT 0x01 /* Halt and boot */
+#define ACTION_REBOOT 0x02 /* Halt and request RiscBSD reboot */
+#define ACTION_KSHELL 0x04 /* Call kshell */
+#define ACTION_DUMP 0x08 /* Dump the system to the dump dev */
+
+#define HALT_ACTION ACTION_HALT | ACTION_KSHELL /* boot(RB_HALT) */
+#define REBOOT_ACTION ACTION_REBOOT /* boot(0) */
+#define PANIC_ACTION ACTION_HALT | ACTION_KSHELL /* panic() */
+
+BootConfig bootconfig; /* Boot config storage */
+videomemory_t videomemory; /* Video memory descriptor */
+
+vm_offset_t physical_start;
+vm_offset_t physical_freestart;
+vm_offset_t physical_freeend;
+vm_offset_t physical_end;
+int physical_memoryblock;
+u_int free_pages;
+vm_offset_t pagetables_start;
+int physmem = 0;
+
+int debug_flags;
+int max_processes;
+int cpu_cache;
+int cpu_ctrl;
+
+u_int ramdisc_size; /* Ramdisc size */
+
+u_int kmodule_base;
+u_int kmodule_size;
+
+u_int videodram_size; /* Amount of DRAM to reserve for video */
+vm_offset_t videodram_start;
+
+vm_offset_t physical_pt_start;
+vm_offset_t virtual_pt_end;
+
+u_int *cursor_data; /* Will move to the vidc code */
+
+typedef struct {
+ vm_offset_t physical;
+ vm_offset_t virtual;
+} pv_addr_t;
+
+pv_addr_t systempage;
+pv_addr_t irqstack;
+pv_addr_t undstack;
+pv_addr_t abtstack;
+pv_addr_t kernelstack;
+#if NHYDRABUS > 0
+pv_addr_t hydrascratch;
+#endif
+
+pt_entry_t kernel_pt_table[15];
+
+/* the following is used externally (sysctl_hw) */
+char machine[] = "arm32"; /* cpu "architecture" */
+
+char *boot_args;
+
+extern pt_entry_t msgbufpte;
+int msgbufmapped;
+vm_offset_t msgbufphys;
+
+extern u_int data_abort_handler_address;
+extern u_int prefetch_abort_handler_address;
+extern u_int undefined_handler_address;
+
+extern int pmap_debug_level;
+
+#define KERNEL_PT_PAGEDIR 0
+#define KERNEL_PT_PDE 1
+#define KERNEL_PT_PTE 2
+#define KERNEL_PT_VMEM 3
+#define KERNEL_PT_SYS 4
+#define KERNEL_PT_KERNEL 5
+#define KERNEL_PT_VMDATA0 6
+#define KERNEL_PT_VMDATA1 7
+#define KERNEL_PT_VMDATA2 8
+#define KERNEL_PT_VMDATA3 9
+#define KERNEL_PT_VMDATA4 10
+#define KERNEL_PT_VMDATA5 11
+#define KERNEL_PT_VMDATA6 12
+#define KERNEL_PT_VMDATA7 13
+#define KERNEL_PT_VMDATA7 13
+#define KERNEL_PT_KSTACK 14
+
+struct user *proc0paddr;
+
+/*
+ * Declare these as initialized data so we can patch them.
+ */
+int nswbuf = 0;
+#ifdef NBUF
+int nbuf = NBUF;
+#else
+int nbuf = 0;
+#endif
+#ifdef BUFPAGES
+int bufpages = BUFPAGES;
+#else
+int bufpages = 0;
+#endif
+
+int cold = 1;
+
+/* Prototypes */
+
+void boot0 __P((void));
+void bootsync __P((void));
+
+char *strstr __P((char */*s1*/, char */*s2*/));
+
+void physconputchar __P((char));
+void physcon_display_base __P((u_int));
+void consinit __P((void));
+
+void map_section __P((vm_offset_t, vm_offset_t, vm_offset_t));
+void map_pagetable __P((vm_offset_t, vm_offset_t, vm_offset_t));
+void map_entry __P((vm_offset_t, vm_offset_t va, vm_offset_t));
+void map_entry_ro __P((vm_offset_t, vm_offset_t, vm_offset_t));
+
+void pmap_bootstrap __P((vm_offset_t /*kernel_l1pt*/));
+void process_kernel_args __P((void));
+u_long strtoul __P((const char */*s*/, char **/*ptr*/, int /*base*/));
+caddr_t allocsys __P((caddr_t /*v*/));
+void identify_cpu __P((void));
+void data_abort_handler __P((trapframe_t */*frame*/));
+void prefetch_abort_handler __P((trapframe_t */*frame*/));
+void undefinedinstruction_bounce __P((trapframe_t */*frame*/));
+void set_boot_devs __P((void));
+void configure __P((void));
+void zero_page_readonly __P((void));
+void zero_page_readwrite __P((void));
+u_int disassemble __P((u_int /*addr*/));
+int setup_cursor __P((void));
+void init_fpe_state __P((struct proc *));
+
+void pmap_debug __P((int /*level*/));
+void dumpsys __P((void));
+void hydrastop __P((void));
+
+void vtbugreport __P((void));
+
+/*
+ * Debug function just to park the CPU
+ *
+ * This should be updated to power down an ARM7500
+ */
+
+void
+halt()
+{
+ while (1);
+}
+
+
+/*
+ * void boot(int howto)
+ *
+ * Reboots the system
+ *
+ * This gets called when a reboot is request by the user or after a panic.
+ * Call boot0() will reboot the machine. For the moment we will try and be
+ * clever and return to the booting environment. This may work if we
+ * have be booted with the Kate boot loader as long as we have not messed
+ * the system up to much. Until we have our own memory management running
+ * this should work. The only use of being able to return (to RISC OS)
+ * is so I don't have to wait while the machine reboots.
+ */
+
+/* NOTE: These variables will be removed, well some of them */
+
+extern u_int spl_mask;
+extern u_int current_mask;
+struct pcb dumppcb;
+extern u_int arm700bugcount;
+extern int ioctlconsolebug;
+
+void
+boot(howto)
+ int howto;
+{
+ int loop;
+ int action;
+
+/* Debugging here */
+
+ if (curproc == NULL)
+ printf("curproc = 0 - must have been in cpu_idle()\n");
+
+/* if (panicstr)
+ printf("ioctlconsolebug=%d %08x\n", ioctlconsolebug, ioctlconsolebug);*/
+
+/* if (curpcb)
+ printf("curpcb=%08x pcb_sp=%08x pcb_und_sp=%08x\n", curpcb, curpcb->pcb_sp, curpcb->pcb_und_sp);*/
+
+#if NHYDRABUS > 0
+/*
+ * If we are halting the master then we should halt the slaves :-)
+ * otherwise it can get a bit disconcerting to have 4 other
+ * processor still tearing away doing things.
+ */
+
+ hydrastop();
+#endif
+
+/* Debug info */
+
+ printf("boot: howto=%08x %08x curproc=%08x\n", howto, spl_mask, (u_int)curproc);
+
+ printf("current_mask=%08x spl_mask=%08x\n", current_mask, spl_mask);
+ printf("ipl_bio=%08x ipl_net=%08x ipl_tty=%08x ipl_clock=%08x ipl_imp=%08x\n",
+ irqmasks[IPL_BIO], irqmasks[IPL_NET], irqmasks[IPL_TTY],
+ irqmasks[IPL_CLOCK], irqmasks[IPL_IMP]);
+
+ dump_spl_masks();
+
+/* vtbugreport();*/
+
+/* Did we encounter the ARM700 bug we discovered ? */
+
+ if (arm700bugcount > 0)
+ printf("ARM700 PREFETCH/SWI bug count = %d\n", arm700bugcount);
+
+/* Disable console buffering */
+
+ cnpollc(1);
+
+/* If we are still cold then hit the air brakes */
+
+ if (cold) {
+ printf("Halted while still in the ICE age.\n");
+ printf("Hit a key to reboot\n");
+ cngetc();
+ boot0();
+ }
+
+/*
+ * Depending on how we got here and with what intructions, choose
+ * the actions to take. (See the actions defined above)
+ */
+
+ if (panicstr)
+ action = PANIC_ACTION;
+ else if (howto & RB_HALT)
+ action = HALT_ACTION;
+ else
+ action = REBOOT_ACTION;
+
+/*
+ * If RB_NOSYNC was not specified sync the discs.
+ * Note: Unless cold is set to 1 here, syslogd will die during the unmount.
+ * It looks like syslogd is getting woken up only to find that it cannot
+ * page part of the binary in as the filesystem has been unmounted.
+ */
+
+
+ if (!(howto & RB_NOSYNC)) {
+ cold = 1; /* no sleeping etc. */
+ bootsync();
+ }
+
+/* Say NO to interrupts */
+
+ splhigh();
+
+#ifdef KSHELL
+
+/* Now enter our crude debug shell if required. Soon to be replaced with DDB */
+
+ if (action & ACTION_KSHELL)
+ shell();
+#else
+ if (action & ACTION_KSHELL) {
+ printf("Halted.\n");
+ printf("Hit a key to reboot ");
+ cngetc();
+ }
+#endif
+
+/* Auto reboot overload protection */
+
+/*
+ * This code stops the kernel entering an endless loop of reboot - panic
+ * cycles. This will only effect kernels that have been configured to
+ * reboot on a panic and will have the effect of stopping further reboots
+ * after it has rebooted 16 times after panics and clean halt or reboot
+ * will reset the counter.
+ */
+
+/*
+ * Have we done 16 reboots in a row ? If so halt rather than reboot
+ * since 16 panics in a row without 1 clean halt means something is
+ * seriously wrong
+ */
+
+ if (cmos_read(RTC_ADDR_REBOOTCNT) > 16)
+ action = (action & ~ACTION_REBOOT) | ACTION_HALT;
+
+/*
+ * If we are rebooting on a panic then up the reboot count otherwise reset
+ * This will thus be reset if the kernel changes the boot action from
+ * reboot to halt due to too any reboots.
+ */
+
+ if ((action & ACTION_REBOOT) && panicstr)
+ cmos_write(RTC_ADDR_REBOOTCNT,
+ cmos_read(RTC_ADDR_REBOOTCNT) + 1);
+ else
+ cmos_write(RTC_ADDR_REBOOTCNT, 0);
+
+/*
+ * If we need a RiscBSD reboot, request it but setting a bit in the CMOS RAM
+ * This can be detected by the RiscBSD boot loader during a RISC OS boot
+ * No other way to do this as RISC OS is in ROM.
+ */
+
+ if (action & ACTION_REBOOT)
+ cmos_write(RTC_ADDR_BOOTOPTS,
+ cmos_read(RTC_ADDR_BOOTOPTS) | 0x02);
+
+/* If we need to do a dump, do it */
+
+ if ((howto & RB_DUMP) && (action & ACTION_DUMP)) {
+ savectx(&dumppcb);
+ dumpsys();
+ }
+
+/* Run any shutdown hooks */
+
+ printf("Running shutdown hooks ...\n");
+ doshutdownhooks();
+
+/* Make sure IRQ's are disabled */
+
+ IRQdisable;
+
+/* Tell the user we are booting */
+
+ printf("boot...");
+
+/* Give the user time to read the last couple of lines of text. */
+
+ for (loop = 5; loop > 0; --loop) {
+ printf("%d..", loop);
+ delay(500000);
+ }
+
+ boot0();
+}
+
+
+/* Sync the discs and unmount the filesystems */
+
+void
+bootsync(void)
+{
+ int iter;
+ int nbusy;
+ struct buf *bp;
+ static int bootsyncdone = 0;
+
+ if (bootsyncdone) return;
+
+ bootsyncdone = 1;
+
+/* Make sure we can still manage to do things */
+
+ if (GetCPSR() & I32_bit) {
+/*
+ * If we get then boot has been called with out RB_NOSYNC and interrupts were
+ * disabled. This means the boot() call did not come from a user process e.g.
+ * shutdown, but must have come from somewhere in the kernel.
+ */
+
+ IRQenable;
+ printf("Warning IRQ's disabled during boot()\n");
+ }
+
+ vfs_shutdown();
+}
+
+
+/*
+ * Estimated loop for n microseconds
+ */
+
+/* Need to re-write this to use the timers */
+
+/* One day soon I will actually do this */
+
+void
+delay(n)
+ u_int n;
+{
+ u_int i;
+
+ while (--n > 0)
+ for (i = 8; --i;);
+}
+
+
+/*
+ * u_int initarm(BootConfig *bootconf)
+ *
+ * Initial entry point on startup. This gets called before main() is
+ * entered.
+ * It should be responcible for setting up everything that must be
+ * in place when main is called.
+ * This includes
+ * Taking a copy of the boot configuration structure.
+ * Initialising the physical console so characters can be printed.
+ * Setting up page tables for the kernel
+ * Relocating the kernel to the bottom of physical memory
+ */
+
+/* This routine is frightening mess ! This is what my mind looks like -mark */
+
+u_int
+initarm(bootconf)
+ BootConfig *bootconf;
+{
+ int loop;
+ int loop1;
+ u_int logical;
+ u_int physical;
+ u_int kerneldatasize;
+ u_int l1pagetable;
+ u_int l2pagetable;
+ extern char page0[], page0_end[];
+ struct exec *kernexec = (struct exec *)KERNEL_BASE;
+
+/* Copy the boot configuration structure */
+
+ bootconfig = *bootconf;
+
+/*
+ * Initialise the video memory descriptor
+ *
+ * This will change in the future to correctly report DRAM as well
+ * but for the moment hardwire it. This will allow the console code
+ * to use the structure now.
+ *
+ * Note: all references to the video memory virtual/physical address
+ * should go via this structure.
+ */
+
+/*
+ * In the future ...
+ *
+ * All console output will be postponed until the primary bootstrap
+ * has been completed so that we have had a chance to reserve some
+ * memory for the video system if we do not have separate VRAM.
+ */
+
+ videomemory.vidm_vbase = bootconfig.display_start;
+ videomemory.vidm_pbase = VRAM_BASE;
+ videomemory.vidm_type = VIDEOMEM_TYPE_VRAM;
+ videomemory.vidm_size = bootconfig.display_size;
+
+/*
+ * Initialise the physical console
+ * This is done in main() but for the moment we do it here so that
+ * we can use printf in initarm() before main() has been called.
+ */
+
+ consinit();
+
+/* Talk to the user */
+
+ printf("initarm...\n");
+
+ printf("Kernel loaded from file %s\n", bootconfig.kernelname);
+ printf("Kernel arg string %s\n", (char *)bootconfig.argvirtualbase);
+
+ printf("\nBoot configuration structure reports the following memory\n");
+
+ printf(" DRAM block 0a at %08x size %08x DRAM block 0b at %08x size %08x\n\r",
+ bootconfig.dram[0].address,
+ bootconfig.dram[0].pages * bootconfig.pagesize,
+ bootconfig.dram[1].address,
+ bootconfig.dram[1].pages * bootconfig.pagesize);
+ printf(" DRAM block 1a at %08x size %08x DRAM block 1b at %08x size %08x\n\r",
+ bootconfig.dram[2].address,
+ bootconfig.dram[2].pages * bootconfig.pagesize,
+ bootconfig.dram[3].address,
+ bootconfig.dram[3].pages * bootconfig.pagesize);
+ printf(" VRAM block 0 at %08x size %08x\n\r",
+ bootconfig.vram[0].address,
+ bootconfig.vram[0].pages * bootconfig.pagesize);
+
+ printf(" videomem = %08x %08x\n", bootconfig.display_start, videomemory.vidm_vbase);
+
+/* Check to make sure the page size is correct */
+
+ if (NBPG != bootconfig.pagesize)
+ panic("Page size is not %d bytes\n", NBPG);
+
+/*
+ * Ok now we have the hard bit.
+ * We have the kernel allocated up high. The rest of the memory map is
+ * available. We are still running on RISC OS page tables.
+ *
+ * We need to construct new page tables move the kernel in physical
+ * memory and switch to them.
+ *
+ * The booter will have left us 6 pages at the top of memory.
+ * Two of these are used as L2 page tables and the other 4 form the L1
+ * page table.
+ */
+
+/*
+ * Ok we must construct own own page table tables.
+ * Once we have these we can reorganise the memory as required
+ */
+
+/*
+ * We better check to make sure the booter has set up the scratch
+ * area for us correctly. We use this area to create temporary pagetables
+ * while we reorganise the memory map.
+ */
+
+ if ((bootconfig.scratchphysicalbase & 0x3fff) != 0)
+ panic("initarm: Scratch area not aligned on 16KB boundry\n");
+
+ if ((bootconfig.scratchsize < 0xc000) != 0)
+ panic("initarm: Scratch area too small (need >= 48KB)\n");
+
+/*
+ * Ok start the primary bootstrap.
+ * The primary bootstrap basically replaces the booter page tables with
+ * new ones that it creates in the boot scratch area. These page tables
+ * map the rest of the physical memory into the virtaul memory map.
+ * This allows low physical memory to be accessed to create the
+ * kernels page tables, relocate the kernel code from high physical
+ * memory to low physical memory etc.
+ */
+
+ printf("initarm: Primary bootstrap ... ");
+
+/*
+ * Update the videomemory structure to reflect the mapping changes
+ */
+
+ videomemory.vidm_vbase = VMEM_VBASE;
+ videomemory.vidm_pbase = VRAM_BASE;
+ videomemory.vidm_type = VIDEOMEM_TYPE_VRAM;
+ videomemory.vidm_size = bootconfig.vram[0].pages * NBPG;
+
+ kerneldatasize = bootconfig.kernsize + bootconfig.argsize;
+
+ l2pagetable = bootconfig.scratchvirtualbase;
+ l1pagetable = l2pagetable + 0x4000;
+
+/*
+ * Now we construct a L2 pagetables for the VRAM, the current kernel memory
+ * and the new kernel memory
+ */
+
+ for (logical = 0; logical < 0x200000; logical += NBPG) {
+ map_entry(l2pagetable + 0x1000, logical,
+ bootconfig.vram[0].address + logical);
+ map_entry(l2pagetable + 0x1000, logical + 0x200000,
+ bootconfig.vram[0].address + logical);
+ }
+
+ for (logical = 0; logical < kerneldatasize + bootconfig.scratchsize;
+ logical += NBPG) {
+ map_entry(l2pagetable + 0x3000, logical,
+ bootconfig.kernphysicalbase + logical);
+ }
+
+#if NHYDRABUS > 0
+ for (logical = 0; logical < 0x200000; logical += NBPG) {
+ map_entry(l2pagetable + 0x2000, logical,
+ bootconfig.dram[0].address + logical + NBPG);
+ }
+#else
+ for (logical = 0; logical < 0x200000; logical += NBPG) {
+ map_entry(l2pagetable + 0x2000, logical,
+ bootconfig.dram[0].address + logical);
+ }
+#endif
+
+/*
+ * Now we construct the L1 pagetable. This only needs the minimum to
+ * keep us going until we can contruct the proper kernel L1 page table.
+ */
+
+ map_section(l1pagetable, VIDC_BASE, VIDC_HW_BASE);
+ map_section(l1pagetable, IOMD_BASE, IOMD_HW_BASE);
+
+ map_pagetable(l1pagetable, 0x00000000,
+ bootconfig.scratchphysicalbase + 0x2000);
+ map_pagetable(l1pagetable, KERNEL_BASE,
+ bootconfig.scratchphysicalbase + 0x3000);
+ map_pagetable(l1pagetable, VMEM_VBASE,
+ bootconfig.scratchphysicalbase + 0x1000);
+
+/* Print some debugging info */
+
+/*
+ printf("page tables look like this ...\n");
+ printf("V0x00000000 - %08x\n", ReadWord(l1pagetable + 0x0000));
+ printf("V0x03500000 - %08x\n", ReadWord(l1pagetable + 0x00d4));
+ printf("V0x00200000 - %08x\n", ReadWord(l1pagetable + 0x0080));
+ printf("V0xf4000000 - %08x\n", ReadWord(l1pagetable + 0x3d00));
+ printf("V0xf0000000 - %08x\n", ReadWord(l1pagetable + 0x3c00));
+ printf("page dir = P%08x\n", bootconfig.scratchphysicalbase + 0x4000);
+ printf("l1= V%08x\n", l1pagetable);
+*/
+
+/*
+ * Pheww right we are ready to switch page tables !!!
+ * The L1 table is at bootconfig.scratchphysicalbase + 0x4000
+ */
+
+/* Switch tables */
+
+ setttb(bootconfig.scratchphysicalbase + 0x4000);
+
+/* Since we have mapped the VRAM up into kernel space we must now update the
+ * the bootconfig and display structures by hand.
+ */
+
+ bootconfig.display_start = VMEM_VBASE;
+ physcon_display_base(VMEM_VBASE);
+
+ printf("done.\n");
+
+/*
+ * Ok we have finished the primary boot strap. All this has done is to
+ * allow us to access all the physical memory from known virtual
+ * location. We also now know that all the used pages are at the top
+ * of the physical memory and where they are in the virtual memory map.
+ *
+ * This should be the stage we are at at the end of the bootstrap when
+ * we have a two stage booter.
+ *
+ * The secondary bootstrap has the responcibility to sort locating the
+ * kernel to the correct address and for creating the kernel page tables.
+ * It must also set up various memory pointers that are used by pmap etc.
+ */
+
+ process_kernel_args();
+
+ printf("initarm: Secondary bootstrap ... ");
+
+/* Zero down the memory we mapped in for the secondary bootstrap */
+
+ bzero(0x00000000, 0x200000);
+
+/* Set up the variables that define the availablilty of physcial memory */
+
+ physical_start = bootconfig.dram[0].address;
+ physical_freestart = physical_start;
+ physical_end = bootconfig.dram[bootconfig.dramblocks - 1].address
+ + bootconfig.dram[bootconfig.dramblocks - 1].pages * NBPG;
+ physical_freeend = physical_end;
+ physical_memoryblock = 0;
+ free_pages = bootconfig.drampages;
+
+ for (loop = 0; loop < bootconfig.dramblocks; ++loop)
+ physmem += bootconfig.dram[loop].pages;
+
+/*
+ * Reserve some pages at the top of the memory for later use
+ *
+ * This area is not currently used but could be used for the allocation
+ * of L1 page tables for each process.
+ * The size of this memory would be determined by the maximum number of
+ * processes.
+ *
+ * For the moment we just reserve a few pages just to make sure the
+ * system copes.
+ */
+
+ physical_freeend -= videodram_size;
+ free_pages -= (videodram_size / NBPG);
+ videodram_start = physical_freeend;
+
+ physical_freeend -= PD_SIZE * max_processes;
+ free_pages -= 4 * max_processes;
+ pagetables_start = physical_freeend;
+
+/* Right We have the bottom meg of memory mapped to 0x00000000
+ * so was can get at it. The kernel will ocupy the start of it.
+ * After the kernel/args we allocate some the the fixed page tables
+ * we need to get the system going.
+ * We allocate one page directory and 8 page tables and store the
+ * physical addresses in the kernel_pt_table array.
+ * Must remember that neither the page L1 or L2 page tables are the same
+ * size as a page !
+ *
+ * Ok the next bit of physical allocate may look complex but it is
+ * simple really. I have done it like this so that no memory gets wasted
+ * during the allocate of various pages and tables that are all different
+ * sizes.
+ * The start address will be page aligned.
+ * We allocate the kernel page directory on the first free 16KB boundry
+ * we find.
+ * We allocate the kernel page tables on the first 1KB boundry we find.
+ * We allocate 9 PT's. This means that in the process we
+ * KNOW that we will encounter at least 1 16KB boundry.
+ *
+ * Eventually if the top end of the memory gets used for process L1 page
+ * tables the kernel L1 page table may be moved up there.
+ */
+
+/*
+ * The Simtec Hydra board needs a 2MB aligned page for bootstrapping.
+ * Simplest thing is to nick the bottom page of physical memory.
+ */
+
+#if NHYDRABUS > 0
+ hydrascratch.physical = physical_start;
+ physical_start += NBPG;
+ --free_pages;
+#endif
+
+ physical = physical_start + kerneldatasize;
+/* printf("physical=%08x next_phys=%08x\n", physical, pmap_next_phys_page(physical - NBPG));*/
+ loop1 = 1;
+ kernel_pt_table[0] = 0;
+ for (loop = 0; loop < 15; ++loop) {
+ if ((physical & (PD_SIZE-1)) == 0 && kernel_pt_table[0] == 0) {
+ kernel_pt_table[KERNEL_PT_PAGEDIR] = physical;
+ bzero((char *)physical - physical_start, PD_SIZE);
+ physical += PD_SIZE;
+ } else {
+ kernel_pt_table[loop1] = physical;
+ bzero((char *)physical - physical_start, PT_SIZE);
+ physical += PT_SIZE;
+ ++loop1;
+ }
+ }
+
+/* A bit of debugging info */
+
+/*
+ for (loop=0; loop < 10; ++loop)
+ printf("%d - P%08x\n", loop, kernel_pt_table[loop]);
+*/
+
+/* This should never be able to happen but better confirm that. */
+
+ if ((kernel_pt_table[0] & (PD_SIZE-1)) != 0)
+ panic("initarm: Failed to align the kernel page directory\n");
+
+/* Update the address of the first free page of physical memory */
+
+ physical_freestart = physical;
+/* printf("physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+ free_pages -= (physical - physical_start) / NBPG;
+
+/* Allocate a page for the system page mapped to 0x00000000 */
+
+ systempage.physical = physical_freestart;
+ physical_freestart += NBPG;
+/* printf("(0)physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+ --free_pages;
+ bzero((char *)systempage.physical - physical_start, NBPG);
+
+/* Allocate another 3 pages for the stacks in different CPU modes. */
+
+ irqstack.physical = physical_freestart;
+ physical_freestart += NBPG;
+ abtstack.physical = physical_freestart;
+ physical_freestart += NBPG;
+ undstack.physical = physical_freestart;
+ physical_freestart += NBPG;
+ bzero((char *)irqstack.physical - physical_start, 3*NBPG);
+ free_pages -= 3;
+ irqstack.virtual = KERNEL_BASE + irqstack.physical-physical_start;
+ abtstack.virtual = KERNEL_BASE + abtstack.physical-physical_start;
+ undstack.virtual = KERNEL_BASE + undstack.physical-physical_start;
+/* printf("(1)physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+
+ kernelstack.physical = physical_freestart;
+ physical_freestart += UPAGES * NBPG;
+ bzero((char *)kernelstack.physical - physical_start, UPAGES * NBPG);
+ free_pages -= UPAGES;
+
+/* printf("(2)physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+
+
+ kernelstack.virtual = KERNEL_BASE + kernelstack.physical
+ - physical_start;
+
+ msgbufphys = physical_freestart;
+ physical_freestart += round_page(sizeof(struct msgbuf));
+ free_pages -= round_page(sizeof(struct msgbuf)) / NBPG;
+
+/* printf("physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/
+
+/* Ok we have allocated physical pages for the primary kernel page tables */
+
+/* Now we fill in the L2 pagetable for the kernel code/data */
+
+ l2pagetable = kernel_pt_table[KERNEL_PT_KERNEL] - physical_start;
+
+ if (N_GETMAGIC(kernexec[0]) == ZMAGIC) {
+/* printf("[ktext read-only] ");
+ printf("[%08x %08x %08x] \n", (u_int)kerneldatasize, (u_int)kernexec->a_text,
+ (u_int)(kernexec->a_text+kernexec->a_data+kernexec->a_bss));*/
+/* printf("physical start=%08x physical freestart=%08x hydra phys=%08x\n", physical_start, physical_freestart, hydrascratch.physical);*/
+ for (logical = 0; logical < 0x00/*kernexec->a_text*/;
+ logical += NBPG)
+ map_entry_ro(l2pagetable, logical, physical_start
+ + logical);
+ for (; logical < kerneldatasize; logical += NBPG)
+ map_entry(l2pagetable, logical, physical_start
+ + logical);
+ } else
+ for (logical = 0; logical < kerneldatasize; logical += NBPG)
+ map_entry(l2pagetable, logical, physical_start
+ + logical);
+
+/* Map the stack pages */
+
+ map_entry(l2pagetable, irqstack.physical-physical_start,
+ irqstack.physical);
+ map_entry(l2pagetable, abtstack.physical-physical_start,
+ abtstack.physical);
+ map_entry(l2pagetable, undstack.physical-physical_start,
+ undstack.physical);
+ map_entry(l2pagetable, kernelstack.physical - physical_start,
+ kernelstack.physical);
+ map_entry(l2pagetable, kernelstack.physical + NBPG - physical_start,
+ kernelstack.physical + NBPG);
+
+ l2pagetable = kernel_pt_table[KERNEL_PT_KSTACK] - physical_start;
+
+ map_entry(l2pagetable, 0x003fe000, kernelstack.physical);
+ map_entry(l2pagetable, 0x003ff000, kernelstack.physical + NBPG);
+
+/* Now we fill in the L2 pagetable for the VRAM */
+
+/*
+ * Current architectures mean that the VRAM is always in 1 continuous
+ * bank.
+ * This means that we can just map the 2 meg that the VRAM would occupy.
+ * In theory we don't need a page table for VRAM, we could section map
+ * it but we would need the page tables if DRAM was in use.
+ */
+
+ l2pagetable = kernel_pt_table[KERNEL_PT_VMEM] - physical_start;
+
+ for (logical = 0; logical < 0x200000; logical += NBPG) {
+ map_entry(l2pagetable, logical, bootconfig.vram[0].address
+ + logical);
+ map_entry(l2pagetable, logical + 0x200000,
+ bootconfig.vram[0].address + logical);
+ }
+
+/* Map entries in the page table used to map PDE's */
+
+ l2pagetable = kernel_pt_table[KERNEL_PT_PDE] - physical_start;
+ map_entry(l2pagetable, 0x0000000,
+ kernel_pt_table[KERNEL_PT_PAGEDIR]);
+ map_entry(l2pagetable, 0x0001000,
+ kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x1000);
+ map_entry(l2pagetable, 0x0002000,
+ kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x2000);
+ map_entry(l2pagetable, 0x0003000,
+ kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x3000);
+
+/*
+ * Map entries in the page table used to map PTE's
+ * Basically every kernel page table gets mapped here
+ */
+
+ l2pagetable = kernel_pt_table[KERNEL_PT_PTE] - physical_start;
+ map_entry(l2pagetable, (KERNEL_BASE >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_KERNEL]);
+ map_entry(l2pagetable, (PAGE_DIRS_BASE >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_PDE]);
+ map_entry(l2pagetable, (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_PTE]);
+ map_entry(l2pagetable, (VMEM_VBASE >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_VMEM]);
+ map_entry(l2pagetable, (0x00000000 >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_SYS]);
+ map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00000000) >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_VMDATA0]);
+ map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00400000) >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_VMDATA1]);
+ map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00800000) >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_VMDATA2]);
+ map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00c00000) >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_VMDATA3]);
+ map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01000000) >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_VMDATA4]);
+ map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01400000) >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_VMDATA5]);
+ map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01800000) >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_VMDATA6]);
+ map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01c00000) >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_VMDATA7]);
+ map_entry(l2pagetable, ((0xef800000) >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_KSTACK]);
+
+ map_entry(l2pagetable, (0xf5000000 >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x0000);
+ map_entry(l2pagetable, (0xf5400000 >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x1000);
+ map_entry(l2pagetable, (0xf5800000 >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x2000);
+ map_entry(l2pagetable, (0xf5c00000 >> (PGSHIFT-2)),
+ kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x3000);
+
+/*
+ * Map the system page in the kernel page table for the bottom 1Meg
+ * of the virtual memory map.
+ */
+
+ l2pagetable = kernel_pt_table[KERNEL_PT_SYS] - physical_start;
+ map_entry(l2pagetable, 0x0000000, systempage.physical);
+
+/* Now we construct the L1 pagetable */
+
+ l1pagetable = kernel_pt_table[KERNEL_PT_PAGEDIR] - physical_start;
+
+/* Map the VIDC20, IOMD, COMBO and podules */
+
+/* Map the VIDC20 */
+
+ map_section(l1pagetable, VIDC_BASE, VIDC_HW_BASE);
+
+/* Map the IOMD (and SLOW and MEDIUM simple podules) */
+
+ map_section(l1pagetable, IOMD_BASE, IOMD_HW_BASE);
+
+/* Map the COMBO (and module space) */
+
+ map_section(l1pagetable, IO_BASE, IO_HW_BASE);
+
+/* Map the L2 pages tables in the L1 page table */
+
+ map_pagetable(l1pagetable, 0x00000000,
+ kernel_pt_table[KERNEL_PT_SYS]);
+ map_pagetable(l1pagetable, 0xef800000,
+ kernel_pt_table[KERNEL_PT_KSTACK]);
+ map_pagetable(l1pagetable, KERNEL_BASE,
+ kernel_pt_table[KERNEL_PT_KERNEL]);
+ map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00000000,
+ kernel_pt_table[KERNEL_PT_VMDATA0]);
+ map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00400000,
+ kernel_pt_table[KERNEL_PT_VMDATA1]);
+ map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00800000,
+ kernel_pt_table[KERNEL_PT_VMDATA2]);
+ map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00c00000,
+ kernel_pt_table[KERNEL_PT_VMDATA3]);
+ map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01000000,
+ kernel_pt_table[KERNEL_PT_VMDATA4]);
+ map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01400000,
+ kernel_pt_table[KERNEL_PT_VMDATA5]);
+ map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01800000,
+ kernel_pt_table[KERNEL_PT_VMDATA6]);
+ map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01c00000,
+ kernel_pt_table[KERNEL_PT_VMDATA7]);
+ map_pagetable(l1pagetable, PAGE_DIRS_BASE,
+ kernel_pt_table[KERNEL_PT_PDE]);
+ map_pagetable(l1pagetable, PROCESS_PAGE_TBLS_BASE,
+ kernel_pt_table[KERNEL_PT_PTE]);
+ map_pagetable(l1pagetable, VMEM_VBASE,
+ kernel_pt_table[KERNEL_PT_VMEM]);
+
+/* Bit more debugging info */
+
+/*
+ printf("page tables look like this ...\n");
+ printf("V0x00000000 - %08x\n", ReadWord(l1pagetable + 0x0000));
+ printf("V0x03200000 - %08x\n", ReadWord(l1pagetable + 0x00c8));
+ printf("V0x03500000 - %08x\n", ReadWord(l1pagetable + 0x00d4));
+ printf("V0xf0000000 - %08x\n", ReadWord(l1pagetable + 0x3c00));
+ printf("V0xf1000000 - %08x\n", ReadWord(l1pagetable + 0x3c40));
+ printf("V0xf2000000 - %08x\n", ReadWord(l1pagetable + 0x3c80));
+ printf("V0xf3000000 - %08x\n", ReadWord(l1pagetable + 0x3cc0));
+ printf("V0xf3300000 - %08x\n", ReadWord(l1pagetable + 0x3ccc));
+ printf("V0xf4000000 - %08x\n", ReadWord(l1pagetable + 0x3d00));
+ printf("V0xf6000000 - %08x\n", ReadWord(l1pagetable + 0x3d80));
+*/
+/* printf("V0xefc00000 - %08x\n", ReadWord(l1pagetable + 0x3bf8));
+ printf("V0xef800000 - %08x\n", ReadWord(l1pagetable + 0x3bfc));*/
+
+/*
+ * Now we have the real page tables in place so we can switch to them.
+ * Once this is done we will be running with the REAL kernel page tables.
+ */
+
+/*
+ * The last thing we must do is copy the kernel down to the new memory.
+ * This copies all our kernel data structures and variables as well
+ * which is why it is left to the last moment.
+ */
+
+ printf("mapping ... ");
+
+ bcopy((char *)KERNEL_BASE, (char *)0x00000000, kerneldatasize);
+
+/* Switch tables */
+
+ setttb(kernel_pt_table[KERNEL_PT_PAGEDIR]);
+
+ printf("done.\n");
+
+/* Right set up the vectors at the bottom of page 0 */
+
+ bcopy(page0, (char *)0x00000000, page0_end - page0);
+
+/*
+ * Pages were allocated during the secondary bootstrap for the
+ * stacks for different CPU modes.
+ * We must now set the r13 registers in the different CPU modes to
+ * point to these stacks.
+ * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+ * of the stack memory.
+ */
+
+#ifdef DIAGNOSTIC
+ printf("IRQ stack V%08x P%08x\n", (u_int) irqstack.virtual,
+ (u_int) irqstack.physical);
+ printf("ABT stack V%08x P%08x\n", (u_int) abtstack.virtual,
+ (u_int) abtstack.physical);
+ printf("UND stack V%08x P%08x\n", (u_int) undstack.virtual,
+ (u_int) undstack.physical);
+#endif
+
+ printf("init subsystems: stacks ");
+
+ set_stackptr(PSR_IRQ32_MODE, irqstack.virtual + NBPG);
+ set_stackptr(PSR_ABT32_MODE, abtstack.virtual + NBPG);
+ set_stackptr(PSR_UND32_MODE, undstack.virtual + NBPG);
+
+ if (pmap_debug_level >= 0)
+ printf("kstack V%08x P%08x\n", (int) kernelstack.virtual,
+ (int) kernelstack.physical);
+
+/*
+ * Well we should set a data abort handler.
+ * Once things get going this will change as we will need a proper handler.
+ * Until then we will use a handler that just panics but tells us
+ * why.
+ * Initialisation of the vectors will just panic on a data abort.
+ * This just fills in a slighly better one.
+ */
+
+ printf("vectors ");
+ data_abort_handler_address = (u_int)data_abort_handler;
+ prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
+ undefined_handler_address = (u_int)undefinedinstruction_bounce;
+
+/* Diagnostic stuff. while writing the boot code */
+
+/*
+ for (loop = 0x0; loop < 0x1000; ++loop) {
+ if (ReadWord(PAGE_DIRS_BASE + loop * 4) != 0)
+ printf("Pagetable for V%08x = %08x\n", loop << 20,
+ ReadWord(0xf2000000 + loop * 4));
+ }
+
+*/
+
+/* Diagnostic stuff. while writing the boot code */
+
+/*
+ for (loop = 0x0; loop < 0x400; ++loop) {
+ if (ReadWord(kernel_pt_table[KERNEL_PT_PTE] + loop * 4) != 0)
+ printf("Pagetable for V%08x P%08x = %08x\n",
+ loop << 22, kernel_pt_table[KERNEL_PT_PTE]+loop*4,
+ ReadWord(kernel_pt_table[KERNEL_PT_PTE]+loop * 4));
+ }
+*/
+
+/* At last !
+ * We now have the kernel in physical memory from the bottom upwards.
+ * Kernel page tables are physically above this.
+ * The kernel is mapped to 0xf0000000
+ * The kernel data PTs will handle the mapping of 0xf1000000-0xf1ffffff
+ * 2Meg of VRAM is mapped to 0xf4000000
+ * The kernel page directory is mapped to 0xf3000000
+ * The page tables are mapped to 0xefc00000
+ * The IOMD is mapped to 0xf6000000
+ * The VIDC is mapped to 0xf6100000
+ */
+
+/* Initialise the undefined instruction handlers */
+
+ printf("undefined ");
+ undefined_init();
+
+/* Boot strap pmap telling it where the kernel page table is */
+
+ printf("pmap ");
+ pmap_bootstrap(PAGE_DIRS_BASE);
+
+/* Setup the IRQ system */
+
+ printf("irq ");
+ irq_init();
+ printf("done.\n");
+
+#ifdef DDB
+ printf("ddb: ");
+ db_machine_init();
+ ddb_init();
+
+ if (boothowto & RB_KDB)
+ Debugger();
+#endif
+
+/* We return the new stack pointer address */
+ return(kernelstack.virtual + USPACE_SVC_STACK_TOP);
+}
+
+
+/*
+ * void cpu_startup(void)
+ *
+ * Machine dependant startup code.
+ *
+ */
+
+void
+cpu_startup()
+{
+ int loop;
+ vm_offset_t minaddr;
+ vm_offset_t maxaddr;
+ caddr_t sysbase;
+ caddr_t size;
+ vm_size_t bufsize;
+ int base, residual;
+
+/* Set the cpu control register */
+
+ cpu_ctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
+ | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE;
+
+ if (cpu_cache & 1)
+ cpu_ctrl |= CPU_CONTROL_IDC_ENABLE;
+ if (cpu_cache & 2)
+ cpu_ctrl |= CPU_CONTROL_WBUF_ENABLE;
+
+ if (!(cpu_cache & 4))
+ cpu_ctrl |= CPU_CONTROL_CPCLK;
+
+#ifdef CPU_LATE_ABORT
+ cpu_ctrl |= CPU_CONTROL_LABT_ENABLE;
+#endif
+
+/* Clear out the cache */
+
+ idcflush();
+
+ cpu_control(cpu_ctrl);
+
+/* All domains MUST be clients, permissions are VERY important */
+
+ cpu_domains(DOMAIN_CLIENT);
+
+/* Lock down zero page */
+
+ zero_page_readonly();
+
+/*
+ * Initialize error message buffer (at end of core).
+ */
+
+/* msgbufphys was setup during the secondary boot strap */
+
+ for (loop = 0; loop < btoc(sizeof(struct msgbuf)); ++loop)
+ pmap_enter(pmap_kernel(),
+ (vm_offset_t)((caddr_t)msgbufp + loop * NBPG),
+ msgbufphys + loop * NBPG, VM_PROT_ALL, TRUE);
+
+ msgbufmapped = 1;
+
+/*
+ * Identify ourselves for the msgbuf (everything printed earlier will
+ * not be buffered).
+ */
+
+ printf(version);
+
+ printf("screen: %d x %d x %d\n", bootconfig.width + 1, bootconfig.height + 1, bootconfig.framerate);
+
+ if (cmos_read(RTC_ADDR_REBOOTCNT) > 0)
+ printf("Warning: REBOOTCNT = %d\n", cmos_read(RTC_ADDR_REBOOTCNT));
+
+ printf("real mem = %d (%d pages)\n", arm_page_to_byte(physmem), physmem);
+
+ /*
+ * Find out how much space we need, allocate it,
+ * and then give everything true virtual addresses.
+ */
+
+ size = allocsys((caddr_t)0);
+ sysbase = (caddr_t)kmem_alloc(kernel_map, round_page(size));
+ if (sysbase == 0)
+ panic("cpu_startup: no room for system tables %d bytes required", size);
+ if ((caddr_t)((allocsys(sysbase) - sysbase)) != size)
+ panic("cpu_startup: system table size inconsistency");
+
+/*
+ * Now allocate buffers proper. They are different than the above
+ * in that they usually occupy more virtual memory than physical.
+ */
+
+ bufsize = MAXBSIZE * nbuf;
+ buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
+ &maxaddr, bufsize, TRUE);
+ minaddr = (vm_offset_t)buffers;
+ if (vm_map_find(buffer_map, vm_object_allocate(bufsize),
+ (vm_offset_t)0, &minaddr, bufsize, FALSE) != KERN_SUCCESS)
+ panic("startup: cannot allocate buffers");
+
+ if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
+/* don't want to alloc more physical mem than needed */
+ bufpages = btoc(MAXBSIZE) * nbuf;
+ }
+
+ base = bufpages / nbuf;
+ residual = bufpages % nbuf;
+ for (loop = 0; loop < nbuf; ++loop) {
+ vm_size_t curbufsize;
+ vm_offset_t curbuf;
+
+/*
+ * First <residual> buffers get (base+1) physical pages
+ * allocated for them. The rest get (base) physical pages.
+ *
+ * The rest of each buffer occupies virtual space,
+ * but has no physical memory allocated for it.
+ */
+
+ curbuf = (vm_offset_t)buffers + loop * MAXBSIZE;
+ curbufsize = CLBYTES * (loop < residual ? base+1 : base);
+ vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
+ vm_map_simplify(buffer_map, curbuf);
+ }
+
+/*
+ * Allocate a submap for exec arguments. This map effectively
+ * limits the number of processes exec'ing at any time.
+ */
+
+ exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
+ 16*NCARGS, TRUE);
+
+/*
+ * Allocate a submap for physio
+ */
+
+ phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
+ VM_PHYS_SIZE, TRUE);
+
+/*
+ * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
+ * we use the more space efficient malloc in place of kmem_alloc.
+ */
+
+ mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
+ M_MBUF, M_NOWAIT);
+ bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
+ mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
+ VM_MBUF_SIZE, FALSE);
+
+/*
+ printf("mb_buf: map=%08x maxaddr = %08x mbutl = %08x\n", mb_map, maxaddr, mbutl);
+*/
+
+/*
+ * Initialise callouts
+ */
+
+ callfree = callout;
+
+ for (loop = 1; loop < ncallout; ++loop)
+ callout[loop - 1].c_next = &callout[loop];
+
+ printf("avail mem = %d (%d pages)\n", (int)ptoa(cnt.v_free_count),
+ (int)ptoa(cnt.v_free_count) / NBPG);
+ printf("using %d buffers containing %d bytes of memory\n",
+ nbuf, bufpages * CLBYTES);
+
+/*
+ * Set up buffers, so they can be used to read disk labels.
+ */
+
+ bufinit();
+
+ proc0paddr = (struct user *)kernelstack.virtual;
+ proc0.p_addr = proc0paddr;
+
+ curpcb = &proc0.p_addr->u_pcb;
+ curpcb->pcb_flags = 0;
+ curpcb->pcb_und_sp = (u_int)proc0.p_addr + USPACE_UNDEF_STACK_TOP;
+ curpcb->pcb_sp = (u_int)proc0.p_addr + USPACE_SVC_STACK_TOP;
+ curpcb->pcb_pagedir = (pd_entry_t *)pmap_extract(kernel_pmap,
+ (vm_offset_t)(kernel_pmap)->pm_pdir);
+
+ proc0.p_md.md_regs = (struct trapframe *)curpcb->pcb_sp - 1;
+#if 0
+/* Hack proc0 */
+
+ proc0paddr = (struct user *)kernelstack.virtual;
+ proc0.p_addr = proc0paddr;
+
+ curpcb = &proc0.p_addr->u_pcb;
+ proc0.p_addr->u_pcb.pcb_flags = 0;
+ proc0.p_addr->u_pcb.pcb_und_sp = (u_int)proc0.p_addr + USPACE_UNDEF_STACK_TOP;
+
+ proc0.p_addr->u_pcb.pcb_pagedir = (pd_entry_t *)pmap_extract(kernel_pmap,
+ (vm_offset_t)(kernel_pmap)->pm_pdir);
+#endif
+/*
+ * Install an IRQ handler on the VSYNC interrupt to reboot if the
+ * middle mouse button is pressed.
+ */
+
+ setup_cursor();
+
+/* Allocate memory for the kmodule area if required */
+
+ if (kmodule_size) {
+ kmodule_size = round_page(kmodule_size);
+ kmodule_base = (u_int)kmem_alloc(kernel_map, kmodule_size);
+ if (kmodule_base)
+ printf("KMODULE SPACE = %08x\n", kmodule_base);
+ else
+ printf("\x1b[31mNO KMODULE SPACE\n\x1b[0m");
+ }
+
+/*
+ * Configure the hardware
+ */
+
+ configure();
+
+/* Set the root, swap and dump devices from the boot args */
+
+ set_boot_devs();
+
+ dump_spl_masks();
+
+ cold = 0; /* We are warm now ... */
+}
+
+
+/*
+ * Allocate space for system data structures. We are given
+ * a starting virtual address and we return a final virtual
+ * address; along the way we set each data structure pointer.
+ *
+ * We call allocsys() with 0 to find out how much space we want,
+ * allocate that much and fill it with zeroes, and then call
+ * allocsys() again with the correct base virtual address.
+ */
+
+caddr_t
+allocsys(v)
+ register caddr_t v;
+{
+
+#define valloc(name, type, num) \
+ (caddr_t)(name) = (type *)v; \
+ v = (caddr_t)((name) + (num));
+
+ valloc(callout, struct callout, ncallout);
+ valloc(swapmap, struct map, nswapmap = maxproc * 2);
+
+#ifdef SYSVSHM
+ valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
+#endif
+#ifdef SYSVSEM
+ valloc(sema, struct semid_ds, seminfo.semmni);
+ valloc(sem, struct sem, seminfo.semmns);
+ /* This is pretty disgusting! */
+ valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
+#endif
+#ifdef SYSVMSG
+ valloc(msgpool, char, msginfo.msgmax);
+ valloc(msgmaps, struct msgmap, msginfo.msgseg);
+ valloc(msghdrs, struct msg, msginfo.msgtql);
+ valloc(msqids, struct msqid_ds, msginfo.msgmni);
+#endif
+
+/*
+ * Determine how many buffers to allocate. We use 10% of the
+ * first 2MB of memory, and 5% of the rest, with a minimum of 16
+ * buffers. We allocate 1/2 as many swap buffer headers as file
+ * i/o buffers.
+ */
+
+ if (bufpages == 0)
+ if (physmem < arm_byte_to_page(2 * 1024 * 1024))
+ bufpages = physmem / (10 * CLSIZE);
+ else
+ bufpages = (arm_byte_to_page(2 * 1024 * 1024)
+ + physmem) / (20 * CLSIZE);
+
+#ifdef DIAGNOSTIC
+ if (bufpages == 0)
+ panic("bufpages = 0\n");
+#endif
+
+ if (nbuf == 0) {
+ nbuf = bufpages;
+ if (nbuf < 16)
+ nbuf = 16;
+ }
+
+ if (nswbuf == 0) {
+ nswbuf = (nbuf / 2) & ~1; /* force even */
+ if (nswbuf > 256)
+ nswbuf = 256; /* sanity */
+ }
+
+ valloc(swbuf, struct buf, nswbuf);
+ valloc(buf, struct buf, nbuf);
+
+ return(v);
+}
+
+
+/* A few functions that are used to help construct the page tables
+ * during the bootstrap process.
+ */
+
+void
+map_section(pagetable, va, pa)
+ vm_offset_t pagetable;
+ vm_offset_t va;
+ vm_offset_t pa;
+{
+ if ((va & 0xfffff) != 0)
+ panic("initarm: Cannot allocate 1MB section on non 1MB boundry\n");
+
+ ((u_int *)pagetable)[(va >> 20)] = L1_SEC((pa & PD_MASK));
+}
+
+
+void
+map_pagetable(pagetable, va, pa)
+ vm_offset_t pagetable;
+ vm_offset_t va;
+ vm_offset_t pa;
+{
+ if ((pa & 0xc00) != 0)
+ panic("pagetables should be group allocated on pageboundry");
+ ((u_int *)pagetable)[(va >> 20) + 0] = L1_PTE((pa & PG_FRAME) + 0x000);
+ ((u_int *)pagetable)[(va >> 20) + 1] = L1_PTE((pa & PG_FRAME) + 0x400);
+ ((u_int *)pagetable)[(va >> 20) + 2] = L1_PTE((pa & PG_FRAME) + 0x800);
+ ((u_int *)pagetable)[(va >> 20) + 3] = L1_PTE((pa & PG_FRAME) + 0xc00);
+}
+
+
+void
+map_entry(pagetable, va, pa)
+ vm_offset_t pagetable;
+ vm_offset_t va;
+ vm_offset_t pa;
+{
+ WriteWord(pagetable + ((va >> 10) & 0x00000ffc),
+ L2_PTE((pa & PG_FRAME), AP_KRW));
+}
+
+
+void
+map_entry_nc(pagetable, va, pa)
+ vm_offset_t pagetable;
+ vm_offset_t va;
+ vm_offset_t pa;
+{
+ WriteWord(pagetable + ((va >> 10) & 0x00000ffc),
+ L2_PTE_NC((pa & PG_FRAME), AP_KRW));
+}
+
+
+void
+map_entry_ro(pagetable, va, pa)
+ vm_offset_t pagetable;
+ vm_offset_t va;
+ vm_offset_t pa;
+{
+ WriteWord(pagetable + ((va >> 10) & 0x00000ffc),
+ L2_PTE((pa & PG_FRAME), AP_KR));
+}
+
+
+int wdresethack = 1;
+
+void
+process_kernel_args()
+{
+ char *ptr;
+ char *args;
+
+/* Ok now we will check the arguments for interesting parameters. */
+
+ args = (char *)bootconfig.argvirtualbase;
+ max_processes = 64;
+ boothowto = 0;
+ kmodule_size = 0;
+ cpu_cache = 0x03;
+ debug_flags = 0;
+ videodram_size = 0;
+
+/* Skip the first parameter (the boot loader filename) */
+
+ while (*args != ' ' && *args != 0)
+ ++args;
+
+ while (*args == ' ')
+ ++args;
+
+/* Skip the kernel image filename */
+
+ while (*args != ' ' && *args != 0)
+ ++args;
+
+ while (*args == ' ')
+ ++args;
+
+ boot_args = NULL;
+
+ if (*args != 0) {
+ boot_args = args;
+
+ if (strstr(args, "nocache"))
+ cpu_cache &= ~1;
+
+ if (strstr(args, "nowritebuf"))
+ cpu_cache &= ~2;
+
+ if (strstr(args, "fpaclk2"))
+ cpu_cache |= 4;
+
+ ptr = strstr(args, "maxproc=");
+ if (ptr) {
+ max_processes = (int)strtoul(ptr + 8, NULL, 10);
+ if (max_processes < 16)
+ max_processes = 16;
+ if (max_processes > 256)
+ max_processes = 256;
+ printf("Maximum \"in memory\" processes = %d\n",
+ max_processes);
+ }
+ ptr = strstr(args, "ramdisc=");
+ if (ptr) {
+ ramdisc_size = (u_int)strtoul(ptr + 8, NULL, 10);
+ ramdisc_size *= 1024;
+ if (ramdisc_size < 32*1024)
+ ramdisc_size = 32*1024;
+ if (ramdisc_size > 2048*1024)
+ ramdisc_size = 2048*1024;
+ }
+ ptr = strstr(args, "kmodule=");
+ if (ptr) {
+ kmodule_size = (u_int)strtoul(ptr + 8, NULL, 10);
+ kmodule_size *= 1024;
+ if (kmodule_size < 4*1024)
+ kmodule_size = 4*1024;
+ if (kmodule_size > 256*1024)
+ kmodule_size = 256*1024;
+ }
+ ptr = strstr(args, "videodram=");
+ if (ptr) {
+ videodram_size = (u_int)strtoul(ptr + 10, NULL, 10);
+ /* Round to 4K page */
+ videodram_size *= 1024;
+ videodram_size = round_page(videodram_size);
+ if (videodram_size > 1024*1024)
+ videodram_size = 1024*1024;
+ printf("VIDEO DRAM = %d\n", videodram_size);
+ }
+ if (strstr(args, "single"))
+ boothowto |= RB_SINGLE;
+ if (strstr(args, "kdb"))
+ boothowto |= RB_KDB;
+ ptr = strstr(args, "pmapdebug=");
+ if (ptr) {
+ pmap_debug_level = (int)strtoul(ptr + 10, NULL, 10);
+ pmap_debug(pmap_debug_level);
+ debug_flags |= 0x01;
+ }
+ if (strstr(args, "termdebug"))
+ debug_flags |= 0x02;
+ if (strstr(args, "nowdreset"))
+ wdresethack = 0;
+ if (strstr(args, "notermcls"))
+ debug_flags |= 0x04;
+ }
+}
+
+/* This should happen in the console code - This really must move soon */
+
+int
+setup_cursor()
+{
+
+/* The cursor currently gets set up here. slightly wasteful on memory */
+
+/*
+ * This should be done in the vidc code as that is responcible for the cursor.
+ * This will probably happen when the vidc code is separated from the console
+ * (currently work in progress)
+ */
+
+ cursor_data = (u_int *)kmem_alloc(kernel_map, NBPG);
+/* printf("Cursor data page = V%08x P%08x\n", cursor_data, pmap_extract(kernel_pmap, (vm_offset_t)cursor_data));*/
+ WriteWord(IOMD_CURSINIT, pmap_extract(kernel_pmap,
+ (vm_offset_t)cursor_data));
+ return(0);
+}
+
+
+/*
+ * Clear registers on exec
+ */
+
+void
+setregs(p, pack, stack, retval)
+ struct proc *p;
+ struct exec_package *pack;
+ u_long stack;
+ register_t *retval;
+{
+ register struct trapframe *tf;
+
+ if (pmap_debug_level >= -1)
+ printf("setregs: ip=%08x sp=%08x proc=%08x\n",
+ (u_int) pack->ep_entry, (u_int) stack, (u_int) p);
+
+ tf = p->p_md.md_regs;
+
+ if (pmap_debug_level >= -1)
+ printf("mdregs=%08x pc=%08x lr=%08x sp=%08x\n",
+ (u_int) tf, tf->tf_pc, tf->tf_usr_lr, tf->tf_usr_sp);
+
+ tf->tf_r11 = 0; /* bottom of the fp chain */
+ tf->tf_r12 = 0; /* ??? */
+ tf->tf_pc = pack->ep_entry;
+ tf->tf_usr_lr = pack->ep_entry;
+ tf->tf_svc_lr = 0x77777777; /* Something we can see */
+ tf->tf_usr_sp = stack;
+ tf->tf_r10 = 0xaa55aa55; /* Something we can see */
+ tf->tf_spsr = PSR_USR32_MODE;
+
+ p->p_addr->u_pcb.pcb_flags = 0;
+
+ retval[1] = 0;
+}
+
+
+/*
+ * Modify the current mapping for zero page to make it read only
+ *
+ * This routine is only used until things start forking. Then new
+ * system pages are mapped read only in pmap_enter().
+ */
+
+void
+zero_page_readonly()
+{
+ WriteWord(0xefc00000, L2_PTE((systempage.physical & PG_FRAME), AP_KR));
+ tlbflush();
+}
+
+
+/*
+ * Modify the current mapping for zero page to make it read/write
+ *
+ * This routine is only used until things start forking. Then system
+ * pages belonging to user processes are never made writable.
+ */
+
+void
+zero_page_readwrite()
+{
+ WriteWord(0xefc00000, L2_PTE((systempage.physical & PG_FRAME), AP_KRW));
+ tlbflush();
+}
+
+
+/*
+ * Send an interrupt to process.
+ *
+ * Stack is set up to allow sigcode stored in u. to call routine, followed by kcall
+ * to sigreturn routine below. After sigreturn resets the signal mask, the stack, and the
+ * frame pointer, it returns to the user specified pc.
+ */
+
+void
+sendsig(catcher, sig, mask, code)
+ sig_t catcher;
+ int sig;
+ int mask;
+ u_long code;
+{
+ struct proc *p = curproc;
+ struct trapframe *tf;
+ struct sigframe *fp, frame;
+ struct sigacts *psp = p->p_sigacts;
+ int oonstack;
+ extern char sigcode[], esigcode[];
+
+ if (pmap_debug_level >= 0)
+ printf("Sendsig: sig=%d mask=%08x catcher=%08x code=%08x\n",
+ sig, mask, (u_int)catcher, (u_int)code);
+
+ tf = p->p_md.md_regs;
+ oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+
+/*
+ * Allocate space for the signal handler context.
+ */
+
+ if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
+ (psp->ps_sigonstack & sigmask(sig))) {
+ fp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
+ psp->ps_sigstk.ss_size - sizeof(struct sigframe));
+ psp->ps_sigstk.ss_flags |= SA_ONSTACK;
+ } else {
+ fp = (struct sigframe *)tf->tf_usr_sp - 1;
+ }
+
+/*
+ * Build the argument list for the signal handler.
+ */
+
+ frame.sf_signum = sig;
+
+ frame.sf_code = code;
+ frame.sf_scp = &fp->sf_sc;
+ frame.sf_handler = catcher;
+
+/*
+ * Build the signal context to be used by sigreturn.
+ */
+
+ frame.sf_sc.sc_onstack = oonstack;
+ frame.sf_sc.sc_mask = mask;
+ frame.sf_sc.sc_r0 = tf->tf_r0;
+ frame.sf_sc.sc_r1 = tf->tf_r1;
+ frame.sf_sc.sc_r2 = tf->tf_r2;
+ frame.sf_sc.sc_r3 = tf->tf_r3;
+ frame.sf_sc.sc_r4 = tf->tf_r4;
+ frame.sf_sc.sc_r5 = tf->tf_r5;
+ frame.sf_sc.sc_r6 = tf->tf_r6;
+ frame.sf_sc.sc_r7 = tf->tf_r7;
+ frame.sf_sc.sc_r8 = tf->tf_r8;
+ frame.sf_sc.sc_r9 = tf->tf_r9;
+ frame.sf_sc.sc_r10 = tf->tf_r10;
+ frame.sf_sc.sc_r11 = tf->tf_r11;
+ frame.sf_sc.sc_r12 = tf->tf_r12;
+ frame.sf_sc.sc_usr_sp = tf->tf_usr_sp;
+ frame.sf_sc.sc_usr_lr = tf->tf_usr_lr;
+ frame.sf_sc.sc_svc_lr = tf->tf_svc_lr;
+ frame.sf_sc.sc_pc = tf->tf_pc;
+ frame.sf_sc.sc_spsr = tf->tf_spsr;
+
+ if (copyout(&frame, fp, sizeof(frame)) != 0) {
+/*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+
+ sigexit(p, SIGILL);
+ /* NOTREACHED */
+ }
+
+/*
+ * Build context to run handler in.
+ */
+
+ tf->tf_r0 = frame.sf_signum;
+ tf->tf_r1 = frame.sf_code;
+ tf->tf_r2 = (u_int)frame.sf_scp;
+ tf->tf_r3 = (u_int)frame.sf_handler;
+ tf->tf_usr_sp = (int)fp;
+ tf->tf_pc = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
+
+ if (pmap_debug_level >= 0)
+ printf("Sendsig: sig=%d pc=%08x\n", sig, tf->tf_pc);
+}
+
+
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken. Reset signal mask and
+ * stack state from context left by sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * psr to gain improper privileges or to cause
+ * a machine fault.
+ */
+
+int
+sys_sigreturn(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_sigreturn_args /* {
+ syscallarg(struct sigcontext *) sigcntxp;
+ } */ *uap = v;
+ struct sigcontext *scp, context;
+/* register struct sigframe *fp;*/
+ register struct trapframe *tf;
+
+ if (pmap_debug_level >= 0)
+ printf("sigreturn: context=%08x\n", (int)SCARG(uap, sigcntxp));
+
+ tf = p->p_md.md_regs;
+
+ /*
+ * The trampoline code hands us the context.
+ * It is unsafe to keep track of it ourselves, in the event that a
+ * program jumps out of a signal handler.
+ */
+
+ scp = SCARG(uap, sigcntxp);
+
+ if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
+ return (EFAULT);
+
+/*
+ * Check for security violations.
+ */
+
+/* Make sure the processor mode has not been tampered with */
+
+ if ((context.sc_spsr & PSR_MODE) != PSR_USR32_MODE)
+ return(EINVAL);
+
+ if (context.sc_onstack & 01)
+ p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+ p->p_sigmask = context.sc_mask & ~sigcantmask;
+
+ /*
+ * Restore signal context.
+ */
+
+ tf->tf_r0 = context.sc_r0;
+ tf->tf_r1 = context.sc_r1;
+ tf->tf_r2 = context.sc_r2;
+ tf->tf_r3 = context.sc_r3;
+ tf->tf_r4 = context.sc_r4;
+ tf->tf_r5 = context.sc_r5;
+ tf->tf_r6 = context.sc_r6;
+ tf->tf_r7 = context.sc_r7;
+ tf->tf_r8 = context.sc_r8;
+ tf->tf_r9 = context.sc_r9;
+ tf->tf_r10 = context.sc_r10;
+ tf->tf_r11 = context.sc_r11;
+ tf->tf_r12 = context.sc_r12;
+ tf->tf_usr_sp = context.sc_usr_sp;
+ tf->tf_usr_lr = context.sc_usr_lr;
+ tf->tf_svc_lr = context.sc_svc_lr;
+ tf->tf_pc = context.sc_pc;
+ tf->tf_spsr = context.sc_spsr;
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(tf, 6);
+#endif
+
+ return (EJUSTRETURN);
+}
+
+/*
+ * machine dependent system variables.
+ */
+
+int
+cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+ int *name;
+ u_int namelen;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+ struct proc *p;
+{
+ printf("cpu_sysctl: Currently stoned - Cannot support the operation\n");
+ return(EOPNOTSUPP);
+}
+
+
+/*
+ * Ok these are some development functions. They map blocks of memory
+ * into the video ram virtual memory.
+ * The idea is to follow this with a call to the vidc device to
+ * reinitialise the vidc20 for the new video ram.
+ */
+
+/* Map DRAM into the video memory */
+
+int
+vmem_mapdram()
+{
+ u_int l2pagetable;
+ u_int logical;
+
+ if (videodram_start == 0 || videodram_size == 0)
+ return(ENOMEM);
+
+/* Flush any video data in the cache */
+
+ idcflush();
+
+/* Get the level 2 pagetable for the video memory */
+
+ l2pagetable = pmap_pte(kernel_pmap, videomemory.vidm_vbase);
+
+/* Map a block of DRAM into the video memory area */
+
+ for (logical = 0; logical < 0x200000; logical += NBPG) {
+ map_entry(l2pagetable, logical, videodram_start
+ + logical);
+ map_entry(l2pagetable, logical + 0x200000,
+ videodram_start + logical);
+ }
+
+/* Flush the TLB so we pick up the new mappings */
+
+ tlbflush();
+
+/* Rebuild the video memory descriptor */
+
+ videomemory.vidm_vbase = VMEM_VBASE;
+ videomemory.vidm_pbase = videodram_start;
+ videomemory.vidm_type = VIDEOMEM_TYPE_DRAM;
+ videomemory.vidm_size = videodram_size;
+
+/* Reinitialise the video system */
+
+/* video_reinit();*/
+ return(0);
+}
+
+
+/* Map VRAM into the video memory */
+
+int
+vmem_mapvram()
+{
+ u_int l2pagetable;
+ u_int logical;
+
+ if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0)
+ return(ENOMEM);
+
+/* Flush any video data in the cache */
+
+ idcflush();
+
+/* Get the level 2 pagetable for the video memory */
+
+ l2pagetable = pmap_pte(kernel_pmap, videomemory.vidm_vbase);
+
+/* Map the VRAM into the video memory area */
+
+ for (logical = 0; logical < 0x200000; logical += NBPG) {
+ map_entry(l2pagetable, logical, bootconfig.vram[0].address
+ + logical);
+ map_entry(l2pagetable, logical + 0x200000,
+ bootconfig.vram[0].address + logical);
+ }
+
+/* Flush the TLB so we pick up the new mappings */
+
+ tlbflush();
+
+/* Rebuild the video memory descriptor */
+
+ videomemory.vidm_vbase = VMEM_VBASE;
+ videomemory.vidm_pbase = VRAM_BASE;
+ videomemory.vidm_type = VIDEOMEM_TYPE_VRAM;
+ videomemory.vidm_size = bootconfig.vram[0].pages * NBPG;
+
+/* Reinitialise the video system */
+
+/* video_reinit();*/
+ return(0);
+}
+
+
+/* Set the cache behaviour for the video memory */
+
+int
+vmem_cachectl(flag)
+ int flag;
+{
+ u_int l2pagetable;
+ u_int logical;
+
+ if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0)
+ return(ENOMEM);
+
+/* Flush any video data in the cache */
+
+ idcflush();
+
+/* Get the level 2 pagetable for the video memory */
+
+ l2pagetable = pmap_pte(kernel_pmap, videomemory.vidm_vbase);
+
+/* Map the VRAM into the video memory area */
+
+ if (flag & 1) {
+ for (logical = 0; logical < 0x200000; logical += NBPG) {
+ map_entry(l2pagetable, logical, bootconfig.vram[0].address
+ + logical);
+ map_entry(l2pagetable, logical + 0x200000,
+ bootconfig.vram[0].address + logical);
+ }
+ } else {
+ for (logical = 0; logical < 0x200000; logical += NBPG) {
+ map_entry_nc(l2pagetable, logical, bootconfig.vram[0].address
+ + logical);
+ map_entry_nc(l2pagetable, logical + 0x200000,
+ bootconfig.vram[0].address + logical);
+ }
+ }
+
+/* Flush the TLB so we pick up the new mappings */
+
+ tlbflush();
+
+ return(0);
+}
+
+#if 0
+extern int vtvalbug;
+extern char *vtlastbug;
+extern u_int vtbugaddr;
+extern u_int vtbugcaddr;
+
+void
+vtbugreport()
+{
+ printf("vtvalbug = %d\n", vtvalbug);
+ if (vtlastbug)
+ printf("vtlastbug = %s\n", vtlastbug);
+ printf("vtbugaddr = %08x\n", vtbugaddr);
+ printf("vtbugcaddr = %08x\n", vtbugcaddr);
+}
+#endif
+
+/* End of machdep.c */
--- /dev/null
+/* $NetBSD: makemodes.c,v 1.3 1996/03/16 00:13:12 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name of the group nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * makemodes.c
+ *
+ * VIDC20 mode configuration program.
+ *
+ * Builds a list of configured modes using mode specifiers to select
+ * the VIDC timings from a monitor definition file
+ *
+ * Not yet perfect, this is just experimental.
+ *
+ * Created : 17/05/95
+ * Last updated : 17/05/95
+ */
+
+#include <stdio.h>
+
+/*#define VERBOSE*/
+
+#define MAX_MD 100 /* Support up to 100 modes from a file */
+
+struct md {
+ int md_xres;
+ int md_yres;
+ int md_pixelrate;
+ int md_htimings[6];
+ int md_vtimings[6];
+ int md_syncpol;
+ int md_framerate;
+} mds[MAX_MD];
+
+int md; /* Number of modes defined in the mds array */
+
+
+void makemode __P((FILE *, int, int, int, int));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char line[100]; /* Line read from mdf */
+ char token[40]; /* token read from mdf line */
+ char value[60]; /* value of token read form mdf line */
+ int startmode; /* Are we between startmode and endmode tokens */
+ char monitor[40]; /* monitor name */
+ int dpms; /* DPMS state for monitor */
+ FILE *mdf_fd; /* mdf file descriptor */
+ FILE *out_fd; /* output file descriptor */
+ int loop; /* loop counter */
+ int x, y, c, f; /* mode specifier variables */
+ int params;
+ char *ptr;
+
+/* Check the args */
+
+ if (argc < 3) {
+ fprintf(stderr, "Syntax: makemodes <mdf> <outfile> <modes>\n");
+ exit(10);
+ }
+
+/* Open the monitor definition file */
+
+ mdf_fd = fopen(argv[1], "r");
+ if (!mdf_fd) {
+ fprintf(stderr, "Cannot open monitor definition file\n");
+ exit(10);
+ }
+
+/* Open the output file */
+
+ out_fd = fopen(argv[2], "w");
+ if (!out_fd) {
+ fprintf(stderr, "Cannot open output file\n");
+ exit(10);
+ }
+
+/* Initialise some variables */
+
+ startmode = 0;
+ md = 0;
+ dpms = 0;
+ monitor[0] = 0;
+
+/* Loop for each line in the monitor definition file */
+
+ do {
+
+/* get a line */
+
+ if (fgets(line, 99, mdf_fd) == NULL)
+ break;
+
+ ptr = line;
+
+/* Skip any spaces or tabs */
+
+ while (*ptr == ' ' || *ptr == '\t')
+ ++ptr;
+
+/* Ignore comment or blank lines */
+
+ if (*ptr == '#' || strlen(ptr) < 2)
+ continue;
+
+/* Do we have a startmode or endmode token ? */
+
+ if (sscanf(ptr, "%s", token) == 1) {
+ if (strcmp(token, "startmode") == 0) {
+ if (md < MAX_MD)
+ startmode = 1;
+ }
+ if (strcmp(token, "endmode") == 0) {
+ startmode = 0;
+ ++md;
+ }
+ }
+
+/* Do we have a token:value line ? */
+
+ if (sscanf(ptr, "%[^:]:%[^\n]\n", token, value) == 2) {
+ if (strcmp(token, "monitor_title") == 0)
+ strcpy(monitor, value);
+ if (strcmp(token, "file_format") == 0) {
+ if (atoi(value) != 1) {
+ fprintf(stderr, "Unrecognised file format\n");
+ exit(10);
+ }
+ }
+ if (strcmp(token, "DPMS_state") == 0)
+ dpms = atoi(value);
+ if (strcmp(token, "x_res") == 0 && startmode)
+ mds[md].md_xres = atoi(value);
+ if (strcmp(token, "y_res") == 0 && startmode)
+ mds[md].md_yres = atoi(value);
+ if (strcmp(token, "pixel_rate") == 0 && startmode)
+ mds[md].md_pixelrate = atoi(value);
+ if (strcmp(token, "h_timings") == 0 && startmode)
+ sscanf(value, "%d,%d,%d,%d,%d,%d",
+ &mds[md].md_htimings[0],
+ &mds[md].md_htimings[1],
+ &mds[md].md_htimings[2],
+ &mds[md].md_htimings[3],
+ &mds[md].md_htimings[4],
+ &mds[md].md_htimings[5]);
+ if (strcmp(token, "v_timings") == 0 && startmode)
+ sscanf(value, "%d,%d,%d,%d,%d,%d",
+ &mds[md].md_vtimings[0],
+ &mds[md].md_vtimings[1],
+ &mds[md].md_vtimings[2],
+ &mds[md].md_vtimings[3],
+ &mds[md].md_vtimings[4],
+ &mds[md].md_vtimings[5]);
+ if (strcmp(token, "sync_pol") == 0 && startmode)
+ mds[md].md_syncpol = atoi(value);
+ }
+
+ }
+ while (!feof(mdf_fd));
+
+/* We have finished with the monitor definition file */
+
+ fclose(mdf_fd);
+
+#ifdef VERBOSE
+
+/* This was for debugging */
+
+ for (loop = 0; loop < md; ++loop) {
+ printf("%d x %d: %d %d [%d,%d,%d,%d,%d,%d] [%d,%d,%d,%d,%d,%d]\n",
+ mds[loop].md_xres,
+ mds[loop].md_yres,
+ mds[loop].md_pixelrate,
+ mds[loop].md_syncpol,
+ mds[loop].md_htimings[0],
+ mds[loop].md_htimings[1],
+ mds[loop].md_htimings[2],
+ mds[loop].md_htimings[3],
+ mds[loop].md_htimings[4],
+ mds[loop].md_htimings[5],
+ mds[loop].md_vtimings[0],
+ mds[loop].md_vtimings[1],
+ mds[loop].md_vtimings[2],
+ mds[loop].md_vtimings[3],
+ mds[loop].md_vtimings[4],
+ mds[loop].md_vtimings[5]);
+ }
+#endif
+
+/* Start building the output file */
+
+ fprintf(out_fd, "/*\n");
+ fprintf(out_fd, " * MACHINE GENERATED: DO NOT EDIT\n");
+ fprintf(out_fd, " *\n");
+ fprintf(out_fd, " * %s, from %s\n", argv[2], argv[1]);
+ fprintf(out_fd, " */\n\n");
+ fprintf(out_fd, "#include <sys/types.h>\n");
+ fprintf(out_fd, "#include <machine/vidc.h>\n\n");
+ fprintf(out_fd, "char *monitor=\"%s\";\n", monitor);
+ fprintf(out_fd, "int dpms=%d;\n", dpms);
+ fprintf(out_fd, "\n", dpms);
+ fprintf(out_fd, "struct vidc_mode vidcmodes[] = {\n");
+
+ loop = 3;
+
+/* Loop over the rest of the args processing then as mode specifiers */
+
+/* NOTE: A mode specifier cannot have a space in it at the moment */
+
+ while (argv[loop]) {
+ printf("%s ==> ", argv[loop]);
+ f = -1;
+ c = 256;
+ params = sscanf(argv[loop], "X%dY%dC%dF%d", &x, &y, &c, &f);
+ if (params < 2)
+ params = sscanf(argv[loop], "%d,%d,%d,%d", &x, &y, &c, &f);
+ if (params == 2 || params == 4)
+ makemode(out_fd, x, y, c, f);
+ else if (params == 3)
+ makemode(out_fd, x, y, 256, c);
+ else
+ printf("Invalid mode specifier\n");
+ printf("\n");
+ ++loop;
+ }
+
+/* Finish off the output file */
+
+ fprintf(out_fd, " { 0 }\n");
+ fprintf(out_fd, "};\n");
+
+ fclose(out_fd);
+}
+
+
+/* Locate an appropriate mode for the specifier and write it to the file */
+
+void makemode(out_fd, x, y, c, f)
+ FILE *out_fd;
+ int x, y, c, f;
+{
+ int loop; /* loop counter */
+ float framerate; /* frame rate */
+ int fr; /* integer frame rate */
+ int found = -1; /* array index of found mode */
+ int max = -1; /* maximum frame rate found */
+ int pos = -1; /* array index of max frame rate */
+
+/* Print some info */
+
+ printf("%d x %d x %d x %d : ", x, y, c, f);
+
+/* Scan the modes */
+
+ for (loop = 0; loop < md; ++loop) {
+
+/* X and Y have to match */
+
+ if (mds[loop].md_xres == x && mds[loop].md_yres == y) {
+
+/* Now calculate the frame rate */
+
+ framerate = (float)mds[loop].md_pixelrate /
+ (float)(mds[loop].md_htimings[0] +
+ mds[loop].md_htimings[1] +
+ mds[loop].md_htimings[2] +
+ mds[loop].md_htimings[3] +
+ mds[loop].md_htimings[4] +
+ mds[loop].md_htimings[5]) /
+ (float)(mds[loop].md_vtimings[0] +
+ mds[loop].md_vtimings[1] +
+ mds[loop].md_vtimings[2] +
+ mds[loop].md_vtimings[3] +
+ mds[loop].md_vtimings[4] +
+ mds[loop].md_vtimings[5]);
+ framerate = framerate * 1000;
+ fr = (framerate + 0.5);
+ mds[loop].md_framerate = fr;
+
+/* Print it as info */
+
+ printf("%d ", fr);
+
+/* Is this a new maximum ? */
+
+ if (max < fr) {
+ max = fr;
+ pos = loop;
+ }
+
+/* Does it match the specified frame rate ? */
+
+ if (fr == f)
+ found = loop;
+ }
+ }
+
+/* No exact match so use the max */
+
+ if (found == -1)
+ found = pos;
+
+/* Do we have an entry for this X & Y resolution */
+
+ if (found != -1) {
+ fprintf(out_fd, " { %d,/**/%d, %d, %d, %d, %d, %d,/**/%d, %d, %d, %d, %d, %d,/**/%d,/**/%d, %d },\n",
+ mds[found].md_pixelrate,
+ mds[found].md_htimings[0],
+ mds[found].md_htimings[1],
+ mds[found].md_htimings[2],
+ mds[found].md_htimings[3],
+ mds[found].md_htimings[4],
+ mds[found].md_htimings[5],
+ mds[found].md_vtimings[0],
+ mds[found].md_vtimings[1],
+ mds[found].md_vtimings[2],
+ mds[found].md_vtimings[3],
+ mds[found].md_vtimings[4],
+ mds[found].md_vtimings[5],
+ ffs(c),
+ mds[found].md_syncpol,
+ mds[found].md_framerate);
+ }
+ else {
+ fprintf(stderr, "Cannot find mode\n");
+ }
+}
+
+/* End of makemodes.c */
--- /dev/null
+/* $NetBSD: mcount.S,v 1.1 1996/01/31 23:16:32 mark Exp $ */
+
+/*
+ * Copyright (C) 1994 Mark Brinicombe
+ * Copyright (C) 1994 Brini
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of Brini may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: mcount.S,v 1.1.1.1 1996/04/24 11:08:27 deraadt Exp $
+ */
+
+fp .req r11
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+ .align 0
+
+ .global mcount
+mcount:
+ add pc, lr, #0x00000004
--- /dev/null
+/* $NetBSD: mem.c,v 1.2 1996/03/27 22:42:24 mark Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Memory special file
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+
+extern char *memhook; /* poor name! */
+caddr_t zeropage;
+
+/*ARGSUSED*/
+int
+mmopen(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+ switch (minor(dev)) {
+ default:
+ break;
+ }
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmclose(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmrw(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ register vm_offset_t o, v;
+ register int c;
+ register struct iovec *iov;
+ int error = 0;
+ static int physlock;
+
+ if (minor(dev) == 0) {
+ /* lock against other uses of shared vmmap */
+ while (physlock > 0) {
+ physlock++;
+ error = tsleep((caddr_t)&physlock, PZERO | PCATCH,
+ "mmrw", 0);
+ if (error)
+ return (error);
+ }
+ physlock = 1;
+ }
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("mmrw");
+ continue;
+ }
+ switch (minor(dev)) {
+
+/* minor device 0 is physical memory */
+ case 0:
+ v = uio->uio_offset;
+ pmap_enter(pmap_kernel(), (vm_offset_t)memhook,
+ trunc_page(v), uio->uio_rw == UIO_READ ?
+ VM_PROT_READ : VM_PROT_WRITE, TRUE);
+ o = uio->uio_offset & PGOFSET;
+ c = min(uio->uio_resid, (int)(NBPG - o));
+ error = uiomove((caddr_t)memhook + o, c, uio);
+ pmap_remove(pmap_kernel(), (vm_offset_t)memhook,
+ (vm_offset_t)memhook + NBPG);
+ continue;
+
+/* minor device 1 is kernel memory */
+ case 1:
+ v = uio->uio_offset;
+ c = min(iov->iov_len, MAXPHYS);
+ if (!kernacc((caddr_t)v, c,
+ uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
+ return (EFAULT);
+ error = uiomove((caddr_t)v, c, uio);
+ continue;
+
+/* minor device 2 is EOF/RATHOLE */
+ case 2:
+ if (uio->uio_rw == UIO_WRITE)
+ uio->uio_resid = 0;
+ return (0);
+
+/* minor device 3 (/dev/zero) is source of nulls on read, rathole on write */
+ case 3:
+ if (uio->uio_rw == UIO_WRITE) {
+ c = iov->iov_len;
+ break;
+ }
+ if (zeropage == NULL) {
+ zeropage = (caddr_t)
+ malloc(CLBYTES, M_TEMP, M_WAITOK);
+ bzero(zeropage, CLBYTES);
+ }
+ c = min(iov->iov_len, CLBYTES);
+ error = uiomove(zeropage, c, uio);
+ continue;
+
+ default:
+ return (ENXIO);
+ }
+ if (error)
+ break;
+ iov->iov_base += c;
+ iov->iov_len -= c;
+ uio->uio_offset += c;
+ uio->uio_resid -= c;
+ }
+ if (minor(dev) == 0) {
+/*unlock:*/
+ if (physlock > 1)
+ wakeup((caddr_t)&physlock);
+ physlock = 0;
+ }
+ return (error);
+}
+
+int
+mmmmap(dev, off, prot)
+ dev_t dev;
+ int off, prot;
+{
+ struct proc *p = curproc; /* XXX */
+
+ switch (minor(dev)) {
+/* minor device 0 is physical memory */
+ case 0:
+ if (off > ctob(physmem) &&
+ suser(p->p_ucred, &p->p_acflag) != 0)
+ return -1;
+ return arm_byte_to_page(off);
+
+/* minor device 1 is kernel memory */
+ case 1:
+ /* XXX - writability, executability checks? */
+ if (!kernacc((caddr_t)off, NBPG, B_READ))
+ return -1;
+ return arm_byte_to_page(vtophys(off));
+
+ default:
+ return -1;
+ }
+}
--- /dev/null
+/* $NetBSD: memset.S,v 1.1 1996/01/31 23:16:35 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * memset.S
+ *
+ * optimized memset function
+ *
+ * Created : 16/05/95
+ * Last updated : 16/05/95
+ *
+ * $Id: memset.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+
+ .global _memset
+
+/* Sets a block of memory to the specified value
+ *
+ * r0 - address
+ * r1 - byte to write
+ * r2 - number of bytes to write
+ */
+
+_memset:
+ and r1, r1, #0x000000ff /* We write bytes */
+
+ cmp r2, #0x00000004 /* Do we have less than 4 bytes */
+ blt memset_lessthanfour
+
+/* Ok first we will word align the address */
+
+ ands r3, r0, #0x00000003 /* Get the bottom two bits */
+ beq memset_addraligned /* The address is word aligned */
+
+ rsb r3, r3, #0x00000004
+ sub r2, r2, r3
+ cmp r3, #0x00000002
+ strb r1, [r0], #0x0001 /* Set 1 byte */
+ strgeb r1, [r0], #0x0001 /* Set another byte */
+ strgtb r1, [r0], #0x0001 /* and a third */
+
+ cmp r2, #0x00000004
+ blt memset_lessthanfour
+
+/* Now we must be word aligned */
+
+memset_addraligned:
+
+ orr r3, r1, r1, lsl #8 /* Repeat the byte into a word */
+ orr r3, r3, r3, lsl #16
+
+/* We know we have at least 4 bytes ... */
+
+ cmp r2, #0x00000020 /* If less than 32 then use words */
+ blt memset_lessthan32
+
+/* We have at least 32 so lets use quad words */
+
+ stmfd sp!, {r4-r6} /* Store registers */
+ mov r4, r3 /* Duplicate data */
+ mov r5, r3
+ mov r6, r3
+
+memset_loop16:
+ stmia r0!, {r3-r6} /* Store 16 bytes */
+ sub r2, r2, #0x00000010 /* Adjust count */
+ cmp r2, #0x00000010 /* Still got at least 16 bytes ? */
+ bgt memset_loop16
+
+ ldmfd sp!, {r4-r6} /* Restore registers */
+
+/* Do we need to set some words as well ? */
+
+ cmp r2, #0x00000004
+ blt memset_lessthanfour
+
+/* Have either less than 16 or less than 32 depending on route taken */
+
+memset_lessthan32:
+
+/* We have at least 4 bytes so copy as words */
+
+memset_loop4:
+ str r3, [r0], #0x0004
+ sub r2, r2, #0x0004
+ cmp r2, #0x00000004
+ bge memset_loop4
+
+memset_lessthanfour:
+ cmp r2, #0x00000000
+ moveq pc, lr /* Zero length so exit */
+
+ cmp r2, #0x00000002
+ strb r1, [r0], #0x0001 /* Set 1 byte */
+ strgeb r1, [r0], #0x0001 /* Set another byte */
+ strgtb r1, [r0], #0x0001 /* and a third */
+
+ mov pc, lr /* Exit */
--- /dev/null
+/* $NetBSD: pmap.c,v 1.4 1996/03/13 21:25:04 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * pmap.c
+ *
+ * Machine dependant vm stuff
+ *
+ * Created : 20/09/94
+ */
+
+/*
+ * The dram block info is currently referenced from the bootconfig.
+ * This should be placed in a separate structure
+ *
+ * Need a pmap_map() routine for multiple pmap_enter() calls
+ *
+ * sob sob sob - been looking at other pmap code ... don't think
+ * I should have base mine of the i386 code ...
+ */
+
+#define PMAPDEBUG 0
+
+/*
+ * Special compilation symbols
+ * DEBUG_PMAP
+ * PMAPDEBUG
+ */
+
+/* Include header files */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+
+#include <machine/bootconfig.h>
+#include <machine/pmap.h>
+#include <machine/pcb.h>
+#include <machine/param.h>
+#include <machine/katelib.h>
+#include <machine/vidc.h>
+
+#include "hydrabus.h"
+
+/*#define bcopy_page(s, d) bcopy(s, d, NBPG)*/
+/*#define bzero_page(s) bzero(s, NBPG)*/
+#define bzero_pagedir(s) bzero(s, PD_SIZE)
+
+#define VM_KERNEL_VIRTUAL_MIN KERNEL_VM_BASE + 0x00000000
+#define VM_KERNEL_VIRTUAL_MAX KERNEL_VM_BASE + 0x01ffffff
+
+#define pmap_pde(m, v) (&((m)->pm_pdir[((vm_offset_t)(v) >> PDSHIFT)&4095]))
+
+#define pmap_pte_pa(pte) (*(pte) & PG_FRAME)
+#define pmap_pde_v(pde) (*(pde) != 0)
+#define pmap_pte_v(pte) (*(pte) != 0)
+
+#define PT_KS 0x80
+
+int pmap_debug_level = -2;
+
+struct pmap kernel_pmap_store;
+pmap_t kernel_pmap;
+
+pagehook_t page_hook0;
+pagehook_t page_hook1;
+char *memhook;
+pt_entry_t msgbufpte;
+
+u_char *pmap_attributes = NULL;
+pv_entry_t pv_table = NULL;
+TAILQ_HEAD(pv_page_list, pv_page) pv_page_freelist;
+int pv_nfree = 0;
+
+vm_size_t npages;
+
+extern vm_offset_t physical_start;
+extern vm_offset_t physical_freestart;
+extern vm_offset_t physical_end;
+extern vm_offset_t physical_freeend;
+extern int physical_memoryblock;
+extern unsigned int free_pages;
+extern vm_offset_t pagetables_start;
+extern int max_processes;
+extern pt_entry_t kernel_pt_table[9];
+extern videomemory_t videomemory;
+
+extern struct proc *proc1;
+
+struct pmap **pagedirectories;
+
+vm_offset_t virtual_start;
+vm_offset_t virtual_end;
+
+vm_offset_t avail_start;
+vm_offset_t avail_end;
+
+typedef struct {
+ vm_offset_t physical;
+ vm_offset_t virtual;
+} pv_addr_t;
+
+extern pv_addr_t kernelstack;
+#if NHYDRABUS > 0
+extern pv_addr_t hydrascratch;
+#endif
+
+#define ALLOC_PAGE_HOOK(x, s) \
+ x.va = virtual_start; \
+ x.pte = (pt_entry_t *)pmap_pte(kernel_pmap, virtual_start); \
+ virtual_start += s;
+
+
+/* Local variables (not used outside this file) */
+
+/* Local function prototypes (not used outside this file) */
+
+pt_entry_t *pmap_pte __P((pmap_t /*pmap*/, vm_offset_t /*va*/));
+int pmap_page_index __P((vm_offset_t /*pa*/));
+void map_pagetable __P((vm_offset_t /*pagetable*/, vm_offset_t /*va*/,
+ vm_offset_t /*pa*/, unsigned int /*flags*/));
+void pmap_copy_on_write __P((vm_offset_t /*pa*/));
+
+void bzero_page __P((vm_offset_t));
+void bcopy_page __P((vm_offset_t, vm_offset_t));
+
+
+/* Function to set the debug level of the pmap code */
+
+void
+pmap_debug(level)
+ int level;
+{
+ pmap_debug_level = level;
+ printf("pmap_debug: level=%d\n", pmap_debug_level);
+}
+
+
+/*
+ * Functions for manipluation pv_entry structures. These are used to keep a
+ * record of the mappings of virtual addresses and the associated physical
+ * pages.
+ */
+
+struct pv_entry *
+pmap_alloc_pv()
+{
+ struct pv_page *pvp;
+ struct pv_entry *pv;
+ int i;
+
+/*
+ * Do we have any free pv_entry structures left ?
+ * If not allocate a page of them
+ */
+
+ if (pv_nfree == 0) {
+ pvp = (struct pv_page *)kmem_alloc(kernel_map, NBPG);
+ if (pvp == 0)
+ panic("pmap_alloc_pv: kmem_alloc() failed");
+ pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[1];
+ for (i = NPVPPG - 2; i; i--, pv++)
+ pv->pv_next = pv + 1;
+ pv->pv_next = 0;
+ pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG - 1;
+ TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ pv = &pvp->pvp_pv[0];
+ } else {
+ --pv_nfree;
+ pvp = pv_page_freelist.tqh_first;
+ if (--pvp->pvp_pgi.pgi_nfree == 0) {
+ TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ }
+ pv = pvp->pvp_pgi.pgi_freelist;
+#ifdef DIAGNOSTIC
+ if (pv == 0)
+ panic("pmap_alloc_pv: pgi_nfree inconsistent");
+#endif
+ pvp->pvp_pgi.pgi_freelist = pv->pv_next;
+ }
+ return pv;
+}
+
+void
+pmap_free_pv(pv)
+ struct pv_entry *pv;
+{
+ register struct pv_page *pvp;
+
+ pvp = (struct pv_page *) trunc_page(pv);
+ switch (++pvp->pvp_pgi.pgi_nfree) {
+ case 1:
+ TAILQ_INSERT_TAIL(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ default:
+ pv->pv_next = pvp->pvp_pgi.pgi_freelist;
+ pvp->pvp_pgi.pgi_freelist = pv;
+ ++pv_nfree;
+ break;
+ case NPVPPG:
+ pv_nfree -= NPVPPG - 1;
+ TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ kmem_free(kernel_map, (vm_offset_t)pvp, NBPG);
+ break;
+ }
+}
+
+
+void
+pmap_collect_pv()
+{
+ struct pv_page_list pv_page_collectlist;
+ struct pv_page *pvp, *npvp;
+ struct pv_entry *ph, *ppv, *pv, *npv;
+ int s;
+
+ TAILQ_INIT(&pv_page_collectlist);
+
+ for (pvp = pv_page_freelist.tqh_first; pvp; pvp = npvp) {
+ if (pv_nfree < NPVPPG)
+ break;
+ npvp = pvp->pvp_pgi.pgi_list.tqe_next;
+ if (pvp->pvp_pgi.pgi_nfree > NPVPPG / 3) {
+ TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ TAILQ_INSERT_TAIL(&pv_page_collectlist, pvp, pvp_pgi.pgi_list);
+ pv_nfree -= pvp->pvp_pgi.pgi_nfree;
+ pvp->pvp_pgi.pgi_nfree = -1;
+ }
+ }
+
+ if (pv_page_collectlist.tqh_first == 0)
+ return;
+
+ for (ph = &pv_table[npages - 1]; ph >= &pv_table[0]; ph--) {
+ if (ph->pv_pmap == 0)
+ continue;
+ s = splimp();
+ for (ppv = ph; (pv = ppv->pv_next) != 0; ) {
+ pvp = (struct pv_page *) trunc_page(pv);
+ if (pvp->pvp_pgi.pgi_nfree == -1) {
+ pvp = pv_page_freelist.tqh_first;
+ if (--pvp->pvp_pgi.pgi_nfree == 0) {
+ TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list);
+ }
+ npv = pvp->pvp_pgi.pgi_freelist;
+#ifdef DIAGNOSTIC
+ if (npv == 0)
+ panic("pmap_collect_pv: pgi_nfree inconsistent");
+#endif
+ pvp->pvp_pgi.pgi_freelist = npv->pv_next;
+ *npv = *pv;
+ ppv->pv_next = npv;
+ ppv = npv;
+ } else
+ ppv = pv;
+ }
+ splx(s);
+ }
+
+ for (pvp = pv_page_collectlist.tqh_first; pvp; pvp = npvp) {
+ npvp = pvp->pvp_pgi.pgi_list.tqe_next;
+ kmem_free(kernel_map, (vm_offset_t)pvp, NBPG);
+ }
+}
+
+
+/*__inline*/ int
+pmap_enter_pv(pmap, va, pind, flags)
+ pmap_t pmap;
+ vm_offset_t va;
+ int pind;
+ u_int flags;
+{
+ register struct pv_entry *pv, *npv;
+ u_int s;
+
+ if (!pv_table)
+ return(1);
+
+ s = splimp();
+ pv = &pv_table[pind];
+
+ if (pmap_debug_level >= 5)
+ printf("pmap_enter_pv: pind=%08x pv %08x: %08x/%08x/%08x\n",
+ pind, (int) pv, (int) pv->pv_va, (int) pv->pv_pmap, (int) pv->pv_next);
+
+ if (pv->pv_pmap == NULL) {
+/*
+ * No entries yet, use header as the first entry
+ */
+ pv->pv_va = va;
+ pv->pv_pmap = pmap;
+ pv->pv_next = NULL;
+ pv->pv_flags = flags;
+ splx(s);
+ return(1);
+ } else {
+/*
+ * There is at least one other VA mapping this page.
+ * Place this entry after the header.
+ */
+/*#ifdef DEBUG*/
+ for (npv = pv; npv; npv = npv->pv_next)
+ if (pmap == npv->pv_pmap && va == npv->pv_va) {
+/*
+ * HACK HACK HACK - The system vector page is wired in with pmap_enter()
+ * this mapping should be deleted during switch_exit() but at the moment it
+ * is not so a duplicate mapping is possible. For the moment we just updated
+ * flags and exit ... This should work as it is a special case.
+ */
+ npv->pv_va = va;
+ npv->pv_pmap = pmap;
+ npv->pv_flags = flags;
+ printf("pmap_enter_pv: already in pv_tab pind=%08x pv %08x: %08x/%08x/%08x",
+ pind, (int) pv, (int) pv->pv_va, (int) pv->pv_pmap, (int) pv->pv_next);
+ splx(s);
+ return(0);
+/* } else
+ panic("pmap_enter_pv: already in pv_tab pind=%08x pv %08x: %08x/%08x/%08x",
+ pind, (int) pv, (int) pv->pv_va, (int) pv->pv_pmap, (int) pv->pv_next);*/
+ }
+/*#endif*/
+ npv = pmap_alloc_pv();
+ npv->pv_va = va;
+ npv->pv_pmap = pmap;
+ npv->pv_flags = flags;
+ npv->pv_next = pv->pv_next;
+ pv->pv_next = npv;
+ }
+ splx(s);
+ return(0);
+}
+
+
+/* __inline*/ u_int
+pmap_remove_pv(pmap, va, pind)
+ pmap_t pmap;
+ vm_offset_t va;
+ int pind;
+{
+ register struct pv_entry *pv, *npv;
+ u_int s;
+ u_int flags = 0;
+
+ if (pv_table == NULL)
+ return(0);
+
+/*
+ * Remove from the PV table (raise IPL since we
+ * may be called at interrupt time).
+ */
+
+ s = splimp();
+ pv = &pv_table[pind];
+
+/* if (va == 0xefbfe000 || va == 0xefbff000 || va == 0xf1003000 || va == 0xf1004000)
+ printf("pmap_remove_pv(%08x, %08x, %d)\n",
+ (u_int)pmap, (u_int)va, pind);*/
+
+/*
+ * If it is the first entry on the list, it is actually
+ * in the header and we must copy the following entry up
+ * to the header. Otherwise we must search the list for
+ * the entry. In either case we free the now unused entry.
+ */
+
+ if (pmap == pv->pv_pmap && va == pv->pv_va) {
+ npv = pv->pv_next;
+ if (npv) {
+ *pv = *npv;
+
+ flags = npv->pv_flags;
+
+ pmap_attributes[pind] |= flags & (PT_M | PT_H);
+
+ pmap_free_pv(npv);
+ } else
+ pv->pv_pmap = NULL;
+ } else {
+ for (npv = pv->pv_next; npv; pv = npv, npv = npv->pv_next) {
+ if (pmap == npv->pv_pmap && va == npv->pv_va)
+ break;
+ }
+ if (npv) {
+ pv->pv_next = npv->pv_next;
+
+ flags = npv->pv_flags;
+ pmap_attributes[pind] |= flags & (PT_M | PT_H);
+
+ pmap_free_pv(npv);
+ }
+ }
+ splx(s);
+ return(flags);
+}
+
+
+/*__inline */ u_int
+pmap_modify_pv(pmap, va, pind, bic_mask, eor_mask)
+ pmap_t pmap;
+ vm_offset_t va;
+ int pind;
+ u_int bic_mask;
+ u_int eor_mask;
+{
+ register struct pv_entry *pv, *npv;
+ u_int s;
+ u_int flags;
+
+ if (pmap_debug_level >= 5)
+ printf("pmap_modify_pv: pmap=%08x va=%08x pi=%08x bic_mask=%08x eor_mask=%08x\n",
+ (int) pmap, (int) va, pind, bic_mask, eor_mask);
+
+ if (!pv_table)
+ return(0);
+
+#ifdef DIAGNOSTIC
+ if (pind > 0x00010000 || pind < 0) {
+ traceback();
+ panic("pmap_modify_pv: pind out of range pind = %08x va=%08x\n", pind, va);
+ }
+#endif
+
+ s = splimp();
+ pv = &pv_table[pind];
+
+ if (pmap_debug_level >= 5)
+ printf("pmap_modify_pv: pind=%08x pv %08x: %08x/%08x/%08x/%08x ",
+ pind, (int) pv, (int)pv->pv_va, (int)pv->pv_pmap, (int)pv->pv_next,
+ pv->pv_flags);
+
+/*
+ * There is at least one VA mapping this page.
+ */
+
+ for (npv = pv; npv; npv = npv->pv_next) {
+ if (pmap == npv->pv_pmap && va == npv->pv_va) {
+ flags = npv->pv_flags;
+ npv->pv_flags = ((flags & ~bic_mask) ^ eor_mask);
+ if (pmap_debug_level >= 0)
+ printf("done flags=%08x\n", flags);
+ splx(s);
+ return(flags);
+ }
+ }
+
+ if (pmap_debug_level >= 0)
+ printf("done.\n");
+ splx(s);
+ return(0);
+}
+
+
+/*
+ * Used to map a range of physical addresses into kernel
+ * virtual address space.
+ *
+ * For now, VM is already on, we only need to map the
+ * specified memory.
+ */
+
+vm_offset_t
+pmap_map(va, spa, epa, prot)
+ vm_offset_t va, spa, epa;
+ int prot;
+{
+ while (spa < epa) {
+ pmap_enter(pmap_kernel(), va, spa, prot, FALSE);
+ va += NBPG;
+ spa += NBPG;
+ }
+ return(va);
+}
+
+
+/*
+ * void pmap_bootstrap(pd_entry_t *kernel_l1pt)
+ *
+ * bootstrap the pmap system. This is called from initarm and allows
+ * the pmap system to initailise any structures it requires.
+ *
+ * Currently this sets up the kernel_pmap that is statically allocated
+ * and also allocated virtual addresses for certain page hooks.
+ * Currently the only one page hook is allocated that is used
+ * to zero physical pages of memory.
+ * It also initialises the start and end address of the kernel data space.
+ */
+
+void
+pmap_bootstrap(kernel_l1pt)
+ pd_entry_t *kernel_l1pt;
+{
+ kernel_pmap = &kernel_pmap_store;
+
+ kernel_pmap->pm_pdir = kernel_l1pt;
+ kernel_pmap->pm_pptpt = kernel_pt_table[2];
+ simple_lock_init(&kernel_pmap->pm_lock);
+ kernel_pmap->pm_count = 1;
+
+ virtual_start = VM_KERNEL_VIRTUAL_MIN;
+ virtual_end = VM_KERNEL_VIRTUAL_MAX;
+
+ ALLOC_PAGE_HOOK(page_hook0, NBPG);
+ ALLOC_PAGE_HOOK(page_hook1, NBPG);
+
+/* The mem special device needs a virtual hook but we don't need a pte */
+
+ memhook = (char *)virtual_start;
+ virtual_start += NBPG;
+
+ msgbufp = (struct msgbuf *)virtual_start;
+ msgbufpte = (pt_entry_t)pmap_pte(kernel_pmap, virtual_start);
+ virtual_start += round_page(sizeof(struct msgbuf));
+
+#if PMAPDEBUG > 0
+ printf("pmap_bootstrap: page_hook = V%08x pte = V%08x\n",
+ page_hook_addr0, page_hook_pte0);
+#endif
+
+#if NHYDRABUS > 0
+ hydrascratch.virtual = virtual_start;
+ virtual_start += NBPG;
+
+ *((pt_entry_t *)pmap_pte(kernel_pmap, hydrascratch.virtual)) = L2_PTE_NC(hydrascratch.physical, AP_KRW);
+ tlbflush();
+#endif
+}
+
+
+/*
+ * void pmap_init(void)
+ *
+ * Initialize the pmap module.
+ * Called by vm_init() in vm/vm_init.c in order to initialise
+ * any structures that the pmap system needs to map virtual memory.
+ */
+
+extern int physmem;
+
+void
+pmap_init()
+{
+ vm_size_t s;
+ vm_offset_t addr;
+
+/* printf("pmap_init:\n");*/
+
+ npages = pmap_page_index(physical_freeend - 1) + 1;
+ printf("Number of pages to handle = %ld\n", npages);
+
+/*
+ * Set the available memory vars - These do not map to real memory
+ * addresses. They are used by ps for %mem calculations.
+ */
+
+/* avail_start = pmap_page_index(physical_start) * NBPG;
+ avail_end = pmap_page_index(physical_freeend) * NBPG;*/
+ avail_start = 0;
+ avail_end = physmem * NBPG;
+
+ s = (vm_size_t) (sizeof(struct pv_entry) * npages + npages);
+/* printf("pv_table size = %08x\n", s);*/
+ s = round_page(s);
+ addr = (vm_offset_t) kmem_alloc(kernel_map, s);
+/* printf("addr = %08x", addr);*/
+ pv_table = (pv_entry_t) addr;
+ addr += sizeof(struct pv_entry) * npages;
+ pmap_attributes = (char *) addr;
+/* printf(" attributes = %08x\n", pmap_attributes);*/
+
+/* Ok currently there are some difficulties in allocating the process
+ * page directories on the fly. This is because the page directories
+ * are 16KB in size and there are no garentees that we can get 16KB
+ * continuous physical memory starting on a 16KB boundry from
+ * kmem_alloc() etc.
+ *
+ * For the moment a number of pages will have been reserved at the top
+ * of the physical memory map.
+ */
+
+ s = max_processes * sizeof(struct pmap *);
+ pagedirectories = (struct pmap **)kmem_alloc(kernel_map, s);
+
+#if PMAPDEBUG > 0
+ printf("pagedirectories pointers at %08x\n", pagedirectories);
+#endif
+
+ bzero(pagedirectories, s);
+ printf("%dKB reserved for L1 page tables\n",
+ max_processes * NBPG * 4 / 1024);
+}
+
+
+/*
+ * Create and return a physical map.
+ *
+ * If the size specified for the map is zero, the map is an actual physical
+ * map, and may be referenced by the hardware.
+ *
+ * If the size specified is non-zero, the map will be used in software only,
+ * and is bounded by that size.
+ */
+
+pmap_t
+pmap_create(size)
+ vm_size_t size;
+{
+ register pmap_t pmap;
+
+/*
+ * Software use map does not need a pmap
+ */
+
+ if (size) return NULL;
+
+/* Allocate memory for pmap structure and zero it */
+/* XXX: I assume waiting here us ok */
+
+ pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
+ bzero(pmap, sizeof(*pmap));
+
+/* Now init the machine part of the pmap */
+
+ pmap_pinit(pmap);
+ return(pmap);
+}
+
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ *
+ * MAJOR rewrite pending
+ */
+
+int
+pmap_allocpagedir(pmap)
+ struct pmap *pmap;
+{
+ int loop;
+ vm_offset_t pd;
+ pt_entry_t *pte;
+
+ if (pmap_debug_level >= 0)
+ printf("pmap_allocpagedir: pmap=%08x\n", (int)pmap);
+
+/*
+ * No need to allocate page table space yet but we do need a
+ * valid page directory table.
+ */
+
+/* Ok we need a 16KB aligned check of memory */
+
+ for (loop = 0; loop < max_processes; ++loop) {
+/* Locate a free page directory */
+
+ if (pagedirectories[loop] == 0) {
+/* Register the pmap for this page directory */
+
+ pagedirectories[loop] = pmap;
+
+/* Calculate the virtual address of the page directory */
+
+ pmap->pm_pdir = (pd_entry_t *) ((PAGE_DIRS_BASE
+ + PD_SIZE) + loop * PD_SIZE);
+ pd = (vm_offset_t)(pagetables_start + loop * PD_SIZE);
+#if PMAP_DEBUG > 0
+ printf("pmap_pinit: page dir at V%08x P%08x\n",
+ pmap->pm_pdir, pde);
+#endif
+
+/* Calculate the address of the page table entry needed to map this page dir */
+
+ pte = (pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+ + ((unsigned int)pmap->pm_pdir >> (PGSHIFT-2)));
+
+/* See if it is already mapped */
+
+ if (*(pte + 0) != 0 || *(pte + 1) != 0
+ || *(pte + 2) != 0 || *(pte + 3) != 0) {
+ if (pmap_debug_level >= 0)
+ printf("pmap_pinit = V%08x (%08x) (%08x) (%08x) (%08x)\n",
+ (int) pte, *(pte+0), *(pte+1),
+ *(pte+2), *(pte+3));
+ }
+
+/* Hook this page directory into the memory map */
+
+ *(pte + 0) = L2_PTE((pd + (0 * NBPG)) & PG_FRAME, AP_KRW);
+ *(pte + 1) = L2_PTE((pd + (1 * NBPG)) & PG_FRAME, AP_KRW);
+ *(pte + 2) = L2_PTE((pd + (2 * NBPG)) & PG_FRAME, AP_KRW);
+ *(pte + 3) = L2_PTE((pd + (3 * NBPG)) & PG_FRAME, AP_KRW);
+
+#if PMAP_DEBUG > 0
+ printf("pmap_pinit = V%08x (%08x) (%08x) (%08x) (%08x)\n",
+ pte, *(pte+0), *(pte+1), *(pte+2), *(pte+3));
+#endif
+
+/* Flush the TLB so that the page directory is accessible */
+
+ tlbflush();
+
+/* Clear it down */
+
+ bzero_pagedir(pmap->pm_pdir);
+
+/* Duplicate the kernel mapping i.e. all mappings 0xf0000000 + */
+
+ bcopy((char *)kernel_pmap->pm_pdir + 0x3c00,
+ (char *)pmap->pm_pdir + 0x3c00, 0x400);
+
+/* Borrow the kernel's system page as well */
+
+/* pmap->pm_pdir[0] = kernel_pmap->pm_pdir[0];
+ pmap->pm_pdir[1] = kernel_pmap->pm_pdir[1];
+ pmap->pm_pdir[2] = kernel_pmap->pm_pdir[2];
+ pmap->pm_pdir[3] = kernel_pmap->pm_pdir[3];*/
+
+/*printf("L1 pagetable V%08x, P%08x\n", pmap->pm_pdir, pd);*/
+
+/* Allocate a page table to map all the page tables for this pmap */
+
+ if (pmap->pm_vptpt == 0) {
+ pmap->pm_vptpt = kmem_alloc(kernel_map, NBPG);
+ pmap->pm_pptpt = pmap_extract(kernel_pmap,
+ pmap->pm_vptpt) & PG_FRAME;
+ }
+
+/* printf("pagetable = V%08x P%08x\n", pagetable,
+ pmap_extract(kernel_pmap, pagetable));
+ printf("L1 addr = %08x\n",
+ &((pd_entry_t **)pmap->pm_pdir)[0xefc]);
+*/
+
+/* Wire in this page table */
+
+ pmap->pm_pdir[0xefc] = L1_PTE(pmap->pm_pptpt + 0x000);
+ pmap->pm_pdir[0xefd] = L1_PTE(pmap->pm_pptpt + 0x400);
+ pmap->pm_pdir[0xefe] = L1_PTE(pmap->pm_pptpt + 0x800);
+ pmap->pm_pdir[0xeff] = L1_PTE(pmap->pm_pptpt + 0xc00);
+
+/* printf("copying %08x\n", (PROCESS_PAGE_TBLS_BASE
+ + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) + 0xf00));
+*/
+
+/*
+ * Map the kernel page tables for 0xf0000000 + and 0x00000000 into
+ * the page table used to map the pmap's page tables
+ */
+
+ bcopy((char *)(PROCESS_PAGE_TBLS_BASE
+ + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) + 0xf00),
+ (char *)pmap->pm_vptpt + 0xf00, 0x100);
+/* bcopy((char *)(PROCESS_PAGE_TBLS_BASE
+ + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) + 0x000),
+ (char *)pmap->pm_vptpt + 0x000, 0x004);*/
+
+/* Add a self reference reference */
+
+ *((pt_entry_t *)(pmap->pm_vptpt + 0xefc)) =
+ L2_PTE(pmap->pm_pptpt, AP_KRWUR);
+
+/*
+ if (pmap_debug_level >= 0) {
+ printf("::::%08x %08x\n",
+ ((pt_entry_t *)(pmap->pm_vptpt + 0xefc)),
+ &((pt_entry_t *)pmap->pm_vptpt)[0xefc >> 2]);
+ }
+*/
+
+/*
+ * Now we get nasty. We need to map the page directory to a standard address
+ * in the memory map. This means we can easily find the active page directory.
+ * This is needed by pmap_pte to hook in an alternate pmap's page tables.
+ * This means that a page table is needed in each process to map this memory
+ * as the kernel tables cannot be used as they are shared.
+ * The HACK is to borrow some of the space in the page table that maps all
+ * the pmap page tables.
+ * Mapping a 16KB page directory into that means that a 16MB chunk of the
+ * memory map will no longer be mappable.
+ * Eventually a chuck of user space (at the top end) could be reserved for
+ * this but for the moment the 16MB block at 0xf5000000 is not allocated and
+ * so has become reserved for this processes.
+ */
+
+ *((pt_entry_t *)(pmap->pm_vptpt + 0xf50)) =
+ L2_PTE(pd + 0x0000, AP_KRW);
+ *((pt_entry_t *)(pmap->pm_vptpt + 0xf54)) =
+ L2_PTE(pd + 0x1000, AP_KRW);
+ *((pt_entry_t *)(pmap->pm_vptpt + 0xf58)) =
+ L2_PTE(pd + 0x2000, AP_KRW);
+ *((pt_entry_t *)(pmap->pm_vptpt + 0xf5c)) =
+ L2_PTE(pd + 0x3000, AP_KRW);
+
+ pmap->pm_count = 1;
+ simple_lock_init(&pmap->pm_lock);
+ return(0);
+ }
+ }
+
+ return(1);
+}
+
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ *
+ * MAJOR rewrite pending
+ */
+
+void
+pmap_pinit(pmap)
+ struct pmap *pmap;
+{
+ if (pmap_debug_level >= 0)
+ printf("pmap_pinit: pmap=%08x\n", (int)pmap);
+
+/* Keep looping until we succeed in allocating a page directory */
+
+ while (pmap_allocpagedir(pmap) != 0) {
+/*
+ * Ok all the allocated L1 page tables are in use so we should sleep for
+ * a while. We only sleep for 10 secs at most. Although we will be wakened
+ * if a slot became available it could be possible for things to jamup with
+ * every process waiting on a process that is waiting for a page table.
+ * If we time out then it means that all the page tables are in use and
+ * there has not be a process termination in 10 secs i.e. possible deadlock
+ */
+
+/*
+ * The snag with this routine is it is not allowed to fail. If we
+ * do detect a possible deadlock then we can report it. The Q is what to
+ * do next. We could start randomly killing processes or process groups.
+ * Since this process is only part formed it is not easy to kill. The
+ * best thing may be to kill it parent.
+ */
+
+/* What we should do here is start swapping out processes. That way
+ * the page directory for the process will be released.
+ * The pagedaemon will swap out processes but only in low memory conditions.
+ * Lack of page directories does not count so we will have to swapout
+ * processes ourselves.
+ */
+
+ if (tsleep((caddr_t)pagedirectories, PZERO, "l1ptwait", 1000)
+ == EWOULDBLOCK)
+ printf("Warning: Possible process deadlock due to shortage of L1 page tables\n");
+ }
+}
+
+
+/*
+ * Retire the given physical map from service.
+ * Should only be called if the map contains no valid mappings.
+ */
+
+void
+pmap_destroy(pmap)
+ pmap_t pmap;
+{
+ int count;
+
+ if (pmap_debug_level >= 0)
+ printf("pmap_destroy: pmap = %08x\n", (int) pmap);
+
+ if (pmap == NULL)
+ return;
+
+ simple_lock(&pmap->pm_lock);
+ count = --pmap->pm_count;
+ simple_unlock(&pmap->pm_lock);
+ if (count == 0) {
+ pmap_release(pmap);
+ free((caddr_t)pmap, M_VMPMAP);
+ } else
+ printf("pmap_destroy: pm_count=%d\n", count);
+}
+
+
+void
+pmap_freepagedir(pmap)
+ register pmap_t pmap;
+{
+ int index;
+
+ index = (((u_int) pmap->pm_pdir) - PAGE_DIRS_BASE - PD_SIZE) / PD_SIZE;
+ if (pagedirectories[index] != pmap)
+ panic("pm_pdir inconsistancy found\n");
+
+ pagedirectories[index] = 0;
+
+/* Wake up any sleeping processes waiting for a l1 page table */
+
+ wakeup((caddr_t)pagedirectories);
+}
+
+
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+
+void
+pmap_release(pmap)
+ register pmap_t pmap;
+{
+ if (pmap_debug_level >= 0)
+ printf("pmap_release: pmap=%08x\n", (int) pmap);
+
+ if (pmap->pm_count != 1) /* XXX: needs sorting */
+ panic("pmap_release count");
+
+/* Free the memory used for the page table mapping */
+
+ kmem_free(kernel_map, (vm_offset_t)pmap->pm_vptpt, NBPG);
+
+ pmap_freepagedir(pmap);
+}
+
+
+/*
+ * void pmap_reference(pmap_t pmap)
+ *
+ * Add a reference to the specified pmap.
+ */
+
+void
+pmap_reference(pmap)
+ pmap_t pmap;
+{
+ if (pmap == NULL)
+ return;
+
+ simple_lock(&pmap->pm_lock);
+ pmap->pm_count++;
+ simple_unlock(&pmap->pm_lock);
+}
+
+
+/*
+ * void pmap_virtual_space(vm_offset_t *start, vm_offset_t *end)
+ *
+ * Return the start and end addresses of the kernel's virtual space.
+ * These values are setup in pmap_bootstrap and are updated as pages
+ * are allocated.
+ */
+
+void
+pmap_virtual_space(start, end)
+ vm_offset_t *start;
+ vm_offset_t *end;
+{
+ *start = virtual_start;
+ *end = virtual_end;
+}
+
+
+/*
+ * void pmap_pageable(pmap_t pmap, vm_offset_t sva, vm_offset_t eva,
+ * boolean_t pageable)
+ *
+ * Make the specified pages (by pmap, offset) pageable (or not) as requested.
+ *
+ * A page which is not pageable may not take a fault; therefore, its
+ * page table entry must remain valid for the duration.
+ *
+ * This routine is merely advisory; pmap_enter will specify that these
+ * pages are to be wired down (or not) as appropriate.
+ */
+
+void
+pmap_pageable(pmap, sva, eva, pageable)
+ pmap_t pmap;
+ vm_offset_t sva;
+ vm_offset_t eva;
+ boolean_t pageable;
+{
+/*
+ * Ok we can only make the specified pages pageable under the following
+ * conditions.
+ * 1. pageable == TRUE
+ * 2. eva = sva + NBPG
+ * 3. the pmap is the kernel_pmap ??? - got this from i386/pmap.c ??
+ *
+ * right this will get called when making pagetables pageable
+ */
+
+ if (pmap_debug_level >= 5)
+ printf("pmap_pageable: pmap=%08x sva=%08x eva=%08x p=%d\n",
+ (int) pmap, (int) sva, (int) eva, (int) pageable);
+
+ if (pmap == kernel_pmap && pageable && eva == (sva + NBPG)) {
+ vm_offset_t pa;
+ pt_entry_t *pte;
+
+ pte = pmap_pte(pmap, sva);
+ if (!pte)
+ return;
+ if (!pmap_pte_v(pte))
+ return;
+ pa = pmap_pte_pa(pte);
+
+/*
+ * Mark it unmodified to avoid pageout
+ */
+ pmap_clear_modify(pa);
+
+ if (pmap_debug_level >= 0)
+ printf("pmap_pageable: ermm can't really do this yet (%08x)!\n",
+ (int) sva);
+ }
+}
+
+
+void
+pmap_activate(pmap, pcbp)
+ pmap_t pmap;
+ struct pcb *pcbp;
+{
+ if (pmap != NULL) {
+#if PMAP_DEBUG > 1
+ printf("pmap_activate: pagedir = V%08x\n", pmap->pm_pdir);
+#endif
+ pcbp->pcb_pagedir = (pd_entry_t *)pmap_extract(kernel_pmap,
+ (vm_offset_t)pmap->pm_pdir);
+ if (pmap_debug_level >= 0)
+ printf("pmap_activate: pmap=%08x pcb=%08x pdir=%08x l1=%08x\n",
+ (int) pmap, (int) pcbp, (int) pmap->pm_pdir,
+ (int) pcbp->pcb_pagedir);
+#if PMAP_DEBUG > 1
+ printf("pmap_activate: pagedir = P%08x\n", pcbp->pcb_pagedir);
+#endif
+
+ if (pmap == &curproc->p_vmspace->vm_pmap) {
+ printf("pmap: Setting TTB\n");
+ setttb((u_int)pcbp->pcb_pagedir);
+ }
+ pmap->pm_pdchanged = FALSE;
+ }
+#if PMAP_DEBUG > 1
+ printf("pmap_activate: done\n");
+#endif
+}
+
+
+/*
+ * void pmap_zero_page(vm_offset_t phys)
+ *
+ * zero fill the specific physical page. To do this the page must be
+ * mapped into the virtual memory. Then bzero can be used to zero it.
+ */
+
+void
+pmap_zero_page(phys)
+ vm_offset_t phys;
+{
+#if PMAPDEBUG > 4
+ printf("pmap_zero_page: pa = %08x", phys);
+#endif
+
+/* Hook the physical page into the memory at our special hook point */
+
+ *page_hook0.pte = L2_PTE(phys & PG_FRAME, AP_KRW);
+
+/* Flush the tlb - eventually this can be a purge tlb */
+
+ tlbflush();
+
+/* Zero the memory */
+
+#if PMAPDEBUG > 4
+ printf(" zeroing...");
+#endif
+ bzero_page(page_hook0.va);
+ idcflush();
+#if PMAPDEBUG > 4
+ printf("done.\n");
+#endif
+}
+
+
+/*
+ * void pmap_copy_page(vm_offset_t src, vm_offset_t dest)
+ *
+ * pmap_copy_page copies the specified page by mapping it into virtual
+ * memory and using bcopy to copy its contents.
+ */
+
+void
+pmap_copy_page(src, dest)
+ vm_offset_t src;
+ vm_offset_t dest;
+{
+ if (pmap_debug_level >= -1)
+ printf("pmap_copy_page: src=P%08x dest=P%08x\n",
+ (int) src, (int) dest);
+
+/* Hook the physical page into the memory at our special hook point */
+
+ *page_hook0.pte = L2_PTE(src & PG_FRAME, AP_KRW);
+ *page_hook1.pte = L2_PTE(dest & PG_FRAME, AP_KRW);
+
+/* Flush the tlb - eventually this can be a purge tlb */
+
+ tlbflush();
+
+/* Copy the memory */
+
+ bcopy_page(page_hook0.va, page_hook1.va);
+ idcflush();
+}
+
+
+/*
+ * int pmap_next_page(vm_offset_t *addr)
+ *
+ * Allocate another physical page returning true or false depending
+ * on whether a page could be allocated.
+ *
+ * MARK - This needs optimising ... look at the amiga version
+ */
+
+int
+pmap_next_page(addr)
+ vm_offset_t *addr;
+{
+ if (physical_freestart == physical_freeend) {
+ if (pmap_debug_level >= 0)
+ printf("pmap_next_page: Trying to allocate beyond memory\n");
+ return(FALSE);
+ }
+
+ pmap_zero_page(physical_freestart);
+ *addr = physical_freestart;
+ --free_pages;
+
+ physical_freestart += NBPG;
+ if (physical_freestart == (bootconfig.dram[physical_memoryblock].address
+ + bootconfig.dram[physical_memoryblock].pages * NBPG)) {
+ ++physical_memoryblock;
+ if (bootconfig.dram[physical_memoryblock].address != 0)
+ physical_freestart = bootconfig.dram[physical_memoryblock].address;
+ }
+
+#if PMAPDEBUG > 10
+ printf("pmap_next_page: Allocated physpage %08x\n", *addr);
+ printf("pmap_next_page: Next page is %08x\n", physical_freestart);
+#endif
+
+ return(TRUE);
+}
+
+
+/*
+ * int pmap_next_phys_page(vm_offset_t *addr)
+ *
+ * Allocate another physical page returning true or false depending
+ * on whether a page could be allocated.
+ */
+
+vm_offset_t
+pmap_next_phys_page(addr)
+ vm_offset_t addr;
+
+{
+ int loop;
+
+ if (addr < bootconfig.dram[0].address)
+ return(bootconfig.dram[0].address);
+
+ loop = 0;
+
+ while (bootconfig.dram[loop].address != 0
+ && addr > (bootconfig.dram[loop].address + bootconfig.dram[loop].pages * NBPG))
+ ++loop;
+
+ if (bootconfig.dram[loop].address == 0)
+ return(0);
+
+ addr += NBPG;
+
+ if (addr >= (bootconfig.dram[loop].address + bootconfig.dram[loop].pages * NBPG)) {
+ if (bootconfig.dram[loop + 1].address == 0)
+ return(0);
+ addr = bootconfig.dram[loop + 1].address;
+ }
+
+ return(addr);
+}
+
+
+/*
+ * unsigned int pmap_free_pages(void)
+ *
+ * Returns the number of free pages the system has.
+ * free_pages is set up during initarm and decremented every time a page
+ * is allocated.
+ */
+
+unsigned int
+pmap_free_pages()
+{
+#if PMAPDEBUG > 0
+ printf("pmap_free_pages: %08x pages free\n", free_pages);
+#endif
+ return(free_pages);
+}
+
+
+/*
+ * int pmap_page_index(vm_offset_t pa)
+ *
+ * returns a linear index to the physical page. This routine has to take
+ * a physical address and work out the corresponding physical page number.
+ * There does not appear to be a simple way of doing this as the memory
+ * is split into a series of blocks. We search each block to determine
+ * which block the physical page is. Once we have scanned the blocks to
+ * this point we can calculate the physical page index.
+ */
+
+int
+pmap_page_index(pa)
+ vm_offset_t pa;
+{
+ int index;
+ int loop;
+
+#if PMAPDEBUG > 0
+ printf("pmap_page_index: pa = P%08x", (int)pa);
+#endif
+
+ if (pa < bootconfig.dram[0].address)
+ return(-1);
+
+ index = 0;
+ for (loop = 0; loop < bootconfig.dramblocks; ++loop) {
+ if (pa < (bootconfig.dram[loop].address
+ + bootconfig.dram[loop].pages * NBPG)) {
+ index += (pa - bootconfig.dram[loop].address) >> PGSHIFT;
+#if PMAPDEBUG > 0
+ printf(" index = %08x\n" ,index);
+#endif
+#ifdef DIAGNOSTIC
+ if (index > 0x00010000 || index < 0)
+ printf("pmap_page_index: pa = %08x\n", (int)pa);
+#endif
+ return(index);
+ } else
+ index += bootconfig.dram[loop].pages;
+ }
+#if PMAPDEBUG > 0
+ printf(" index = Invalid\n");
+#endif
+ if (pmap_debug_level >= 1)
+ printf("page invalid - no index %08x\n", (int) pa);
+ return(-1);
+}
+
+
+void
+pmap_remove(pmap, sva, eva)
+ struct pmap *pmap;
+ vm_offset_t sva;
+ vm_offset_t eva;
+{
+ register pt_entry_t *pte = NULL;
+ vm_offset_t pa;
+ int pind;
+ int flush = 0;
+
+ idcflush();
+
+ if (pmap_debug_level >= 0)
+ printf("pmap_remove: pmap=%08x sva=%08x eva=%08x\n", (int) pmap,
+ (int) sva, (int) eva);
+
+ sva &= PG_FRAME;
+ eva &= PG_FRAME;
+
+/*
+ * We need to acquire a pointer to a page table page before entering
+ * the following loop.
+ */
+
+ while (sva < eva) {
+ pte = pmap_pte(pmap, sva);
+ if (pte) break;
+ sva = (sva & PD_MASK) + NBPD;
+ }
+
+ while (sva < eva) {
+/* only check once in a while */
+ if ((sva & PT_MASK) == 0) {
+ if (!pmap_pde_v(pmap_pde(pmap, sva))) {
+/* We can race ahead here, to the next pde. */
+ sva += NBPD;
+ pte += arm_byte_to_page(NBPD);
+ continue;
+ }
+ }
+
+ if (!pmap_pte_v(pte))
+ goto next;
+
+ flush = 1;
+
+/*
+ * Update statistics
+ */
+
+/* Wired bit done below */
+
+/*
+ if (pmap_pte_w(pte))
+ pmap->pm_stats.wired_count--;
+*/
+ pmap->pm_stats.resident_count--;
+
+ pa = pmap_pte_pa(pte);
+
+/*
+ * Invalidate the PTEs.
+ * XXX: should cluster them up and invalidate as many
+ * as possible at once.
+ */
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_REMOVE)
+ printf("remove: inv pte at %x(%x) ", pte, *pte);
+#endif
+
+ if ((pind = pmap_page_index(pa)) != -1) {
+/* pmap_attributes[pind] |= *pte & (PG_M | PG_U);*/
+/* pmap_remove_pv will update pmap_attributes */
+#ifdef DIAGNOSTIC
+ if (pind > 0x00010000 || pind < 0) {
+ printf("eerk ! pind=%08x pa=%08x\n", pind, (int) pa);
+ panic("The axe has fallen, were dead\n");
+ }
+#endif
+ if (pmap_remove_pv(pmap, sva, pind) & PT_W)
+ pmap->pm_stats.wired_count--;
+ }
+
+ *pte = 0;
+next:
+ sva += NBPG;
+ pte++;
+ }
+
+ if (flush)
+ pmap_update();
+}
+
+
+/*
+ * Routine: pmap_remove_all
+ * Function:
+ * Removes this physical page from
+ * all physical maps in which it resides.
+ * Reflects back modify bits to the pager.
+ */
+
+void
+pmap_remove_all(pa)
+ vm_offset_t pa;
+{
+ struct pv_entry *ph, *pv, *npv;
+ register pmap_t pmap;
+ register pt_entry_t *pte;
+ int pind;
+ int s;
+
+ idcflush();
+ if (pmap_debug_level >= 0)
+ printf("pmap_remove_all: pa=%08x ", (int) pa);
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
+ printf("pmap_remove_all(%x)", (int) pa);
+ /*pmap_pvdump(pa);*/
+#endif
+
+ if ((pind = pmap_page_index(pa)) == -1) {
+ if (pmap_debug_level >= 0)
+ printf("no accounting\n");
+ return;
+ }
+
+ s = splimp();
+ pv = ph = &pv_table[pind];
+
+ if (ph->pv_pmap == NULL) {
+ if (pmap_debug_level >= 0)
+ printf("free page\n");
+ splx(s);
+ return;
+ }
+
+ while (pv) {
+ pmap = pv->pv_pmap;
+ pte = pmap_pte(pmap, pv->pv_va);
+
+ if (pmap_debug_level >= 0)
+ printf("[%08x,%08x,%08x,%08x] ", (int) pmap, *pte,
+ (int) pv->pv_va, pv->pv_flags);
+
+#ifdef DEBUG
+ if (!pte || !pmap_pte_v(pte) || pmap_pte_pa(pte) != pa)
+ panic("pmap_remove_all: bad mapping");
+#endif
+
+/*
+ * Update statistics
+ */
+/* Wired bit done below */
+
+/*
+ if (pmap_pte_w(pte))
+ pmap->pm_stats.wired_count--;
+*/
+ pmap->pm_stats.resident_count--;
+
+ if (pv->pv_flags & PT_W)
+ pmap->pm_stats.wired_count--;
+
+/*
+ * Invalidate the PTEs.
+ * XXX: should cluster them up and invalidate as many
+ * as possible at once.
+ */
+#ifdef DEBUG
+ if (pmapdebug & PDB_REMOVE)
+ printf("remove: inv pte at %x(%x) ", pte, *pte);
+#endif
+
+#ifdef needednotdone
+reduce wiring count on page table pages as references drop
+#endif
+
+/*
+ * Update saved attributes for managed page
+ */
+
+/* pmap_attributes[pind] |= *pte & (PG_M | PG_U);*/
+ pmap_attributes[pind] |= pv->pv_flags & (PT_M | PT_H);
+
+ *pte = 0;
+
+ npv = pv->pv_next;
+ if (pv == ph)
+ ph->pv_pmap = NULL;
+ else
+ pmap_free_pv(pv);
+ pv = npv;
+ }
+ splx(s);
+
+ if (pmap_debug_level >= 0)
+ printf("done\n");
+
+ pmap_update();
+}
+
+
+/*
+ * Set the physical protection on the specified range of this map as requested.
+ */
+
+void
+pmap_protect(pmap, sva, eva, prot)
+ pmap_t pmap;
+ vm_offset_t sva;
+ vm_offset_t eva;
+ vm_prot_t prot;
+{
+ register pt_entry_t *pte = NULL;
+ register int armprot;
+ int flush = 0;
+ vm_offset_t pa;
+ int pind;
+
+ if (pmap_debug_level >= 0)
+ printf("pmap_protect: pmap=%08x %08x->%08x %08x\n",
+ (int) pmap, (int) sva, (int) eva, prot);
+
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+ pmap_remove(pmap, sva, eva);
+ return;
+ }
+ if (prot & VM_PROT_WRITE)
+ return;
+
+ sva &= PG_FRAME;
+ eva &= PG_FRAME;
+
+/*
+ * We need to acquire a pointer to a page table page before entering
+ * the following loop.
+ */
+
+ while (sva < eva) {
+ pte = pmap_pte(pmap, sva);
+ if (pte)
+ break;
+ sva = (sva & PD_MASK) + NBPD;
+ }
+
+ while (sva < eva) {
+/*printf("pmap_protect: sva = %08x eva=%08x\n", sva, eva);*/
+/* only check once in a while */
+ if ((sva & PT_MASK) == 0) {
+ if (!pmap_pde_v(pmap_pde(pmap, sva))) {
+/* We can race ahead here, to the next pde. */
+ sva += NBPD;
+ pte += arm_byte_to_page(NBPD);
+ continue;
+ }
+ }
+
+ if (!pmap_pte_v(pte))
+ goto next;
+
+ flush = 1;
+
+ armprot = 0;
+/*
+ if (prot & VM_PROT_WRITE)
+ armprot |= PT_AP(AP_W);
+*/
+ if (sva < VM_MAXUSER_ADDRESS)
+ armprot |= PT_AP(AP_U);
+ else if (sva < VM_MAX_ADDRESS)
+ armprot |= PT_AP(AP_W); /* XXX Ekk what is this ? */
+ *pte = (*pte & 0xfffff00f) | armprot;
+
+ pa = pmap_pte_pa(pte);
+
+/* Get the physical page index */
+
+ if ((pind = pmap_page_index(pa)) == -1)
+ panic("pmap_protect: pmap_page_index failed for pte %08x\n", pte);
+
+/* Clear write flag */
+
+ pmap_modify_pv(pmap, sva, pind, PT_Wr, 0);
+next:
+ sva += NBPG;
+ pte++;
+ }
+
+ if (flush)
+ pmap_update();
+}
+
+
+/*
+ * void pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot,
+ * boolean_t wired)
+ *
+ * Insert the given physical page (p) at
+ * the specified virtual address (v) in the
+ * target physical map with the protection requested.
+ *
+ * If specified, the page will be wired down, meaning
+ * that the related pte can not be reclaimed.
+ *
+ * NB: This is the only routine which MAY NOT lazy-evaluate
+ * or lose information. That is, this routine must actually
+ * insert this page into the given map NOW.
+ */
+
+void
+pmap_enter(pmap, va, pa, prot, wired)
+ pmap_t pmap;
+ vm_offset_t va;
+ vm_offset_t pa;
+ vm_prot_t prot;
+ boolean_t wired;
+{
+ register pt_entry_t *pte;
+ register u_int npte;
+ int pind = -2;
+ u_int cacheable = 0;
+
+#if PMAP_DEBUG > 5
+ printf("pmap_enter: V%08x P%08x in pmap V%08x\n", va, pa, pmap);
+#endif
+
+ if (pmap_debug_level >= 5)
+ printf("pmap_enter: V%08x P%08x in pmap V%08x prot=%08x, wired = %d\n",
+ (int) va, (int) pa, (int) pmap, prot, wired);
+
+/* Valid pmap ? */
+
+ if (pmap == NULL)
+ return;
+
+/* Valid address ? */
+
+ if (va >= VM_KERNEL_VIRTUAL_MAX)
+ panic("pmap_enter: too big");
+
+/*
+ * Get a pointer to the pte for this virtual address. We should always have
+ * a page table ready for us so if the page table is missing ....
+ */
+
+ pte = pmap_pte(pmap, va);
+ if (!pte) {
+ printf("pmap_enter: pde = %08x\n", (u_int) pmap_pde(pmap, va));
+ printf("pmap_enter: pte = %08x\n", (u_int) pmap_pte(pmap, va));
+ panic("Failure 01 in pmap_enter (V%08x P%08x)\n", (u_int) va, (u_int) pa);
+ }
+
+/* More debugging info */
+
+ if (pmap_debug_level >= 5) {
+ printf("pmap_enter: pte for V%08x = V%08x", (u_int) va, (u_int) pte);
+ printf(" (%08x)\n", *pte);
+ }
+
+/* Is the pte valid ? If so then this page is already mapped */
+
+ if (pmap_pte_v(pte))
+ {
+ vm_offset_t opa;
+
+/* Get the physical address of the current page mapped */
+
+ opa = pmap_pte_pa(pte);
+
+/* Are we mapping the same page ? */
+
+ if (opa == pa)
+ {
+ int flags;
+
+/* All we must be doing is changing the protection */
+
+ if (pmap_debug_level >= 0)
+ printf("Failure 02 in pmap_enter (V%08x P%08x)\n", (u_int) va, (u_int) pa);
+
+ pind = pmap_page_index(pa);
+ cacheable = (*pte) & PT_C;
+
+/* Has the wiring changed ? */
+
+ flags = pmap_modify_pv(pmap, va, pind, 0, 0) & PT_W;
+ if (flags && !wired)
+ --pmap->pm_stats.wired_count;
+ else if (!flags && wired)
+ ++pmap->pm_stats.wired_count;
+
+ }
+ else
+ {
+/* We are replacing the page with a new one. */
+
+ idcflush();
+
+ if (pmap_debug_level >= 0)
+ printf("Failure 03 in pmap_enter (V%08x P%08x P%08x)\n",
+ (int) va, (int) pa, (int) opa);
+
+/*
+ * If it is part of our managed memory then we must remove it from the PV list
+ */
+
+ if ((pind = pmap_page_index(opa)) != -1)
+ {
+/* pmap_attributes[pind] |= *pte & (PG_M | PG_U);*/
+/* pmap_remove_pv updates pmap_attribute */
+/* Adjust the wiring count if the page was wired */
+ if (pmap_remove_pv(pmap, va, pind) & PT_W)
+ --pmap->pm_stats.wired_count;
+
+ }
+
+/* Update the wiring stats for the new page */
+
+ if (wired)
+ ++pmap->pm_stats.wired_count;
+
+/*
+ * Enter on the PV list if part of our managed memory
+ */
+ if ((pind = pmap_page_index(pa)) != -1)
+ {
+ if (pmap_enter_pv(pmap, va, pind, 0))
+ cacheable = PT_C;
+ }
+ else
+ /*
+ * Assumption: if it is not part of our managed memory
+ * then it must be device memory which may be volatile.
+ * The video memory may be double mapped but should only be accesses from
+ * one address at a time. Will be double mapped by the X server and
+ * we must keep the cache on for performance.
+ */
+ if (pa >= videomemory.vidm_pbase
+ && pa < videomemory.vidm_pbase + videomemory.vidm_size)
+ cacheable = PT_C;
+ else
+ cacheable = 0;
+ }
+ }
+ else
+ {
+/* pte is not valid so we must be hooking in a new page */
+
+ idcflush();
+
+ ++pmap->pm_stats.resident_count;
+ if (wired)
+ ++pmap->pm_stats.wired_count;
+
+/*
+ * Enter on the PV list if part of our managed memory
+ */
+ if ((pind = pmap_page_index(pa)) != -1)
+ {
+ if (pmap_enter_pv(pmap, va, pind, 0))
+ cacheable = PT_C;
+ }
+ else
+ /*
+ * Assumption: if it is not part of our managed memory
+ * then it must be device memory which may be volatile.
+ */
+ {
+ /*
+ * Bit of a hack really as all doubly mapped addresses should be uncached
+ * as the cache works on virtual addresses not physical ones.
+ * However for the video memory this kill performance and the screen
+ * should be locked anyway so there should only be one process trying
+ * to write to it at once.
+ */
+
+ if (pa >= videomemory.vidm_pbase
+ && pa < videomemory.vidm_pbase + videomemory.vidm_size)
+ cacheable = PT_C;
+ else
+ cacheable = 0;
+ if (pmap_debug_level > 0)
+ printf("pmap_enter: non-managed memory mapping va=%08x pa=%08x\n",
+ (int) va, (int) pa);
+ }
+ }
+
+/* Construct the pte, giving the correct access */
+
+ npte = (pa & PG_FRAME) | cacheable | PT_B;
+
+if (va == 0 && (prot & VM_PROT_WRITE))
+ printf("va=0 prot=%d\n", prot);
+
+/*if (va < VM_MIN_ADDRESS)
+ printf("pmap_enter: va=%08x\n", (u_int)va);*/
+
+/* if (va >= VM_MIN_ADDRESS && va < VM_MAXUSER_ADDRESS && !wired)
+ npte |= L2_INVAL;
+ else*/
+ npte |= L2_SPAGE;
+
+/************ not sure about wired *************/
+
+ if (prot & VM_PROT_WRITE)
+ npte |= PT_AP(AP_W);
+
+ if (va >= VM_MIN_ADDRESS) {
+ if (va < VM_MAXUSER_ADDRESS)
+ npte |= PT_AP(AP_U);
+ else if (va < VM_MAX_ADDRESS) /* This must be a page table */
+ npte |= PT_AP(AP_W);
+ }
+
+ if (va >= VM_MIN_ADDRESS && va < VM_MAXUSER_ADDRESS && pind != -1) /* Inhibit write access for user pages */
+ *pte = (npte & ~PT_AP(AP_W));
+ else
+ *pte = npte;
+
+ if (*pte == 0)
+ {
+ panic("oopss: *pte = 0 in pmap_enter() npte=%08x\n", npte);
+ }
+
+ if (pind != -1)
+ {
+ int flags = 0;
+
+ if (wired) flags |= PT_W;
+ flags |= npte & (PT_Wr | PT_Us);
+/* if (flags & PT_Wr) flags |= PT_M;*/
+ #ifdef DIAGNOSTIC
+ if (pind > 0x00010000 || pind < 0)
+ {
+ printf("pind=%08x\n", pind);
+ }
+ #endif
+/* pmap_modify_pv(pmap, va, pind, 0xffffffff, flags);*/
+ pmap_modify_pv(pmap, va, pind, ~(PT_Wr | PT_Us | PT_W), flags);
+ }
+
+/*
+ * If we are mapping in a page to where the page tables are store then we
+ * must be mapping a page table. In this case we should also map the
+ * page table into the page directory
+ */
+
+ if (va >= 0xefc00000 && va < 0xf0000000)
+ {
+ if (pmap_debug_level >= 0)
+ {
+ printf("Page being mapped in the page table area\n");
+ printf("page P%08x will be installed in the L1 table as well\n",
+ (int) pa);
+ }
+ pa = pa & PG_FRAME;
+ pmap->pm_pdir[((va - 0xefc00000)>>10)+0] = L1_PTE(pa + 0x000);
+ pmap->pm_pdir[((va - 0xefc00000)>>10)+1] = L1_PTE(pa + 0x400);
+ pmap->pm_pdir[((va - 0xefc00000)>>10)+2] = L1_PTE(pa + 0x800);
+ pmap->pm_pdir[((va - 0xefc00000)>>10)+3] = L1_PTE(pa + 0xc00);
+ }
+
+/* Better flush the TLB ... */
+
+ tlbflush();
+
+#if PMAP_DEBUG > 5
+ printf("pmap_enter: pte = V%08x %08x\n", pte, *pte);
+#endif
+ }
+
+
+/*
+ * pmap_page_protect:
+ *
+ * Lower the permission for all mappings to a given page.
+ */
+
+void
+pmap_page_protect(phys, prot)
+ vm_offset_t phys;
+ vm_prot_t prot;
+{
+ if (pmap_debug_level >= 0)
+ printf("pmap_page_protect: pa=%08x, prot=%d\n", (int) phys, prot);
+
+ switch(prot) {
+ case VM_PROT_READ:
+ case VM_PROT_READ|VM_PROT_EXECUTE:
+ pmap_copy_on_write(phys);
+ break;
+
+ case VM_PROT_ALL:
+ break;
+
+ default:
+ pmap_remove_all(phys);
+ break;
+ }
+}
+
+
+/*
+ * Routine: pmap_change_wiring
+ * Function: Change the wiring attribute for a map/virtual-address
+ * pair.
+ * In/out conditions:
+ * The mapping must already exist in the pmap.
+ */
+
+void
+pmap_change_wiring(pmap, va, wired)
+ pmap_t pmap;
+ vm_offset_t va;
+ boolean_t wired;
+{
+ register pt_entry_t *pte;
+ vm_offset_t pa;
+ int pind;
+ int current;
+
+/* Get the pte */
+
+ pte = pmap_pte(pmap, va);
+ if (!pte)
+ return;
+
+/* Extract the physical address of the page */
+
+ pa = pmap_pte_pa(pte);
+
+/* Get the physical page index */
+
+ if ((pind = pmap_page_index(pa)) == -1)
+ return;
+
+/* Update the wired bit in the pv entry for this page. */
+
+ current = pmap_modify_pv(pmap, va, pind, PT_W, wired ? PT_W : 0) & PT_W;
+
+/* Update the statistics */
+
+ if (wired & !current)
+ pmap->pm_stats.wired_count++;
+ else if (!wired && current)
+ pmap->pm_stats.wired_count--;
+}
+
+
+/*
+ * pt_entry_t *pmap_pte(pmap_t pmap, vm_offset_t va)
+ *
+ * Return the pointer to a page table entry corresponding to the supplied
+ * virtual address.
+ *
+ * The page directory is first checked to make sure that a page table
+ * for the address in question exists and if it does a pointer to the
+ * entry is returned.
+ *
+ * The way this works is that that the kernel page tables are mapped
+ * into the memory map at 0xf3c00000 to 0xf3fffffff. This allows
+ * page tables to be located quickly.
+ */
+
+pt_entry_t *
+pmap_pte(pmap, va)
+ pmap_t pmap;
+ vm_offset_t va;
+{
+ pd_entry_t *pde;
+ pt_entry_t *ptp;
+ pt_entry_t *result;
+ int s;
+
+/* The pmap must be valid */
+
+ if (!pmap)
+ return(NULL);
+
+/* Return the address of the pte */
+
+#if PMAP_DEBUG > 10
+ printf("pmap_pte: pmap=V%08x va=V%08x pde = V%08x", pmap, va,
+ pmap_pde(pmap, va));
+ printf(" (%08x)\n", *(pmap_pde(pmap, va)));
+#endif
+
+ if (pmap_debug_level >= 10) {
+ printf("pmap_pte: pmap=V%08x va=V%08x pde = V%08x", (int) pmap,
+ (int) va, (int) pmap_pde(pmap, va));
+ printf(" (%08x)\n", *(pmap_pde(pmap, va)));
+ }
+
+/* Do we have a valid pde ? If not we don't have a page table */
+
+ if (!pmap_pde_v(pmap_pde(pmap, va))) {
+ if (pmap_debug_level >= 0)
+ printf("pmap_pte: failed - pde = %08x\n", (int) pmap_pde(pmap, va));
+ return(NULL);
+ }
+
+ if (pmap_debug_level >= 10)
+ printf("pmap pagetable = P%08x current = P%08x\n", (int) pmap->pm_pptpt,
+ (*((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+ + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2))+0xefc)) & PG_FRAME));
+
+ if (pmap == kernel_pmap || pmap->pm_pptpt
+ == (*((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+ + ((PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) & ~3)+0xefc)) & PG_FRAME)) {
+ ptp = (pt_entry_t *)PROCESS_PAGE_TBLS_BASE;
+ } else {
+ pde = (pd_entry_t *)CURRENT_PAGEDIR_BASE;
+ idcflush();
+
+/*printf("\x1b[33mpde=%08x kernel pmap=%08x pmap=%08x\x1b[0m\n", pde, kernel_pmap, pmap);*/
+ ptp = (pt_entry_t *)ALT_PAGE_TBLS_BASE;
+ pde[(ALT_PAGE_TBLS_BASE >> 20) + 0] = L1_PTE(pmap->pm_pptpt + 0x000);
+ pde[(ALT_PAGE_TBLS_BASE >> 20) + 1] = L1_PTE(pmap->pm_pptpt + 0x400);
+ pde[(ALT_PAGE_TBLS_BASE >> 20) + 2] = L1_PTE(pmap->pm_pptpt + 0x800);
+ pde[(ALT_PAGE_TBLS_BASE >> 20) + 3] = L1_PTE(pmap->pm_pptpt + 0xc00);
+
+ *((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + ((PROCESS_PAGE_TBLS_BASE
+ >> (PGSHIFT-2)) & ~3) + (ALT_PAGE_TBLS_BASE >> 20))) =
+ L2_PTE(pmap->pm_pptpt, AP_KRWUR);
+ tlbflush();
+ }
+ if (pmap_debug_level >= 10)
+ printf("page tables base = %08x\n", (int) ptp);
+ result = (pt_entry_t *)((char *)ptp + ((va >> (PGSHIFT-2)) & ~3));
+ return(result);
+}
+
+
+/*
+ * Routine: pmap_extract
+ * Function:
+ * Extract the physical page address associated
+ * with the given map/virtual_address pair.
+ */
+
+vm_offset_t
+pmap_extract(pmap, va)
+ pmap_t pmap;
+ vm_offset_t va;
+{
+ register pt_entry_t *pte;
+ register vm_offset_t pa;
+/*
+ printf("pmap_extract: pmap = %08x va = V%08x\n", pmap, va);
+*/
+
+/*
+ * Get the pte for this virtual address. If there is no pte then there is
+ * no page table etc.
+ */
+
+ pte = pmap_pte(pmap, va);
+ if (!pte)
+ return(0);
+
+/* Is the pte valid ? If not then no paged is actually mapped here */
+
+ if (!pmap_pte_v(pte))
+ return(0);
+
+/* Extract the physical address from the pte */
+
+ pa = pmap_pte_pa(pte);
+
+/* printf("pmap_extract: pa = P%08x\n", (pa | (va & ~PG_FRAME))); */
+
+ return(pa | (va & ~PG_FRAME));
+}
+
+
+#if 0 /* Macro in pmap.h */
+pt_entry_t *
+vtopte(va)
+ vm_offset_t va;
+{
+ return((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE
+ + (arm_byte_to_page(va) << 2)));
+}
+#endif
+
+#if 0 /* Macro in pmap.h */
+u_int
+vtophys(va)
+ vm_offset_t va;
+{
+ return((*vtopte(va) & PG_FRAME) | ((unsigned)(va) & ~PG_FRAME));
+}
+#endif
+
+
+/*
+ * Copy the range specified by src_addr/len from the source map to the
+ * range dst_addr/len in the destination map.
+ *
+ * This routine is only advisory and need not do anything.
+ */
+
+void
+pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
+ pmap_t dst_pmap;
+ pmap_t src_pmap;
+ vm_offset_t dst_addr;
+ vm_size_t len;
+ vm_offset_t src_addr;
+{
+ if (pmap_debug_level >= 0)
+ printf("pmap_copy(%x, %x, %x, %x, %x)\n",
+ (int) dst_pmap, (int) src_pmap, (int) dst_addr,
+ (int) len, (int) src_addr);
+}
+
+
+void
+pmap_dump_pvlist(phys, m)
+ vm_offset_t phys;
+ char *m;
+{
+ register struct pv_entry *pv;
+
+ if (!pv_table)
+ return;
+
+ printf("%s %08x:", m, (int) phys);
+ pv = &pv_table[pmap_page_index(phys)];
+ if (pv->pv_pmap == NULL) {
+ printf(" no mappings\n");
+ return;
+ }
+
+ for (; pv; pv = pv->pv_next)
+ printf(" pmap %08x va %08x flags %08x", (int) pv->pv_pmap,
+ (int) pv->pv_va, pv->pv_flags);
+
+ printf("\n");
+}
+
+
+void
+pmap_dump_pvs()
+{
+ register struct pv_entry *pv;
+ register int loop;
+
+ if (!pv_table)
+ return;
+
+ printf("pv dump\n");
+
+ for (loop = 0; loop < npages; ++loop) {
+ pv = &pv_table[loop];
+ if (pv->pv_pmap != NULL) {
+ printf("%4d : ", loop);
+ for (; pv; pv = pv->pv_next) {
+ printf(" pmap %08x va %08x flags %08x", (int) pv->pv_pmap,
+ (int) pv->pv_va, pv->pv_flags);
+ }
+ printf("\n");
+ }
+ }
+ }
+
+
+boolean_t
+pmap_testbit(pa, setbits)
+ vm_offset_t pa;
+ int setbits;
+{
+ register struct pv_entry *pv;
+/* register pt_entry_t *pte;*/
+ int pind;
+ int s;
+
+ if (pmap_debug_level >= 1)
+ printf("pmap_testbit: pa=%08x set=%08x\n", (int) pa, setbits);
+
+ if (pv_table == NULL || pmap_attributes == NULL)
+ return(FALSE);
+
+ if ((pind = pmap_page_index(pa)) == -1)
+ return(FALSE);
+
+ s = splimp();
+ pv = &pv_table[pind];
+
+/*
+ if (pmap_debug_level >= 0)
+ printf("pmap_attributes = %02x\n", pmap_attributes[pind]);
+*/
+
+/*
+ * Check saved info first
+ */
+
+ if (pmap_attributes[pind] & setbits) {
+ if (pmap_debug_level >= 0)
+ printf("pmap_attributes = %02x\n", pmap_attributes[pind]);
+
+ splx(s);
+ return(TRUE);
+ }
+
+/*
+ * Not found, check current mappings returning
+ * immediately if found.
+ */
+
+ if (pv->pv_pmap != NULL) {
+ for (; pv; pv = pv->pv_next) {
+/* pte = pmap_pte(pv->pv_pmap, pv->pv_va);*/
+
+/* The write bit is in the flags */
+
+ if ((pv->pv_flags & setbits) /*|| (*pte & (setbits & PT_Wr))*/) {
+ splx(s);
+ return(TRUE);
+ }
+ if ((setbits & PT_M) && pv->pv_va >= VM_MAXUSER_ADDRESS) {
+ splx(s);
+ return(TRUE);
+ }
+ if ((setbits & PT_H) && pv->pv_va >= VM_MAXUSER_ADDRESS) {
+ splx(s);
+ return(TRUE);
+ }
+ }
+ }
+
+ splx(s);
+ return(FALSE);
+}
+
+
+/*
+ * Modify pte bits for all ptes corresponding to the given physical address.
+ * We use `maskbits' rather than `clearbits' because we're always passing
+ * constants and the latter would require an extra inversion at run-time.
+ */
+
+void
+pmap_changebit(pa, setbits, maskbits)
+ vm_offset_t pa;
+ int setbits;
+ int maskbits;
+{
+ register struct pv_entry *pv;
+ register pt_entry_t *pte;
+ vm_offset_t va;
+ int pind;
+ int s;
+
+ if (pmap_debug_level >= 1)
+ printf("pmap_changebit: pa=%08x set=%08x mask=%08x\n",
+ (int) pa, setbits, maskbits);
+
+ if (pv_table == NULL || pmap_attributes == NULL)
+ return;
+
+ if ((pind = pmap_page_index(pa)) == -1)
+ return;
+
+ s = splimp();
+ pv = &pv_table[pind];
+
+/*
+ * Clear saved attributes (modify, reference)
+ */
+
+ if (pmap_debug_level >= 0 && pmap_attributes[pind])
+ printf("pmap_attributes = %02x\n", pmap_attributes[pind]);
+
+ if (~maskbits)
+ pmap_attributes[pind] &= maskbits;
+
+/*
+ * Loop over all current mappings setting/clearing as appropos
+ */
+
+ if (pv->pv_pmap != NULL) {
+ for (; pv; pv = pv->pv_next) {
+ va = pv->pv_va;
+
+/*
+ * XXX don't write protect pager mappings
+ */
+
+ if (maskbits == ~PT_Wr) {
+ extern vm_offset_t pager_sva, pager_eva;
+
+ if (va >= pager_sva && va < pager_eva)
+ continue;
+ }
+
+ pv->pv_flags = (pv->pv_flags & maskbits) | setbits;
+ pte = pmap_pte(pv->pv_pmap, va);
+ if ((maskbits & PT_Wr) == 0)
+ *pte = (*pte) & ~PT_AP(AP_W);
+ if (setbits & PT_Wr)
+ *pte = (*pte) | PT_AP(AP_W);
+/*
+ if ((maskbits & PT_H) == 0)
+ *pte = ((*pte) & ~L2_MASK) | L2_INVAL;
+*/
+ }
+ pmap_update();
+ }
+ splx(s);
+}
+
+
+void
+pmap_clear_modify(pa)
+ vm_offset_t pa;
+{
+ if (pmap_debug_level >= 0)
+ printf("pmap_clear_modify pa=%08x\n", (int) pa);
+ pmap_changebit(pa, 0, ~PT_M);
+}
+
+
+void
+pmap_clear_reference(pa)
+ vm_offset_t pa;
+{
+ if (pmap_debug_level >= 0)
+ printf("pmap_clear_reference pa=%08x\n", (int) pa);
+ pmap_changebit(pa, 0, ~PT_H);
+}
+
+
+void
+pmap_copy_on_write(pa)
+ vm_offset_t pa;
+{
+ if (pmap_debug_level >= 0)
+ printf("pmap_copy_on_write pa=%08x\n", (int) pa);
+ pmap_changebit(pa, 0, ~PT_Wr);
+}
+
+boolean_t
+pmap_is_modified(pa)
+ vm_offset_t pa;
+{
+ boolean_t result;
+
+ result = pmap_testbit(pa, PT_M);
+ if (pmap_debug_level >= 0)
+ printf("pmap_is_modified pa=%08x %08x\n", (int) pa, result);
+
+ return(result);
+}
+
+
+boolean_t
+pmap_is_referenced(pa)
+ vm_offset_t pa;
+{
+ boolean_t result;
+/* int pind;*/
+
+ result = pmap_testbit(pa, PT_H);
+ if (pmap_debug_level >= 0)
+ printf("pmap_is_referenced pa=%08x %08x\n", (int) pa, result);
+
+ return(result);
+}
+
+
+int
+pmap_modified_emulation(pmap, va)
+ pmap_t pmap;
+ vm_offset_t va;
+{
+ pt_entry_t *pte;
+ vm_offset_t pa;
+ int pind;
+ u_int flags;
+
+/* Get the pte */
+
+ pte = pmap_pte(pmap, va);
+ if (!pte)
+ return(0);
+
+/* Extract the physical address of the page */
+
+ pa = pmap_pte_pa(pte);
+
+/* Get the physical page index */
+
+ if ((pind = pmap_page_index(pa)) == -1)
+ return(0);
+
+/* Get the current flags for this page. */
+
+ flags = pmap_modify_pv(pmap, va, pind, 0, 0);
+ if (pmap_debug_level > 2)
+ printf("pmap_modified_emulation: flags = %08x\n", flags);
+
+/*
+ * Do the flags say this page is writable ? If not then it is a genuine
+ * write fault. If yes then the write fault is our fault as we did not
+ * reflect the write access in the PTE. Now we know a write has occurred
+ * we can correct this and also set the modified bit
+ */
+
+ if (!(flags & PT_Wr))
+ return(0);
+
+ if (pmap_debug_level > 0)
+ printf("pmap_modified_emulation: Got a hit va=%08x\n", (int) va);
+
+ if (pmap_debug_level > 0)
+ printf("pte = %08x (%08x)", (int) pte, *pte);
+ *pte = *pte | PT_AP(AP_W);
+ if (pmap_debug_level > 0)
+ printf("->(%08x)\n", *pte);
+
+ tlbflush();
+
+/* pmap_modify_pv(pmap, va, pind, PT_M, PT_M);*/
+
+ if (pmap_attributes)
+ pmap_attributes[pind] |= PT_M;
+
+/* panic("pmap_modified_emulation: Not yet completed\n");*/
+
+/* Return, indicating the problem has been dealt with */
+
+ return(1);
+}
+
+
+int
+pmap_handled_emulation(pmap, va)
+ pmap_t pmap;
+ vm_offset_t va;
+{
+ pt_entry_t *pte;
+ vm_offset_t pa;
+ int pind;
+/* u_int flags;*/
+
+ if (pmap_debug_level > 2)
+ printf("pmap_handled_emulation\n");
+
+/* return(0);*/
+
+/* Get the pte */
+
+ pte = pmap_pte(pmap, va);
+ if (!pte) {
+ if (pmap_debug_level > 2)
+ printf("no pte\n");
+ return(0);
+ }
+
+/* Check for a zero pte */
+
+ if (pmap_debug_level > 1)
+ printf("*pte=%08x\n", *pte);
+
+ if (*pte == 0)
+ return(0);
+
+ if (pmap_debug_level > 1)
+ printf("pmap_handled_emulation: non zero pte %08x\n", *pte);
+
+/* Have we marked a valid pte as invalid ? */
+
+ if (((*pte) & L2_MASK) != L2_INVAL)
+ return(0);
+
+ if (pmap_debug_level >=-1)
+ printf("Got an invalid pte\n");
+
+/* Extract the physical address of the page */
+
+ pa = pmap_pte_pa(pte);
+
+/* Get the physical page index */
+
+ if ((pind = pmap_page_index(pa)) == -1)
+ return(0);
+
+/*
+ * Ok we just enable the pte and mark the flags as handled
+ */
+
+ if (pmap_debug_level > 0)
+ printf("pmap_handled_emulation: Got a hit va=%08x\n", (int) va);
+
+ if (pmap_debug_level > 0)
+ printf("pte = %08x (%08x)", (int) pte, *pte);
+ *pte = ((*pte) & ~L2_MASK) | L2_SPAGE;
+ if (pmap_debug_level > 0)
+ printf("->(%08x)\n", *pte);
+
+ tlbflush();
+
+ if (pmap_attributes)
+ pmap_attributes[pind] |= PT_H;
+
+/* Return, indicating the problem has been dealt with */
+
+ return(1);
+}
+
+
+void
+pmap_pagedir_dump()
+{
+ int loop;
+
+ printf("PD pmap PD pmap\n");
+
+ for (loop = 0; loop < max_processes / 2; ++loop) {
+ printf("%2d %08x %2d %08x\n", loop,
+ (int) pagedirectories[loop], loop + max_processes / 2,
+ (int) pagedirectories[loop + max_processes / 2]);
+ }
+}
+
+
+int
+pmap_page_attributes(va)
+ vm_offset_t va;
+{
+ vm_offset_t pa;
+ int pind;
+
+/* Get the physical page */
+
+ pa = (vm_offset_t)vtopte(va);
+
+/* Get the physical page index */
+
+ if ((pind = pmap_page_index(pa)) == -1)
+ return(-1);
+
+ if (pmap_attributes)
+ return((int)pmap_attributes[pind]);
+
+ return(-1);
+}
+
+#if 0 /* Macro in pmap.h */
+vm_offset_t
+pmap_phys_address(ppn)
+ int ppn;
+{
+ return(arm_page_to_byte(ppn));
+}
+#endif
+
+
+void
+pmap_collect(pmap)
+ pmap_t pmap;
+{
+}
+
+/* End of pmap.c */
--- /dev/null
+/* $NetBSD: postmortem.c,v 1.4 1996/03/13 21:26:52 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * postmortem.c
+ *
+ * Postmortem routines
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+#include <machine/frame.h>
+#include <machine/katelib.h>
+
+#ifdef POSTMORTEM
+
+typedef struct {
+ vm_offset_t physical;
+ vm_offset_t virtual;
+} pv_addr_t;
+
+extern pv_addr_t irqstack;
+extern pv_addr_t undstack;
+extern pv_addr_t abtstack;
+extern struct proc *proc1;
+
+int usertraceback = 0;
+
+/* dumpb - dumps memory in bytes */
+
+void
+pm_dumpb(addr, count)
+ u_char *addr;
+ int count;
+{
+ u_int byte;
+ int loop;
+
+ for (; count > 0; count -= 16) {
+ printf("%08x: ", (int)addr);
+
+ for (loop = 0; loop < 16; ++loop) {
+ byte = addr[loop];
+ printf("%02x ", byte);
+ }
+
+ printf(" ");
+
+ for (loop = 0; loop < 16; ++loop) {
+ byte = addr[loop];
+ if (byte < 0x20)
+ printf("\x1b[31m%c\x1b[0m", byte + '@');
+ else if (byte == 0x7f)
+ printf("\x1b[31m?\x1b[0m");
+ else if (byte < 0x80)
+ printf("%c", byte);
+ else if (byte < 0xa0)
+ printf("\x1b[32m%c\x1b[0m", byte - '@');
+ else if (byte == 0xff)
+ printf("\x1b[32m?\x1b[0m");
+ else
+ printf("%c", byte & 0x7f);
+ }
+
+ printf("\r\n");
+ addr += 16;
+ }
+}
+
+
+/* dumpw - dumps memory in bytes */
+
+void
+pm_dumpw(addr, count)
+ u_char *addr;
+ int count;
+{
+ u_int byte;
+ int loop;
+
+ for (; count > 0; count -= 32) {
+ printf("%08x: ", (int)addr);
+
+ for (loop = 0; loop < 8; ++loop) {
+ byte = ((u_int *)addr)[loop];
+ printf("%08x ", byte);
+ }
+
+ printf(" ");
+
+ for (loop = 0; loop < 32; ++loop) {
+ byte = addr[loop];
+ if (byte < 0x20)
+ printf("\x1b[31m%c\x1b[0m", byte + '@');
+ else if (byte == 0x7f)
+ printf("\x1b[31m?\x1b[0m");
+ else if (byte < 0x80)
+ printf("%c", byte);
+ else if (byte < 0xa0)
+ printf("\x1b[32m%c\x1b[0m", byte - '@');
+ else if (byte == 0xff)
+ printf("\x1b[32m?\x1b[0m");
+ else
+ printf("%c", byte & 0x7f);
+ }
+
+ printf("\r\n");
+ addr += 32;
+ }
+}
+
+
+/* Dump a trap frame */
+
+void
+dumpframe(frame)
+ trapframe_t *frame;
+{
+ u_int s;
+
+ s = splhigh();
+ printf("frame address = %08x ", (u_int)frame);
+ printf("spsr =%08x\n", frame->tf_spsr);
+ printf("r0 =%08x r1 =%08x r2 =%08x r3 =%08x\n", frame->tf_r0, frame->tf_r1, frame->tf_r2, frame->tf_r3);
+ printf("r4 =%08x r5 =%08x r6 =%08x r7 =%08x\n", frame->tf_r4, frame->tf_r5, frame->tf_r6, frame->tf_r7);
+ printf("r8 =%08x r9 =%08x r10=%08x r11=%08x\n", frame->tf_r8, frame->tf_r9, frame->tf_r10, frame->tf_r11);
+ printf("r12=%08x r13=%08x r14=%08x r15=%08x\n", frame->tf_r12, frame->tf_usr_sp, frame->tf_usr_lr, frame->tf_pc);
+ printf("slr=%08x\n", frame->tf_svc_lr);
+
+ (void)splx(s);
+}
+
+
+/* Dump kstack information */
+/*
+void kstack_stuff(p)
+ struct proc *p;
+{
+ struct pmap *pmap;
+
+ if (p == 0) return;
+ if (p->p_addr == 0) return;
+ if (p->p_vmspace == 0) return;
+
+ printf("proc=%08x comm=%s pid=%d\n", (u_int)p, p->p_comm, p->p_pid);
+
+ pmap = &p->p_vmspace->vm_pmap;
+
+ printf("pmap=%08x\n", (u_int)pmap);
+
+ printf("p->p_addr=%08x pa=%08x,%d:%08x,%d\n",
+ (u_int)p->p_addr,
+ (u_int)pmap_extract(pmap, (vm_offset_t)p->p_addr),
+ pmap_page_index(pmap_extract(pmap, (vm_offset_t)p->p_addr)),
+ (u_int)pmap_extract(pmap, (vm_offset_t)p->p_addr + NBPG),
+ pmap_page_index(pmap_extract(pmap, (vm_offset_t)p->p_addr + NBPG)));
+}
+*/
+
+void
+check_stacks(p)
+ struct proc *p;
+{
+ u_char *ptr;
+ int loop;
+
+ if (p) {
+ ptr = ((u_char *)p->p_addr) + USPACE_UNDEF_STACK_BOTTOM;
+ for (loop = 0; loop < (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ;
+ printf("%d bytes of undefined stack fill pattern out of %d bytes\n", loop,
+ USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM);
+ ptr = ((u_char *)p->p_addr) + USPACE_SVC_STACK_BOTTOM;
+ for (loop = 0; loop < (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ;
+ printf("%d bytes of svc stack fill pattern out of %d bytes\n", loop,
+ USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM);
+ }
+}
+
+
+/* Perform a postmortem */
+
+void
+postmortem(frame)
+ trapframe_t *frame;
+{
+ u_int s;
+ struct proc *p = curproc;
+ int loop;
+ u_int addr;
+
+ s = splhigh();
+
+/* Check the stack for a known pattern */
+
+ check_stacks(p);
+
+#ifdef ROTTEN_INARDS
+ addr = traceback();
+
+ dumpframe(frame);
+
+ printf("curproc=%08x paddr=%08x pcb=%08x curpcb=%08x\n",
+ (u_int) curproc, (u_int) curproc->p_addr,
+ (u_int) &curproc->p_addr->u_pcb, (u_int) curpcb);
+ printf("CPSR=%08x ", GetCPSR());
+
+ printf("Process = %08x ", (u_int)curproc);
+ printf("pid = %d ", curproc->p_pid);
+ printf("comm = %s\n", curproc->p_comm);
+
+ pm_dumpw(irqstack.virtual + NBPG - 0x100, 0x100);
+ pm_dumpw(undstack.virtual + NBPG - 0x20, 0x20);
+ pm_dumpw(abtstack.virtual + NBPG - 0x20, 0x20);
+
+ printf("abt_sp=%08x irq_sp=%08x und_sp=%08x svc_sp=%08x\n",
+ get_stackptr(PSR_ABT32_MODE),
+ get_stackptr(PSR_IRQ32_MODE),
+ get_stackptr(PSR_UND32_MODE),
+ get_stackptr(PSR_SVC32_MODE));
+
+ if (curpcb)
+ printf("curpcb=%08x pcb_sp=%08x pcb_und_sp=%08x\n", curpcb, curpcb->pcb_sp, curpcb->pcb_und_sp);
+
+ printf("proc0=%08x paddr=%08x pcb=%08x\n", (u_int)&proc0,
+ (u_int)proc0.p_addr, (u_int) &proc0.p_addr->u_pcb);
+
+/*
+ kstack_stuff(&proc0);
+ kstack_stuff(curproc);
+*/
+#else
+ printf("Process = %08x ", (u_int)curproc);
+ printf("pid = %d ", curproc->p_pid);
+ printf("comm = %s\n", curproc->p_comm);
+ printf("CPSR=%08x ", GetCPSR());
+
+ printf("Traceback info\n");
+ addr = simpletraceback();
+ printf("Trapframe PC = %08x\n", frame->tf_pc);
+ printf("Trapframe SPSR = %08x\n", frame->tf_spsr);
+
+ if (usertraceback) {
+ printf("Attempting user trackback\n");
+ user_traceback(frame->tf_r11);
+ }
+
+#endif
+ if ((frame->tf_spsr & PSR_MODE) == PSR_IRQ32_MODE
+ && addr >= irqstack.virtual && addr < (irqstack.virtual + NBPG)) {
+ printf("Trap occurred in IRQ\n");
+ printf("IRQ Traceback info\n");
+ irqtraceback(addr, irqstack.virtual);
+ }
+ (void)splx(s);
+}
+
+
+void
+buried_alive(p)
+ struct proc *p;
+{
+ printf("Ok major screw up detected on kernel stack\n");
+ printf("Putting the process down to minimise further trashing\n");
+ printf("Process was %08x pid=%d comm=%s\n", (u_int) p, p->p_pid, p->p_comm);
+
+}
+#else
+void
+postmortem(frame)
+ trapframe_t *frame;
+{
+ printf("No postmortem support compiled in\n");
+}
+
+void
+buried_alive(p)
+ struct proc *p;
+{
+}
+#endif
+
+void
+traceback_sym(lr, pc)
+ u_int lr;
+ u_int pc;
+{
+#ifdef DDB
+ printf("fp->lr=%08x fp->pc=%08x\n", lr, pc);
+/* printf("fp->lr=");
+ db_printsym((db_addr_t)(lr), DB_STGY_ANY);
+ printf(" fp->pc=");
+ db_printsym((db_addr_t)(pc), DB_STGY_ANY);
+ printf("\n");*/
+#else
+ printf("fp->lr=%08x fp->pc=%08x\n", lr, pc);
+#endif
+}
+
+/* End of postmortem.c */
--- /dev/null
+/* $NetBSD: process_machdep.c,v 1.2 1996/03/27 22:42:26 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank Lancaster. All rights reserved.
+ * Copyright (c) 1995 Tools GmbH. All rights reserved.
+ * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1993 Jan-Simon Pendry
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From:
+ * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
+ */
+
+/*
+ * This file may seem a bit stylized, but that so that it's easier to port.
+ * Functions to be implemented here are:
+ *
+ * process_read_regs(proc, regs)
+ * Get the current user-visible register set from the process
+ * and copy it into the regs structure (<machine/reg.h>).
+ * The process is stopped at the time read_regs is called.
+ *
+ * process_write_regs(proc, regs)
+ * Update the current register set from the passed in regs
+ * structure. Take care to avoid clobbering special CPU
+ * registers or privileged bits in the PSL.
+ * The process is stopped at the time write_regs is called.
+ *
+ * process_sstep(proc, sstep)
+ * Arrange for the process to trap or not trap depending on sstep
+ * after executing a single instruction.
+ *
+ * process_set_pc(proc)
+ * Set the process's program counter.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/vnode.h>
+#include <sys/ptrace.h>
+
+#include <machine/reg.h>
+
+static inline struct trapframe *
+process_frame(p)
+ struct proc *p;
+{
+
+ return (p->p_md.md_regs);
+}
+
+static inline struct fp_state *
+process_fpframe(p)
+ struct proc *p;
+{
+
+ /* is this correct ? don't we need fpregs in the trapframe ?
+ or doesn't the kernel use fp ? */
+ return (&p->p_addr->u_pcb.pcb_fpstate);
+}
+
+int
+process_read_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
+ struct trapframe *tf = process_frame(p);
+
+ bcopy((caddr_t)&tf->tf_r0, (caddr_t)regs->r, sizeof(regs->r));
+ regs->r_sp = tf->tf_usr_sp;
+ regs->r_lr = tf->tf_usr_lr;
+ regs->r_pc = tf->tf_pc;
+ regs->r_cpsr = tf->tf_spsr;
+
+ return (0);
+}
+
+int
+process_read_fpregs(p, regs)
+ struct proc *p;
+ struct fpreg *regs;
+{
+ struct fp_state *statep;
+
+ /* NOTE: struct fpreg == struct fpstate */
+ statep = process_fpframe(p);
+ bcopy(statep, regs, sizeof(struct fpreg));
+ return (0);
+}
+
+int
+process_write_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
+ struct trapframe *tf = process_frame(p);
+
+ bcopy((caddr_t)regs->r, (caddr_t)&tf->tf_r0, sizeof(regs->r));
+ tf->tf_usr_sp = regs->r_sp;
+ tf->tf_usr_lr = regs->r_lr;
+ tf->tf_pc = regs->r_pc;
+ tf->tf_spsr &= ~PSR_FLAGS;
+ tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS;
+
+ return (0);
+}
+
+int
+process_write_fpregs(p, regs)
+ struct proc *p;
+ struct fpreg *regs;
+{
+ struct fp_state *statep;
+
+ /* NOTE: struct fpreg == struct fpstate */
+ statep = process_fpframe(p);
+ bcopy(regs, statep, sizeof(struct fpreg));
+ return (0);
+}
+
+int
+process_sstep(p, sstep)
+ struct proc *p;
+ int sstep;
+{
+ if (sstep)
+ /* this is going to be fun, I'll start off with kgdb_step ... */
+ return (EINVAL);
+ return (0);
+}
+
+int
+process_set_pc(p, addr)
+ struct proc *p;
+ caddr_t addr;
+{
+ struct trapframe *tf = process_frame(p);
+
+ tf->tf_pc = (int)addr;
+
+ return (0);
+}
--- /dev/null
+/* $NetBSD: scratch.S,v 1.2 1996/02/02 02:35:49 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * scratch.S
+ *
+ * Miscellaneous routines scratchpad routines
+ *
+ * Created : 02/04/95
+ * Last updated : 04/06/95
+ *
+ * $Id: scratch.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+#include "assym.h"
+
+lr .req r14
+pc .req r15
+
+.text
+
+ .global _ReadWordWithChecks
+
+/* Reads a word but traps failed faults
+ *
+ * r0 - address to read
+ * r1 - address to store result
+ */
+
+Lcurpcb:
+ .word _curpcb
+
+_ReadWordWithChecks:
+ ldr r2, Lcurpcb
+ ldr r2, [r2]
+ teq r2, #0x00000000
+ beq ReadWordPCBFault
+ add r3, pc, #ReadWordFault - . - 8
+ str r3, [r2, #PCB_ONFAULT]
+
+ ldr r0, [r0]
+ str r0, [r1]
+
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mov pc, lr
+
+ReadWordFault:
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mov r0, #0x00000001
+ mov pc, lr
+
+ReadWordPCBFault:
+ stmfd sp!, {lr}
+ mov r2, r0
+ add r0, pc, #ReadWordText1 - . - 8
+ mov r1, r2
+ bl _printf
+ mov r0, #0x00000001
+ ldmfd sp!, {lr}
+ mov pc, lr
+
+ReadWordText1:
+ .asciz "Alert ! PCB = %08x during ReadWordWithChecks addr=%08x\n"
+
+
+ .global new_fuword
+
+new_fuword:
+ ldr r2, Lcurpcb
+ ldr r2, [r2]
+ teq r2, #0x00000000
+ beq fusupcbfault
+ add r1, pc, #fusufault - . - 8
+ str r1, [r2, #PCB_ONFAULT]
+
+ ldr r0, [r0]
+
+ mov r1, #0x00000000
+ str r1, [r2, #PCB_ONFAULT]
+ mov pc, lr
+
+ .global new_fuswintr
+
+new_fuswintr:
+ ldr r2, Lcurpcb
+ ldr r2, [r2]
+ teq r2, #0x00000000
+ beq fusupcbfault
+ add r1, pc, #fusubailout - . - 8
+ str r1, [r2, #PCB_ONFAULT]
+
+ ldr r0, [r0]
+ bic r0, r0, #0xff000000
+ bic r0, r0, #0x00ff0000
+
+ mov r1, #0x00000000
+ str r1, [r2, #PCB_ONFAULT]
+ mov pc, lr
+
+ .global new_fusword
+
+new_fusword:
+ ldr r2, Lcurpcb
+ ldr r2, [r2]
+ teq r2, #0x00000000
+ beq fusupcbfault
+ add r1, pc, #fusufault - . - 8
+ str r1, [r2, #PCB_ONFAULT]
+
+ ldr r0, [r0]
+ bic r0, r0, #0xff000000
+ bic r0, r0, #0x00ff0000
+
+ mov r1, #0x00000000
+ str r1, [r2, #PCB_ONFAULT]
+ mov pc, lr
+
+ .global new_fubyte
+
+new_fubyte:
+ ldr r2, Lcurpcb
+ ldr r2, [r2]
+ teq r2, #0x00000000
+ beq fusupcbfault
+ add r1, pc, #fusufault - . - 8
+ str r1, [r2, #PCB_ONFAULT]
+
+ ldrb r0, [r0]
+
+ mov r1, #0x00000000
+ str r1, [r2, #PCB_ONFAULT]
+ mov pc, lr
+
+
+fusufault:
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mvn r0, #0x00000000
+ mov pc, lr
+
+ .global fusubailout
+
+fusubailout:
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mvn r0, #0x00000000
+ mov pc, lr
+
+fusuaddrfault:
+ mvn r0, #0x00000000
+ mov pc, lr
+
+fusupcbfault:
+ stmfd sp!, {lr}
+ mov r2, r0
+ add r0, pc, #ReadWordText1 - . - 8
+ mov r1, r2
+ bl _printf
+ mvn r0, #0x00000000
+ ldmfd sp!, {lr}
+ mov pc, lr
+
+ .global new_suword
+
+new_suword:
+ ldr r2, Lcurpcb
+ ldr r2, [r2]
+ teq r2, #0x00000000
+ beq fusupcbfault
+ add r3, pc, #fusufault - . - 8
+ str r3, [r2, #PCB_ONFAULT]
+
+ str r1, [r0]
+
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mov pc, lr
+
+ .global new_suswintr
+
+new_suswintr:
+ ldr r2, Lcurpcb
+ ldr r2, [r2]
+ teq r2, #0x00000000
+ beq fusupcbfault
+ add r3, pc, #fusubailout - . - 8
+ str r3, [r2, #PCB_ONFAULT]
+
+ strb r1, [r0, #0x0000]
+ mov r1, r1, lsr #8
+ strb r1, [r0, #0x0000]
+
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mov pc, lr
+
+ .global new_susword
+
+new_susword:
+ ldr r2, Lcurpcb
+ ldr r2, [r2]
+ teq r2, #0x00000000
+ beq fusupcbfault
+ add r3, pc, #fusufault - . - 8
+ str r3, [r2, #PCB_ONFAULT]
+
+ strb r1, [r0, #0x0000]
+ mov r1, r1, lsr #8
+ strb r1, [r0, #0x0000]
+
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mov pc, lr
+
+ .global new_subyte
+
+new_subyte:
+ ldr r2, Lcurpcb
+ ldr r2, [r2]
+ teq r2, #0x00000000
+ beq fusupcbfault
+ add r3, pc, #fusufault - . - 8
+ str r3, [r2, #PCB_ONFAULT]
+
+ strb r1, [r0]
+
+ mov r0, #0x00000000
+ str r0, [r2, #PCB_ONFAULT]
+ mov pc, lr
--- /dev/null
+/* $NetBSD: setcpsr.S,v 1.1 1996/01/31 23:16:54 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * setcpsr.S
+ *
+ * Miscellaneous routines to play with the CPSR register
+ *
+ * Eventually this routine can be inline assembly.
+ *
+ * Created : 12/09/94
+ * Last updated : 28/05/95
+ *
+ * Based of kate/display/setcpsr.s
+ *
+ * $Id: setcpsr.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+fp .req r11
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+
+ .global _SetCPSR
+
+/* Sets and clears bits in the CPSR register
+ *
+ * r0 - bic mask
+ * r1 - eor mask
+ */
+
+_SetCPSR:
+/* mov ip, sp
+ stmfd sp!, {fp, ip, lr, pc}
+ sub fp, ip, #4*/
+
+ mrs r3, cpsr_all /* Set the CPSR */
+ bic r2, r3, r0
+ eor r2, r2, r1
+ msr cpsr_all, r2
+
+ mov r0, r3 /* Return the old CPSR */
+
+/* ldmea fp, {fp, sp, pc}*/
+ mov pc, lr
+
+ .global _GetCPSR
+
+/* Gets the CPSR register
+ *
+ * Returns the CPSR in r0
+ */
+
+_GetCPSR:
+ mrs r0, cpsr_all /* Get the CPSR */
+
+ mov pc, lr
+
--- /dev/null
+/* $NetBSD: setstack.S,v 1.1 1996/01/31 23:16:59 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * setstack.S
+ *
+ * Miscellaneous routine to play with the stack pointer in different CPU modes
+ *
+ * Eventually this routine can be inline assembly.
+ *
+ * Created : 17/09/94
+ * Last updated : 15/10/94
+ *
+ * Based of kate/display/setstack.s
+ *
+ * $Id: setstack.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+#include <machine/cpu.h>
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+
+ .global _set_stackptr
+
+/* To set the stack pointer for a particular mode we must switch
+ * to that mode update the banked r13 and then switch back.
+ * This routine provides an easy way of doing this for any mode
+ *
+ * r0 = CPU mode
+ * r1 = stackptr
+ */
+
+_set_stackptr:
+ mrs r3, cpsr_all /* Switch to the appropriate mode */
+ bic r2, r3, #(PSR_MODE)
+ orr r2, r2, r0
+ msr cpsr_all, r2
+
+ mov sp, r1 /* Set the stack pointer */
+
+ msr cpsr_all, r3 /* Restore the old mode */
+
+ mov pc, lr /* Exit */
+
+ .global _get_stackptr
+
+/* To get the stack pointer for a particular mode we must switch
+ * to that mode copy the banked r13 and then switch back.
+ * This routine provides an easy way of doing this for any mode
+ *
+ * r0 = CPU mode
+ */
+
+_get_stackptr:
+ mrs r3, cpsr_all /* Switch to the appropriate mode */
+ bic r2, r3, #(PSR_MODE)
+ orr r2, r2, r0
+ msr cpsr_all, r2
+
+ mov r0, sp /* Set the stack pointer */
+
+ msr cpsr_all, r3 /* Restore the old mode */
+
+ mov pc, lr /* Exit */
+
+/* End of setstack.S */
--- /dev/null
+/* $NetBSD: spl.S,v 1.1 1996/03/08 18:03:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe.
+ * Copyright (c) Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * splasm.S
+ *
+ * spl routines
+ *
+ * Created : 01/03/96
+ *
+ * $Id: spl.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $
+ */
+
+#include "assym.h"
+#include <machine/psl.h>
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+ .text
+ .align 0
+
+Lcurrent_spl_level:
+ .word _current_spl_level
+
+Lspl_masks:
+ .word _spl_masks
+
+Lspl_mask:
+ .word _spl_mask
+
+ .global _raisespl
+_raisespl:
+ mov r3, r0 /* Save the new value */
+ ldr r1, Lcurrent_spl_level /* Get the current spl level */
+ ldr r0, [r1]
+ cmp r3, r0
+ movle pc, lr
+
+ str r3, [r1] /* Store the new spl mask */
+
+ ldr r2, Lspl_masks /* Get the spl mask */
+ ldr r2, [r2, r3, lsl #2]
+
+ ldr r1, Lspl_mask /* Store in the current spl mask */
+ str r2, [r1]
+
+ stmfd sp!, {r0, lr} /* Preserve registers */
+ bl _irq_setmasks /* Update the actual masks */
+ ldmfd sp!, {r0, pc} /* Exit */
+
+
+ .global _lowerspl
+_lowerspl:
+ mov r3, r0 /* Save the new value */
+ ldr r1, Lcurrent_spl_level /* Get the current spl level */
+ ldr r0, [r1]
+ cmp r3, r0
+ movge pc, lr
+
+ str r3, [r1] /* Store the new spl mask */
+
+ ldr r2, Lspl_masks /* Get the spl mask */
+ ldr r2, [r2, r3, lsl #2]
+
+ ldr r1, Lspl_mask /* Store in the current spl mask */
+ str r2, [r1]
+
+ stmfd sp!, {r0, lr} /* Preserve registers */
+ bl _irq_setmasks /* Update the actual masks */
+ ldmfd sp!, {r0, pc} /* Exit */
+
+
+ .global _splx
+_splx:
+ mov r3, r0 /* Save the new value */
+ ldr r1, Lcurrent_spl_level /* Get the current spl level */
+ ldr r0, [r1]
+ cmp r3, r0
+ moveq pc, lr
+
+ str r3, [r1] /* Store the new spl mask */
+
+ ldr r2, Lspl_masks /* Get the spl mask */
+ ldr r2, [r2, r3, lsl #2]
+
+ ldr r1, Lspl_mask /* Store in the current spl mask */
+ str r2, [r1]
+
+ stmfd sp!, {r0, lr} /* Preserve registers */
+ bl _irq_setmasks /* Update the actual masks */
+ ldmfd sp!, {r0, pc} /* Exit */
+
--- /dev/null
+/* $NetBSD: strstr.c,v 1.2 1996/03/27 22:42:28 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: strstr.c,v 1.4 1995/06/15 00:08:43 jtc Exp
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/*
+ * Find the first occurrence of find in s.
+ */
+
+char *
+strstr(s, find)
+ register const char *s, *find;
+{
+ register char c, sc;
+ register size_t len;
+
+ if ((c = *find++) != 0) {
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return (NULL);
+ } while (sc != c);
+ } while (strncmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+
+/* End of strstr.c */
--- /dev/null
+#include <sys/param.h>
+
+#ifndef ULONG_MAX
+#define ULONG_MAX ((u_long)(~0L)) /* 0xFFFFFFFF */
+#endif
+
+u_long
+strtoul(s, ptr, base)
+ const char *s;
+ char **ptr;
+ int base;
+{
+ u_long total = 0;
+ u_int digit;
+ const char *start=s;
+ int did_conversion=0;
+ int overflow = 0;
+ int negate = 0;
+ u_long maxdiv, maxrem;
+
+ if (s == NULL) {
+ if (!ptr)
+ *ptr = (char *)start;
+ return 0L;
+ }
+
+ while (*s == ' ')
+ s++;
+ if (*s == '+')
+ s++;
+ else if (*s == '-')
+ s++, negate = 1;
+ if (base==0 || base==16) { /* the 'base==16' is for handling 0x */
+ int tmp;
+
+ /*
+ * try to infer base from the string
+ */
+ if (*s != '0')
+ tmp = 10; /* doesn't start with 0 - assume decimal */
+ else if (s[1] == 'X' || s[1] == 'x')
+ tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */
+ else
+ tmp = 8; /* starts with 0 - hence octal */
+ if (base==0)
+ base = (int)tmp;
+ }
+
+ maxdiv = ULONG_MAX / base;
+ maxrem = ULONG_MAX % base;
+
+ while ((digit = *s) != '\0') {
+ if (digit >= '0' && digit < ('0'+base))
+ digit -= '0';
+ else
+ if (base > 10) {
+ if (digit >= 'a' && digit < ('a'+(base-10)))
+ digit = digit - 'a' + 10;
+ else if (digit >= 'A' && digit < ('A'+(base-10)))
+ digit = digit - 'A' + 10;
+ else
+ break;
+ }
+ else
+ break;
+ did_conversion = 1;
+ if (total > maxdiv
+ || (total == maxdiv && digit > maxrem))
+ overflow = 1;
+ total = (total * base) + digit;
+ s++;
+ }
+ if (overflow) {
+ if (ptr != NULL)
+ *ptr = (char *)s;
+ return (ULONG_MAX);
+ }
+ if (ptr != NULL)
+ *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start);
+ return negate ? -total : total;
+}
+
+/* End of strtoul.c */
--- /dev/null
+/* $NetBSD: stubs.c,v 1.4 1996/03/08 18:41:52 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * stubs.c
+ *
+ * Routines that are temporary or do not have a home yet.
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/proc.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/vnode.h>
+#include <sys/conf.h>
+#include <sys/reboot.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <dev/ramdisk.h>
+#include <machine/param.h>
+#include <machine/vmparam.h>
+#include <machine/cpu.h>
+#include <machine/irqhandler.h>
+#include <machine/vidc.h>
+#include <machine/bootconfig.h>
+#include <machine/katelib.h>
+#include <machine/psl.h>
+
+#include "fdc.h"
+#include "rd.h"
+
+#define VM_MAXKERN_ADDRESS 0xf3000000
+
+extern int ffs_mountroot();
+extern int cd9660_mountroot();
+int do_mountroot();
+int (*mountroot)() = do_mountroot;
+
+extern u_int soft_interrupts;
+
+extern int msgbufmapped;
+extern dev_t rootdev;
+extern dev_t dumpdev;
+#ifdef RAMDISK_HOOKS
+extern struct rd_conf *bootrd;
+#endif
+
+extern BootConfig bootconfig;
+extern videomemory_t videomemory;
+
+int
+do_mountroot()
+{
+ struct buf *bp;
+ int loop;
+ int s;
+ int type;
+ int floppysize;
+ int error;
+
+#if (NFDC > 0 && NRD > 0 && defined(RAMDISK_HOOKS))
+
+/*
+ * Ok ideally the ramdisc would be loaded via the rd_open_hook() but since
+ * we are loading the ramdisc from floppy we only want to load it during
+ * the boot and not at any other time.
+ */
+
+/*
+ * Ok bit of bodging here. The ramdisc minor is the unit number. However if booting
+ * from the ramdisc we limit to always booting off minor 0 i.e. rd0 The ramdisc
+ * device passed as the root device is only used to identify the ramdisc major. The
+ * minor, instead of indicating the ramdisc unit is used to indicate the floppy
+ * minor that should be used for loading the boot ramdisc which is unit 0.
+ */
+
+ if (major(rootdev) == 18 && bootrd) {
+ if (load_ramdisc_from_floppy(bootrd, makedev(17, minor(rootdev))) != 0)
+ panic("Failed to load ramdisc\n");
+ boothowto |= RB_SINGLE;
+ rootdev = makedev(major(rootdev), 0);
+ }
+#endif
+
+/*
+ * Slight bug with mounting CD's sometimes. The first mount may fail
+ * so we will try again. This only happens with the temporary ATAPI
+ * CDROM driver we are using
+ */
+
+#ifdef CD9660
+ if (major(rootdev) == 20 || major(rootdev) == 26) {
+ error = cd9660_mountroot();
+ if (error)
+ error = cd9660_mountroot();
+ }
+ else {
+#endif
+#ifdef FFS
+ error = ffs_mountroot();
+#else
+#error FFS not configured
+#endif
+#ifdef CD9660
+ if (error)
+ error = cd9660_mountroot();
+ }
+#endif
+ return(error);
+}
+
+
+/*
+ * All the copyin and copyout and copystr functions need to be recoded in assembly
+ * at some point. The guts of the functions now use an assembly bcopy routine but
+ * it would be nice to code them completely in assembly. The main reason they have
+ * not been is purely because it is easier to add debugging code to check the
+ * parameters in C.
+ */
+
+#if 0
+int
+copystr(from, to, maxlen, lencopied)
+ void *from;
+ void *to;
+ size_t maxlen;
+ size_t *lencopied;
+{
+ int byte = 0;
+ int len;
+
+ len = 0;
+
+ do {
+ if (len == maxlen)
+ break;
+ byte = *((caddr_t)from)++;
+ *((caddr_t)to)++ = byte;
+ ++len;
+ } while (byte != 0);
+
+ if (lencopied)
+ *lencopied = len;
+
+ if (byte == 0)
+ return(0);
+ else
+ return(ENAMETOOLONG);
+}
+
+
+#else
+int
+copystr(from, to, maxlen, lencopied)
+ void *from;
+ void *to;
+ size_t maxlen;
+ size_t *lencopied;
+
+{
+ return(copystrinout(from, to, maxlen, lencopied));
+}
+#endif
+
+int copystrinout __P((void */*from*/, void */*to*/, size_t /*maxlen*/, size_t */*lencopied*/));
+
+
+int
+copyinstr(udaddr, kaddr, len, done)
+ void *udaddr;
+ void *kaddr;
+ u_int len;
+ u_int *done;
+{
+ if (udaddr < (void *)VM_MIN_ADDRESS
+ || udaddr >= (void *)VM_MAXUSER_ADDRESS) {
+ printf("akt: copyinstr: udaddr=%08x kaddr=%08x\n",
+ (u_int)udaddr, (u_int)kaddr);
+ return(EFAULT);
+ }
+ if (kaddr < (void *)VM_MAXUSER_ADDRESS
+ || kaddr >= (void *)VM_MAXKERN_ADDRESS) {
+ printf("akt: copyinstr: udaddr=%08x kaddr=%08x\n",
+ (u_int)udaddr, (u_int)kaddr);
+ return(EFAULT);
+ }
+ return(copystrinout(udaddr, kaddr, len, done));
+}
+
+int
+copyoutstr(kaddr, udaddr, len, done)
+ void *kaddr;
+ void *udaddr;
+ u_int len;
+ u_int *done;
+{
+ if (udaddr < (void *)VM_MIN_ADDRESS
+ || udaddr >= (void*)VM_MAXUSER_ADDRESS) {
+ printf("akt: copyoutstr: udaddr=%08x kaddr=%08x\n",
+ (u_int)udaddr, (u_int)kaddr);
+ return(EFAULT);
+ }
+ if (kaddr < (void *)VM_MAXUSER_ADDRESS
+ || kaddr >= (void *)VM_MAXKERN_ADDRESS) {
+ printf("akt: copyoutstr: udaddr=%08x kaddr=%08x\n",
+ (u_int)udaddr, (u_int)kaddr);
+ return(EFAULT);
+ }
+ return(copystrinout(kaddr, udaddr, len, done));
+}
+
+int bcopyinout __P((void *, void *, u_int));
+
+int
+copyin(udaddr, kaddr, len)
+ void *udaddr;
+ void *kaddr;
+ u_int len;
+{
+ int error;
+
+ if (udaddr < (void *)VM_MIN_ADDRESS
+ || udaddr >= (void *)VM_MAXUSER_ADDRESS) {
+ printf("akt: copyin: udaddr=%08x kaddr=%08x\n",
+ (u_int)udaddr, (u_int)kaddr);
+ return(EFAULT);
+ }
+ if (kaddr < (void *)VM_MAXUSER_ADDRESS
+ || kaddr >= (void *)VM_MAXKERN_ADDRESS) {
+ printf("akt: copyin: udaddr=%08x kaddr=%08x\n",
+ (u_int)udaddr, (u_int)kaddr);
+ return(EFAULT);
+ }
+ error = bcopyinout(udaddr, kaddr, len);
+ if (error)
+ printf("akt: copyin(%08x,%08x,%08x) failed\n",
+ (u_int)udaddr, (u_int)kaddr, len);
+ return(error);
+}
+
+int
+copyout(kaddr, udaddr, len)
+ void *kaddr;
+ void *udaddr;
+ u_int len;
+{
+ int error;
+
+ if (udaddr < (void*)VM_MIN_ADDRESS
+ || udaddr >= (void*)VM_MAXUSER_ADDRESS) {
+ printf("akt: copyout: udaddr=%08x kaddr=%08x\n",
+ (u_int)udaddr, (u_int)kaddr);
+ return(EFAULT);
+ }
+ if (kaddr < (void *)VM_MAXUSER_ADDRESS
+ || kaddr >= (void *)VM_MAXKERN_ADDRESS) {
+ printf("akt: copyout: udaddr=%08x kaddr=%08x\n",
+ (u_int)udaddr, (u_int)kaddr);
+ return(EFAULT);
+ }
+ error = bcopyinout(kaddr, udaddr, len);
+ if (error) {
+ printf("akt: copyout(%08x,%08x,%08x) failed\n",
+ (u_int)kaddr, (u_int)udaddr, len);
+ traceback();
+ }
+ return(error);
+}
+
+void
+setsoftnet()
+{
+ soft_interrupts |= IRQMASK_SOFTNET;
+}
+
+int astpending;
+
+void
+setsoftast()
+{
+ astpending = 1;
+}
+
+extern int want_resched;
+
+void
+need_resched(void)
+{
+ want_resched = 1;
+ setsoftast();
+}
+
+
+struct queue {
+ struct queue *q_next, *q_prev;
+};
+
+/*
+ * insert an element into a queue
+ */
+
+void
+_insque(v1, v2)
+ void *v1;
+ void *v2;
+{
+ register struct queue *elem = v1, *head = v2;
+ register struct queue *next;
+
+ next = head->q_next;
+ elem->q_next = next;
+ head->q_next = elem;
+ elem->q_prev = head;
+ next->q_prev = elem;
+}
+
+/*
+ * remove an element from a queue
+ */
+
+void
+_remque(v)
+ void *v;
+{
+ register struct queue *elem = v;
+ register struct queue *next, *prev;
+
+ next = elem->q_next;
+ prev = elem->q_prev;
+ next->q_prev = prev;
+ prev->q_next = next;
+ elem->q_prev = 0;
+}
+
+
+
+/*
+ * These variables are needed by /sbin/savecore
+ */
+u_long dumpmag = 0x8fca0101; /* magic number */
+int dumpsize = 0; /* pages */
+long dumplo = 0; /* blocks */
+
+/*
+ * This is called by configure to set dumplo and dumpsize.
+ * Dumps always skip the first CLBYTES of disk space
+ * in case there might be a disk label stored there.
+ * If there is extra space, put dump at the end to
+ * reduce the chance that swapping trashes it.
+ */
+
+void
+dumpconf()
+{
+ int nblks; /* size of dump area */
+ int maj;
+
+ if (dumpdev == NODEV)
+ return;
+ maj = major(dumpdev);
+ if (maj < 0 || maj >= nblkdev)
+ panic("dumpconf: bad dumpdev=0x%x", dumpdev);
+ if (bdevsw[maj].d_psize == NULL)
+ return;
+ nblks = (*bdevsw[maj].d_psize)(dumpdev);
+ if (nblks <= ctod(1))
+ return;
+
+ dumpsize = physmem;
+
+ /* Always skip the first CLBYTES, in case there is a label there. */
+ if (dumplo < ctod(1))
+ dumplo = ctod(1);
+
+ /* Put dump at end of partition, and make it fit. */
+ if (dumpsize > dtoc(nblks - dumplo))
+ dumpsize = dtoc(nblks - dumplo);
+ if (dumplo < nblks - ctod(dumpsize))
+ dumplo = nblks - ctod(dumpsize);
+}
+
+
+extern pagehook_t page_hook0;
+
+/*
+ * Doadump comes here after turning off memory management and
+ * getting on the dump stack, either when called above, or by
+ * the auto-restart code.
+ */
+
+void
+dumpsys()
+{
+ daddr_t blkno;
+ int psize;
+ int error;
+ int addr;
+ int block;
+ vm_offset_t dumpspace;
+
+ msgbufmapped = 0;
+ if (dumpdev == NODEV)
+ return;
+ if (dumpsize == 0) {
+ dumpconf();
+ if (dumpsize == 0)
+ return;
+ }
+ printf("\ndumping to dev %x, offset %d\n", (u_int)dumpdev,
+ (u_int)dumplo);
+
+ blkno = dumplo;
+ dumpspace = page_hook0.va;
+
+ psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
+ printf("dump ");
+ if (psize == -1) {
+ printf("area unavailable\n");
+ return;
+ }
+
+ error = 0;
+ for (block = 0; block < bootconfig.dramblocks && error == 0; ++block) {
+ for (addr = bootconfig.dram[block].address;
+ addr < bootconfig.dram[block].address
+ + bootconfig.dram[block].pages * NBPG; addr += NBPG) {
+ pmap_map(dumpspace, addr, addr + NBPG, VM_PROT_READ);
+ error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev, blkno, (caddr_t) dumpspace, NBPG);
+ if (error) break;
+ blkno += btodb(NBPG);
+ }
+ }
+
+ if (error == 0 && videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) {
+ for (addr = videomemory.vidm_pbase; addr < videomemory.vidm_pbase
+ + videomemory.vidm_size; addr += NBPG) {
+ pmap_map(dumpspace, addr, addr + NBPG, VM_PROT_READ);
+ error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev, blkno, (caddr_t) dumpspace, NBPG);
+ if (error) break;
+ blkno += btodb(NBPG);
+ }
+ }
+
+ switch (error) {
+ case ENXIO:
+ printf("device bad\n");
+ break;
+
+ case EFAULT:
+ printf("device not ready\n");
+ break;
+
+ case EINVAL:
+ printf("area improper\n");
+ break;
+
+ case EIO:
+ printf("i/o error\n");
+ break;
+
+ case EINTR:
+ printf("aborted from console\n");
+ break;
+
+ default:
+ printf("succeeded\n");
+ break;
+ }
+ printf("\n\n");
+ delay(1000000);
+}
+
+/*
+ * Dummy function is case no audio device has been configured
+ * Need to fix the code that uses this function (console) to check NBEEP.
+ */
+
+#include "beep.h"
+#if NBEEP == 0
+void
+beep_generate()
+{
+}
+#endif
+
+
+#if 0
+/* Debugging functions to dump the buffers linked to a vnode */
+
+void
+dumpvndbuf(vp)
+ register struct vnode *vp;
+{
+ register struct buf *bp, *nbp;
+ int s;
+
+ s = splbio();
+ for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
+ nbp = bp->b_vnbufs.le_next;
+
+ printf("buf=%08x\n", bp);
+ printf("flags=%08x proc=%08x bufsize=%08x dev=%04x\n", bp->b_flags, bp->b_proc, bp->b_bufsize, bp->b_dev);
+ printf("vp=%08x resid=%08x count=%08x addr=%08x\n", bp->b_vp, bp->b_resid, bp->b_bcount, bp->b_un.b_addr);
+ }
+ (void)splx(s);
+}
+
+
+void
+dumpvncbuf(vp)
+ register struct vnode *vp;
+{
+ register struct buf *bp, *nbp;
+ int s;
+
+ s = splbio();
+ for (bp = vp->v_cleanblkhd.lh_first; bp; bp = nbp) {
+ nbp = bp->b_vnbufs.le_next;
+
+ printf("buf=%08x\n", bp);
+ printf("flags=%08x proc=%08x bufsize=%08x dev=%04x\n", bp->b_flags, bp->b_proc, bp->b_bufsize, bp->b_dev);
+ printf("vp=%08x resid=%08x count=%08x addr=%08x\n", bp->b_vp, bp->b_resid, bp->b_bcount, bp->b_un.b_addr);
+ }
+ (void)splx(s);
+}
+#endif
+
+
+extern u_int spl_mask;
+
+int current_spl_level = SPL_0;
+u_int spl_masks[8];
+
+int safepri = SPL_0;
+
+void
+set_spl_masks()
+{
+ spl_masks[SPL_0] = 0xffffffff;
+ spl_masks[SPL_SOFT] = ~IRQMASK_SOFTNET;
+ spl_masks[SPL_BIO] = irqmasks[IPL_BIO];
+ spl_masks[SPL_NET] = irqmasks[IPL_NET];
+ spl_masks[SPL_TTY] = irqmasks[IPL_TTY];
+ spl_masks[SPL_CLOCK] = irqmasks[IPL_CLOCK];
+ spl_masks[SPL_IMP] = irqmasks[IPL_IMP];
+ spl_masks[SPL_HIGH] = 0x00000000;
+}
+
+void
+dump_spl_masks()
+{
+ printf("spl0=%08x splsoft=%08x splbio=%08x splnet=%08x\n",
+ spl_masks[SPL_0], spl_masks[SPL_SOFT], spl_masks[SPL_BIO], spl_masks[SPL_NET]);
+ printf("spltty=%08x splclock=%08x splimp=%08x splhigh=%08x\n",
+ spl_masks[SPL_TTY], spl_masks[SPL_CLOCK], spl_masks[SPL_IMP], spl_masks[SPL_HIGH]);
+}
+
+/*
+ * Ok things are broken here. If we lower the spl level to SPL_SOFT
+ * then, for the most things work. However wd interrupts start to get
+ * lost ... i.e. you either get wdc interrupt lost messages or
+ * wdc timeout messages.
+ * The fault is the CLKF_FRAME macro uses in kern_clock.c. This
+ * currently always returns 1 thus splsoftclock() is always
+ * called before calling softclock().
+ *
+ * This is about to be fixed
+ */
+
+int
+splsoftclock()
+{
+/* return(lowerspl(SPL_SOFT));*/
+ return(current_spl_level);
+}
+
+/* End of stubs.c */
--- /dev/null
+/* $NetBSD: swapgeneric.c,v 1.2 1996/03/27 22:42:30 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * swapgeneric.h
+ *
+ * Miscellaneous swap stuff
+ *
+ * Created : 10/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+
+dev_t rootdev = NODEV;
+dev_t swapdev = NODEV;
+dev_t argdev = NODEV;
+dev_t dumpdev = NODEV;
+int nswap;
+struct swdevt swdevt[] = {
+ { NODEV, 0, 0 },
+ { NODEV, 0, 0 },
+ { NODEV, 0, 0 },
+ { NODEV, 0, 0 },
+};
+
+/* End of swapgeneric.c */
--- /dev/null
+/* $NetBSD: sys_machdep.c,v 1.2 1996/03/27 22:42:31 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * sys_machdep.c
+ *
+ * Machine dependant syscalls
+ *
+ * Created : 10/01/96
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/buf.h>
+#include <sys/exec.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/sysctl.h>
+#include <sys/syscallargs.h>
+
+int
+sys_sysarch(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_sysarch_args /* {
+ syscallarg(int) op;
+ syscallarg(char *) parms;
+ } */ *uap = v;
+
+ printf("sys_sysarch: Currently stoned - Cannot support the operation (%d)\n",
+ SCARG(uap, op));
+
+ return(EINVAL);
+}
+
+/* End of sys_machdep.c */
--- /dev/null
+/* $NetBSD: syscall.c,v 1.5 1996/03/13 21:21:00 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * syscall.c
+ *
+ * High level syscall handling
+ *
+ * Created : 09/11/94
+ */
+
+#include <sys/param.h>
+#include <sys/filedesc.h>
+#include <sys/errno.h>
+#include <sys/exec.h>
+#include <sys/kernel.h>
+#include <sys/mount.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/signalvar.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/protosw.h>
+#include <sys/reboot.h>
+#include <sys/user.h>
+#include <sys/syscall.h>
+#include <sys/syscallargs.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/katelib.h>
+#include <machine/undefined.h>
+
+#include "hydrabus.h"
+
+/*
+ * CONTINUE_AFTER_SYSCALL_BUG is used to determine whether the kernel
+ * should continue running following a swi instruction in SVC mode.
+ * This was used for debugging.
+ */
+
+#define CONTINUE_AFTER_SYSCALL_BUG
+
+extern int pmap_debug_level;
+extern u_int kmodule_size;
+extern u_int kmodule_base;
+u_int arm700bugcount = 0;
+extern int vnodeconsolebug;
+extern int usertraceback;
+
+#if NHYDRABUS > 0
+typedef struct {
+ vm_offset_t physical;
+ vm_offset_t virtual;
+} pv_addr_t;
+
+extern pv_addr_t hydrascratch;
+#endif
+
+void postmortem __P((trapframe_t *));
+void fpe_dump_prof __P(());
+
+#define SYSCALL_SPECIAL_RETURN \
+ userret(p, frame->tf_pc, sticks); \
+ validate_trapframe(frame, 4); \
+ return;
+
+/*
+ * syscall(frame):
+ *
+ * System call request from POSIX system call gate interface to kernel.
+ */
+
+void
+syscall(frame, code)
+ trapframe_t *frame;
+ int code;
+{
+ caddr_t params;
+ struct sysent *callp;
+ struct proc *p;
+ int error, opc;
+ u_int argsize;
+ int args[8], rval[2];
+ int nsys;
+ u_quad_t sticks;
+ int regparams;
+
+ cnt.v_syscall++;
+
+#ifdef DIAGNOSTIC
+ if ((frame->tf_spsr & PSR_MODE) != PSR_USR32_MODE) {
+ u_int s;
+
+ s = splhigh();
+ printf("swi code = %08x %d\n", code, code);
+ postmortem(frame);
+
+ printf("nkt: syscall in kernel mode !\n");
+#ifdef CONTINUE_AFTER_SYSCALL_BUG
+ printf("The system should now be considered very unstable :-(\n");
+ sigexit(curproc, SIGILL);
+
+/* Not reached */
+
+ (void)splx(s);
+ userret(curproc, frame->tf_pc, curproc->p_sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 4);
+#endif
+ return;
+#else
+ panic("syscall in kernel mode !\n");
+#endif
+ }
+#endif
+
+/*
+ * ARM700/ARM710 match sticks and sellotape job ...
+ *
+ * I know this affects GPS/VLSI ARM700/ARM710.
+ *
+ * Not heard anything from ARM since I told them about this ...
+ * On occasion data aborts are mishandled and end up calling
+ * the swi vector.
+ */
+
+ if ((ReadWord(frame->tf_pc - 4) & 0x0f000000) != 0x0f000000) {
+ frame->tf_pc -= 4;
+ ++arm700bugcount;
+
+ userret(curproc, frame->tf_pc, curproc->p_sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 4);
+#endif
+ return;
+ }
+
+#ifdef DIAGNOSTIC
+ if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) {
+ splhigh();
+
+ printf("swi code = %08x %d\n", code, code);
+ postmortem(frame);
+ panic("syscall in non SVC mode !");
+ }
+#endif
+
+/*
+ * Enable interrupts if they were enable before the exception.
+ * Sinces all syscalls *should* come from user mode it will always
+ * be safe to enable them, but check anyway.
+ */
+
+#ifndef BLOCK_IRQS
+ if (!(frame->tf_spsr & I32_bit))
+ enable_interrupts(I32_bit);
+#endif
+
+ p = curproc;
+ sticks = p->p_sticks;
+ p->p_md.md_regs = frame;
+ opc = frame->tf_pc;
+ params = (caddr_t)&frame->tf_r0;
+ regparams = 4;
+
+ if (pmap_debug_level >= -1)
+ printf("\x1b[31mSYSCALL\x1b[0m: code=%08x lr=%08x pid=%d\n",
+ code, frame->tf_pc, p->p_pid);
+
+ nsys = p->p_emul->e_nsysent;
+ callp = p->p_emul->e_sysent;
+
+ switch (code) {
+ case 0x1002:
+ printf((char *)frame->tf_r0, frame->tf_r1, frame->tf_r2, frame->tf_r3);
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case 0x1003:
+ printf("%s", (char *)frame->tf_r0);
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+/* case 0x1004:
+ if (frame->tf_r0 != 0)
+ panic((char *)frame->tf_r0, frame->tf_r1, frame->tf_r2,
+ frame->tf_r3);
+ panic("SYSCALL 0x1004 panic\n");
+ break;*/
+
+/* case 0x1007:
+ pmap_debug(frame->tf_r0);
+ SYSCALL_SPECIAL_RETURN;
+ break;*/
+
+ case 0x1008:
+ switch (frame->tf_r0) {
+ case 0 :
+ debug_show_all_procs(frame->tf_r1, frame->tf_r2);
+ break;
+#ifdef FPE
+ case 4 :
+ fpe_dump_prof();
+ break;
+#endif
+ case 5 :
+ pmap_dump_pvs();
+ break;
+ case 6:
+ WriteWord(frame->tf_r1, frame->tf_r2);
+ break;
+ case 7:
+ frame->tf_r0 = ReadWord(frame->tf_r1);
+ break;
+ case 8:
+ WriteByte(frame->tf_r1, frame->tf_r2);
+ break;
+ case 9:
+ frame->tf_r0 = ReadByte(frame->tf_r1);
+ break;
+ case 10:
+ WriteShort(frame->tf_r1, frame->tf_r2);
+ break;
+ case 11:
+ frame->tf_r0 = ReadShort(frame->tf_r1);
+ break;
+ case 16:
+ pmap_pagedir_dump();
+ break;
+/* case 32:
+ frame->tf_r0 = pmap_next_phys_page(frame->tf_r1);
+ break;*/
+ default:
+ printf("Unknown SYS_special call (%d)\n", frame->tf_r0);
+ break;
+ }
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case 0x100a:
+ printf("Warning: This syscall is about to be revoked (0x100a)\n");
+ frame->tf_r0 = pmap_page_attributes(frame->tf_r0);
+ SYSCALL_SPECIAL_RETURN;
+ break;
+/*
+ case 0x1010:
+ frame->tf_r0 = kmodule_base;
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case 0x1011:
+ frame->tf_r0 = kmodule_size;
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case 0x1012:
+ if (frame->tf_r1 < kmodule_size) {
+ bcopy((char *)frame->tf_r0, (char *)kmodule_base,
+ frame->tf_r1);
+ frame->tf_r0 = 0;
+ }
+ else
+ frame->tf_r0 = 1;
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case 0x1013:
+ {
+ int (*caller)();
+
+ caller = (void *)frame->tf_r0;
+
+ frame->tf_r0 = (*caller)(printf, install_coproc_handler);
+ }
+ SYSCALL_SPECIAL_RETURN;
+ break;
+*/
+#if NHYDRABUS > 0
+ case 0x1014:
+ frame->tf_r0 = hydrascratch.physical;
+ SYSCALL_SPECIAL_RETURN;
+ break;
+ case 0x1015:
+ frame->tf_r0 = hydrascratch.virtual;
+ SYSCALL_SPECIAL_RETURN;
+ break;
+ case 0x1016:
+ frame->tf_r0 = (u_int)proc0.p_addr->u_pcb.pcb_pagedir;
+ SYSCALL_SPECIAL_RETURN;
+ break;
+ case 0x1017:
+ frame->tf_r0 = kmem_alloc(kernel_map, round_page(frame->tf_r0));
+ SYSCALL_SPECIAL_RETURN;
+ break;
+ case 0x1018:
+ kmem_free(kernel_map, frame->tf_r0, frame->tf_r1);
+ SYSCALL_SPECIAL_RETURN;
+ break;
+#endif
+#if 0
+ case 0x1020:
+ vprint(frame->tf_r0, frame->tf_r1);
+ SYSCALL_SPECIAL_RETURN;
+ break;
+ case 0x1021:
+ { struct vnode *vp;
+ vp = (struct vp *)frame->tf_r0;
+ if (vp->v_numoutput > 0 && vp->v_usecount == 0 && vp->v_writecount == 0) {
+ printf("Patching vnode %08x\n", vp);
+ vprint(NULL, vp);
+ if (--vp->v_numoutput < 0)
+ panic("vwakeup: neg numoutput");
+ if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
+ vp->v_flag &= ~VBWAIT;
+ wakeup((caddr_t)&vp->v_numoutput);
+ }
+ }
+ SYSCALL_SPECIAL_RETURN;
+ }
+ break;
+
+ case 0x1022:
+ { struct vnode *vp;
+ vp = (struct vp *)frame->tf_r0;
+ if (vp->v_numoutput == 0 && vp->v_usecount == 0 && vp->v_writecount == 0) {
+ printf("Patching vnode %08x\n", vp);
+ vprint(NULL, vp);
+ if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
+ vp->v_flag &= ~VBWAIT;
+ wakeup((caddr_t)&vp->v_numoutput);
+ }
+ }
+ SYSCALL_SPECIAL_RETURN;
+ }
+ break;
+
+ case 0x1023:
+ wakeup((caddr_t)frame->tf_r0);
+ SYSCALL_SPECIAL_RETURN;
+ break;
+/*
+ case 0x1024:
+ dumpvndbuf((struct vnode *)frame->tf_r0);
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case 0x1025:
+ dumpvncbuf((struct vnode *)frame->tf_r0);
+ SYSCALL_SPECIAL_RETURN;
+ break;
+*/
+/* case 0x1026:
+ vfs_bufstats();
+ SYSCALL_SPECIAL_RETURN;
+ break;
+*/
+ case 0x1027:
+ bcopy(frame->tf_r0, frame->tf_r1, sizeof(struct vnode));
+ SYSCALL_SPECIAL_RETURN;
+ break;
+ case 0x1028:
+ vnodeconsolebug = frame->tf_r0;
+ SYSCALL_SPECIAL_RETURN;
+ break;
+#endif
+ case 0x102a:
+ usertraceback = frame->tf_r0;
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case 0x102b:
+ frame->tf_r0 = vmem_mapdram();
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case 0x102c:
+ frame->tf_r0 = vmem_mapvram();
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case 0x102d:
+ frame->tf_r0 = vmem_cachectl(frame->tf_r0);
+ SYSCALL_SPECIAL_RETURN;
+ break;
+
+ case SYS_syscall:
+/* code = fuword(params);*/
+ code = ReadWord(params);
+ params += sizeof(int);
+ regparams -= 1;
+ printf("SYS_syscall: code=%d %02x", code, code);
+ break;
+
+ case SYS___syscall:
+ if (callp != sysent)
+ break;
+/* code = fuword(params + _QUAD_LOWWORD * sizeof(int));*/
+
+/* Since this will be a register ... */
+
+ code = ReadWord(params + _QUAD_LOWWORD * sizeof(int));
+ params += sizeof(quad_t);
+ regparams -= 2;
+ break;
+
+ default:
+ /* do nothing by default */
+ break;
+ }
+
+ if (code < 0 || code >= nsys)
+ callp += p->p_emul->e_nosys; /* illegal */
+ else
+ callp += code;
+
+ if (callp->sy_call == sys_nosys) {
+ printf("SYSCALL: nosys code=%08x lr=%08x proc=%08x pid=%d %s\n",
+ code, frame->tf_pc, (u_int)p, p->p_pid, p->p_comm);
+ postmortem(frame);
+#ifdef POSTMORTEM
+ disassemble(frame->tf_pc-8);
+ disassemble(frame->tf_pc-4);
+ disassemble(frame->tf_pc);
+ disassemble(frame->tf_pc+4);
+#endif
+ pmap_debug(-2);
+ }
+
+ argsize = callp->sy_argsize;
+ if (argsize > (regparams * sizeof(int)))
+ argsize = regparams*sizeof(int);
+/* if (argsize && (error = copyin(params, (caddr_t)args, argsize))) {
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, callp->sy_narg, args);
+#endif
+ goto bad;
+ }*/
+ if (argsize)
+ bcopy(params, (caddr_t)args, argsize);
+
+ argsize = callp->sy_argsize;
+ if (callp->sy_argsize > (regparams * sizeof(int))
+ && (error = copyin((caddr_t)frame->tf_usr_sp,
+ (caddr_t)&args[regparams], argsize - (regparams * sizeof(int))))) {
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, callp->sy_narg, args);
+#endif
+ goto bad;
+ }
+
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, callp->sy_narg, args);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code, argsize, args);
+#endif
+ rval[0] = 0;
+ rval[1] = frame->tf_r1;
+
+ error = (*callp->sy_call)(p, args, rval);
+
+ switch (error) {
+ case 0:
+/*
+ * Reinitialize proc pointer `p' as it may be different
+ * if this is a child returning from fork syscall.
+ */
+ p = curproc;
+ frame->tf_r0 = rval[0];
+ frame->tf_r1 = rval[1];
+ frame->tf_spsr &= ~PSR_C_bit; /* carry bit */
+ break;
+
+ case ERESTART:
+/*
+ * Reconstruct the pc. opc contains the odl pc address which is
+ * the instruction after the swi.
+ */
+ frame->tf_pc = opc - 4;
+ break;
+
+ case EJUSTRETURN:
+/* nothing to do */
+ break;
+
+ default:
+ bad:
+ frame->tf_r0 = error;
+ frame->tf_spsr |= PSR_C_bit; /* carry bit */
+ break;
+ }
+
+#ifdef SYSCALL_DEBUG
+ scdebug_ret(p, code, error, rval[0]);
+#endif
+
+ validate_trapframe(frame, 4);
+
+ userret(p, frame->tf_pc, sticks);
+
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET))
+ ktrsysret(p->p_tracep, code, error, rval[0]);
+#endif
+
+ validate_trapframe(frame, 4);
+}
+
+
+void
+child_return(p, frame)
+ struct proc *p;
+ struct trapframe *frame;
+{
+ frame->tf_r0 = 0;
+ frame->tf_spsr &= ~PSR_C_bit; /* carry bit */
+
+ userret(p, frame->tf_pc, 0);
+
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET))
+ ktrsysret(p->p_tracep, SYS_fork, 0, 0);
+#endif
+}
+
+/* End of syscall.c */
--- /dev/null
+/* $NetBSD: undefined.c,v 1.2 1996/03/08 20:54:25 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * undefined.c
+ *
+ * Fault handler
+ *
+ * Created : 06/01/95
+ */
+
+#define CONTINUE_AFTER_RESET_BUG
+#define FAST_FPE
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#ifdef FAST_FPE
+#include <sys/acct.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/frame.h>
+#include <machine/undefined.h>
+#include <machine/irqhandler.h>
+
+#ifdef FAST_FPE
+extern int want_resched;
+#endif
+
+undef_handler_t undefined_handlers[MAX_COPROCS];
+
+u_int disassemble __P((u_int));
+
+
+int
+default_undefined_handler(address, instruction, frame)
+ u_int address;
+ u_int instruction;
+ trapframe_t *frame;
+{
+ struct proc *p;
+
+ p = curproc;
+ if (p == NULL)
+ p = &proc0;
+ log(LOG_ERR, "Undefined instruction 0x%08x @ 0x%08x in process %s (pid %d)\n",
+ instruction, address, p->p_comm, p->p_pid);
+ return(1);
+}
+
+
+int
+install_coproc_handler(coproc, handler)
+ int coproc;
+ undef_handler_t handler;
+{
+ if (coproc < 0 || coproc > MAX_COPROCS)
+ return(EINVAL);
+ if (handler == (undef_handler_t)0)
+ handler = default_undefined_handler;
+
+ undefined_handlers[coproc] = handler;
+ return(0);
+}
+
+
+void
+undefined_init()
+{
+ int loop;
+
+ for (loop = 0; loop < MAX_COPROCS; ++loop)
+ undefined_handlers[loop] = default_undefined_handler;
+}
+
+
+void
+undefinedinstruction(frame)
+ trapframe_t *frame;
+{
+ struct proc *p;
+/* struct pcb *pcb;*/
+ u_int fault_pc;
+ int fault_instruction;
+ int s;
+ int fault_code;
+ u_quad_t sticks;
+ int coprocessor;
+
+#ifndef BLOCK_IRQS
+ if (!(frame->tf_spsr & I32_bit))
+ enable_interrupts(I32_bit);
+#endif
+
+/* Update vmmeter statistics */
+
+ cnt.v_trap++;
+
+ fault_pc = frame->tf_pc - 4;
+
+/* Should use fuword() here .. but in the interests of squeezing every bit
+ * of speed we will just use ReadWord(). We know the instruction can be
+ * read as was just executed so this will never fail unless the kernel
+ * is screwed up in which case it does not really matter does it ?
+ */
+
+ fault_instruction = ReadWord(fault_pc);
+
+/* Check for coprocessor instruction */
+
+/*
+ * According to the datasheets you only need to look at bit 27 of the instruction
+ * to tell the difference between and undefined instruction and a
+ * coprocessor instruction.
+ */
+
+ if ((fault_instruction & (1 << 27)) != 0)
+ coprocessor = (fault_instruction >> 8) & 0x0f;
+ else {
+ coprocessor = 0;
+ s = splhigh();
+ disassemble(fault_pc);
+ (void)splx(s);
+ }
+
+/* Get the current proc structure or proc0 if there is none */
+
+ if ((p = curproc) == 0)
+ p = &proc0;
+
+/* printf("fault in process %08x %d\n", p, p->p_pid);*/
+
+ if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
+/* printf("USR32 mode : %08x\n", frame->tf_spsr);*/
+ sticks = p->p_sticks;
+
+/* Modify the fault_code to reflect the USR/SVC state at time of fault */
+
+ fault_code = FAULT_USER;
+ p->p_md.md_regs = frame;
+ } else
+ fault_code = 0;
+
+#if 0
+/* can't use curpcb, as it might be NULL; and we have p in a register anyway */
+
+ pcb = &p->p_addr->u_pcb;
+ if (pcb == 0)
+ {
+ panic("no pcb ... we're toast !\n");
+ }
+#endif
+
+/* OK this is were we do something about the instruction */
+
+/* Check for coprocessor instruction */
+
+/*
+ s = splhigh();
+ printf("Coprocessor number %d instruction fault\n", coprocessor);
+ (void)splx(s);
+*/
+
+ if ((undefined_handlers[coprocessor](fault_pc, fault_instruction,
+ frame)) != 0) {
+ s = splhigh();
+
+ if ((fault_instruction & 0x0f000010) == 0x0e000000) {
+ printf("CDP\n");
+ disassemble(fault_pc);
+ }
+ else if ((fault_instruction & 0x0e000000) == 0x0c000000) {
+ printf("LDC/STC\n");
+ disassemble(fault_pc);
+ }
+ else if ((fault_instruction & 0x0f000010) == 0x0e000010) {
+ printf("MRC/MCR\n");
+ disassemble(fault_pc);
+ }
+ else {
+ printf("Undefined instruction\n");
+ disassemble(fault_pc);
+ }
+
+ (void)splx(s);
+
+ if ((fault_code & FAULT_USER) == 0) {
+ printf("Undefined instruction in kernel: Heavy man !\n");
+ postmortem(frame);
+ }
+
+ trapsignal(p, SIGILL, fault_instruction);
+ }
+
+ if ((fault_code & FAULT_USER) == 0)
+ return;
+
+#ifdef FAST_FPE
+/* Optimised exit code */
+
+ {
+ int sig;
+
+/* take pending signals */
+
+ while ((sig = (CURSIG(p))) != 0) {
+ postsig(sig);
+ }
+
+ p->p_priority = p->p_usrpri;
+
+/*
+ * Check for reschedule request, at the moment there is only
+ * 1 ast so this code should always be run
+ */
+
+ if (want_resched) {
+ /*
+ * Since we are curproc, a clock interrupt could
+ * change our priority without changing run queues
+ * (the running process is not kept on a run queue).
+ * If this happened after we setrunqueue ourselves but
+ * before we switch()'ed, we might not be on the queue
+ * indicated by our priority
+ */
+
+ s = splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nivcsw++;
+
+ mi_switch();
+
+ (void)splx(s);
+ while ((sig = (CURSIG(p))) != 0) {
+ postsig(sig);
+ }
+ }
+
+/*
+ * The profiling bit is commented out at the moment. This can be reinstated
+ * later on. Currently addupc_task is not written.
+ */
+
+ if (p->p_flag & P_PROFIL) {
+ extern int psratio;
+ addupc_task(p, frame->tf_pc, (int)(p->p_sticks - sticks) * psratio );
+ }
+
+ curpriority = p->p_priority;
+ }
+
+#else
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 5);
+#endif
+
+ userret(p, frame->tf_pc, sticks);
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 5);
+#endif
+#endif
+}
+
+
+void
+resethandler(frame)
+ trapframe_t *frame;
+{
+ postmortem(frame);
+
+#ifdef CONTINUE_AFTER_RESET_BUG
+ printf("Branch throuh zero\n");
+ printf("The system should now be considered very unstable :-)\n");
+ sigexit(curproc, SIGILL);
+
+#ifdef VALIDATE_TRAPFRAME
+ validate_trapframe(frame, 4);
+#endif
+#else
+ panic("Branch through zero..... were dead\n");
+#endif
+}
+
+/* End of undefined.c */
--- /dev/null
+/* $NetBSD: vm_machdep.c,v 1.3 1996/03/13 21:16:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * vm_machdep.h
+ *
+ * vm machine specifiv bits
+ *
+ * Created : 08/10/94
+ */
+
+#define DEBUG_VMMACHDEP
+/*#define FREESWAPPEDPAGEDIRS*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/buf.h>
+#include <sys/user.h>
+#include <sys/core.h>
+#include <sys/exec.h>
+#include <sys/syslog.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/cpu.h>
+#include <machine/pmap.h>
+#include <machine/reg.h>
+#include <machine/vmparam.h>
+#include <machine/katelib.h>
+
+#ifdef ARMFPE
+#include <sys/device.h>
+#include <machine/cpus.h>
+#include <arm32/fpe-arm/armfpe.h>
+#endif
+
+typedef struct {
+ vm_offset_t physical;
+ vm_offset_t virtual;
+} pv_addr_t;
+
+extern pv_addr_t systempage;
+
+extern int pmap_debug_level;
+
+void switch_exit __P((struct proc */*p*/, struct proc */*proc0*/));
+int savectx __P((struct pcb *pcb));
+void pmap_activate __P((pmap_t /*pmap*/, struct pcb */*pcbp*/));
+extern void proc_trampoline __P(());
+extern void child_return __P(());
+
+/*
+ * Special compilation symbols
+ * DEBUG_VMMACHDEP
+ */
+
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the kernel stack and pcb, making the child
+ * ready to run, and marking it so that it can return differently
+ * than the parent. Returns 1 in the child process, 0 in the parent.
+ * We currently double-map the user area so that the stack is at the same
+ * address in each process; in the future we will probably relocate
+ * the frame pointers on the stack after copying.
+ */
+
+void
+cpu_fork(p1, p2)
+ struct proc *p1;
+ struct proc *p2;
+{
+ struct user *up = p2->p_addr;
+ struct pcb *pcb = (struct pcb *)&p2->p_addr->u_pcb;
+ struct trapframe *tf;
+ struct switchframe *sf;
+ int loop;
+ vm_offset_t addr;
+ u_char *ptr;
+ vm_offset_t muaddr = VM_MAXUSER_ADDRESS;
+ struct vm_map *vp;
+
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0)
+ printf("cpu_fork: %08x %08x %08x %08x\n", (u_int)p1, (u_int)p2,
+ (u_int) curproc, (u_int)&proc0);
+#endif
+
+/* Sync the pcb */
+ savectx(curpcb);
+
+/* Copy the pcb */
+ *pcb = p1->p_addr->u_pcb;
+
+/* Set up the undefined stack for the process. Note: this stack is not in use if we are forking */
+ pcb->pcb_und_sp = (u_int)p2->p_addr + USPACE_UNDEF_STACK_TOP;
+ pcb->pcb_sp = (u_int)p2->p_addr + USPACE_SVC_STACK_TOP;
+
+/* Fill the undefined stack with a known pattern */
+
+ ptr = ((u_char *)p2->p_addr) + USPACE_UNDEF_STACK_BOTTOM;
+ for (loop = 0; loop < (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM); ++loop, ++ptr) {
+ *ptr = 0xdd;
+ }
+
+/* Fill the kernel stack with a known pattern */
+
+ ptr = ((u_char *)p2->p_addr) + USPACE_SVC_STACK_BOTTOM;
+ for (loop = 0; loop < (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM); ++loop, ++ptr) {
+ *ptr = 0xdd;
+ }
+
+/* Now ...
+ * vm_fork has allocated UPAGES in kernel Vm space for us. p2->p_addr
+ * points to the start of this. The i386 releases this memory in vm_fork
+ * and relocates it in cpu_fork.
+ * We can work with it allocated by vm_fork. We we must do is
+ * copy the stack and activate the p2 page directory.
+ * We activate first and then call savectx which will copy the stack.
+ * This must also set the stack pointer for p2 to its correct address
+ * NOTE: This will be different from p1 stack address.
+ */
+
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0) {
+ printf("cpu_fork: pcb = %08x pagedir = %08x\n",
+ (u_int)&up->u_pcb, (u_int)up->u_pcb.pcb_pagedir);
+ printf("p1->procaddr=%08x p1->procaddr->u_pcb=%08x pid=%d pmap=%08x\n",
+ (u_int)p1->p_addr, (u_int)&p1->p_addr->u_pcb, p1->p_pid, (u_int)&p1->p_vmspace->vm_pmap);
+ printf("p2->procaddr=%08x p2->procaddr->u_pcb=%08x pid=%d pmap=%08x\n",
+ (u_int)p2->p_addr, (u_int)&p2->p_addr->u_pcb, p2->p_pid, (u_int)&p2->p_vmspace->vm_pmap);
+ }
+#endif
+
+/* ream out old pagetables */
+
+ vp = &p2->p_vmspace->vm_map;
+ (void)vm_deallocate(vp, muaddr, VM_MAX_ADDRESS - muaddr);
+ (void)vm_allocate(vp, &muaddr, VM_MAX_ADDRESS - muaddr, FALSE);
+ (void)vm_map_inherit(vp, muaddr, VM_MAX_ADDRESS, VM_INHERIT_NONE);
+
+
+/* Get the address of the page table containing 0x00000000 */
+
+ addr = trunc_page((u_int)vtopte(0));
+
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0) {
+ printf("fun time: paging in PT %08x for %08x\n", (u_int)addr, 0);
+ printf("p2->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p2->p_vmspace->vm_pmap.pm_pdir[0]);
+ printf("p2->pm_vptpt[0] = %08x", *((int *)(p2->p_vmspace->vm_pmap.pm_vptpt + 0)));
+ }
+#endif
+
+/* Nuke the exising mapping */
+
+ p2->p_vmspace->vm_pmap.pm_pdir[0] = 0;
+ p2->p_vmspace->vm_pmap.pm_pdir[1] = 0;
+ p2->p_vmspace->vm_pmap.pm_pdir[2] = 0;
+ p2->p_vmspace->vm_pmap.pm_pdir[3] = 0;
+
+ *((int *)(p2->p_vmspace->vm_pmap.pm_vptpt + 0)) = 0;
+
+/* Wire down a page to cover the page table zero page and the start of the user are in */
+
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0) {
+ printf("vm_map_pageable: addr=%08x\n", addr);
+ }
+#endif
+
+ if (vm_map_pageable(&p2->p_vmspace->vm_map, addr, addr+NBPG, FALSE) != 0) {
+ panic("Failed to fault in system page PT\n");
+ }
+
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0) {
+ printf("party on! acquired a page table for 0M->(4M-1)\n");
+ printf("p2->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p2->p_vmspace->vm_pmap.pm_pdir[0]);
+ printf("p2->pm_vptpt[0] = %08x", *((int *)(p2->p_vmspace->vm_pmap.pm_vptpt + 0)));
+ }
+#endif
+
+/* Map the system page */
+
+ pmap_enter(&p2->p_vmspace->vm_pmap, 0,
+ systempage.physical, VM_PROT_READ, TRUE);
+
+ pmap_activate(&p2->p_vmspace->vm_pmap, &up->u_pcb);
+
+#ifdef ARMFPE
+/* Initialise a new FP context for p2 and copy the context from p1 */
+ arm_fpe_core_initcontext(FP_CONTEXT(p2));
+ arm_fpe_copycontext(FP_CONTEXT(p1), FP_CONTEXT(p2));
+#endif
+
+ p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_sp - 1;
+
+ *tf = *p1->p_md.md_regs;
+ sf = (struct switchframe *)tf - 1;
+ sf->sf_spl = SPL_0;
+ sf->sf_r4 = (u_int)child_return;
+ sf->sf_r5 = (u_int)p2;
+ sf->sf_pc = (u_int)proc_trampoline;
+ pcb->pcb_sp = (u_int)sf;
+}
+
+
+void
+cpu_set_kpc(p, pc)
+ struct proc *p;
+ u_long pc;
+{
+ struct switchframe *sf = (struct switchframe *)p->p_addr->u_pcb.pcb_sp;
+
+ sf->sf_r4 = pc;
+ sf->sf_r5 = (u_int)p;
+}
+
+
+/*
+ * cpu_exit is called as the last action during exit.
+ *
+ * We clean up a little and then call switch_exit() with the old proc as an
+ * argument. switch_exit() first switches to proc0's context, then does the
+ * vmspace_free() and kmem_free() that we don't do here, and finally jumps
+ * into switch() to wait for another process to wake up.
+ */
+
+void
+cpu_exit(p)
+ register struct proc *p;
+{
+ struct vmspace *vm;
+
+#ifdef ARMFPE
+/* Abort any active FP operation and deactivate the context */
+ arm_fpe_core_abort(FP_CONTEXT(p), NULL, NULL);
+ arm_fpe_core_changecontext(0);
+#endif
+
+/* Report how much stack has been used - debugging */
+
+/* if (p) {
+ u_char *ptr;
+ int loop;
+
+ ptr = ((u_char *)p2->p_addr) + USPACE_UNDEF_STACK_BOTTOM;
+ for (loop = 0; loop < (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ;
+ log(LOG_INFO, "%d bytes of undefined stack fill pattern\n", loop);
+ ptr = ((u_char *)p2->p_addr) + USPACE_SVC_STACK_BOTTOM;
+ for (loop = 0; loop < (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ;
+ log(LOG_INFO, "%d bytes of svc stack fill pattern\n", loop);
+
+ }
+*/
+
+/* printf("cpu_exit: proc=%08x pid=%d comm=%s\n", p, p->p_pid, p->p_comm);*/
+
+ vm = p->p_vmspace;
+ if (vm->vm_refcnt == 1) /* What does this do and is it needed ? */
+ vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS);
+
+ cnt.v_swtch++;
+
+ switch_exit(p, &proc0);
+}
+
+
+void
+cpu_swapin(p)
+ struct proc *p;
+{
+ vm_offset_t addr;
+ int loop;
+
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0)
+ printf("cpu_swapin(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap);
+#endif
+
+#ifdef FREESWAPPEDPAGEDIRS
+ printf("cpu_swapin(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap);
+ if (p->p_vmspace->vm_pmap.pm_pdir)
+ printf("pdir = %08x\n", p->p_vmspace->vm_pmap.pm_pdir);
+ pmap_pinit(&p->p_vmspace->vm_pmap);
+ pmap_debug_level = 10;
+#endif
+
+/* Get the address of the page table containing 0x00000000 */
+
+ addr = trunc_page((u_int)vtopte(0));
+
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0) {
+ printf("fun time: paging in PT %08x for %08x\n", (u_int)addr, 0);
+ printf("p->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p->p_vmspace->vm_pmap.pm_pdir[0]);
+ printf("p->pm_vptpt[0] = %08x", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0)));
+ }
+#endif
+
+/* Wire down a page to cover the page table zero page and the start of the user are in */
+
+ vm_map_pageable(&p->p_vmspace->vm_map, addr, addr+NBPG, FALSE);
+
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0) {
+ printf("party on! acquired a page table for 0M->(4M-1)\n");
+ printf("p->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p->p_vmspace->vm_pmap.pm_pdir[0]);
+ printf("p->pm_vptpt[0] = %08x", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0)));
+ }
+#endif
+
+/* Map the system page */
+
+ pmap_enter(&p->p_vmspace->vm_pmap, 0,
+ systempage.physical, VM_PROT_READ, TRUE);
+}
+
+
+void
+cpu_swapout(p)
+ struct proc *p;
+{
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0) {
+ printf("cpu_swapout(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap);
+ printf("p->pm_vptpt[0] = %08x", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0)));
+ }
+#endif
+
+/* Free the system page mapping */
+
+ pmap_remove(&p->p_vmspace->vm_pmap, 0, NBPG);
+
+#ifdef FREESWAPPEDPAGEDIRS
+ printf("cpu_swapout(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap);
+ printf("p->pm_vptpt[0] = %08x pdir=%08x\n", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0)), p->p_vmspace->vm_pmap.pm_pdir);
+ pmap_freepagedir(&p->p_vmspace->vm_pmap);
+ p->p_vmspace->vm_pmap.pm_pdir = 0;
+#endif
+
+ idcflush();
+}
+
+
+/*
+ * Move pages from one kernel virtual address to another.
+ * Both addresses are assumed to reside in the Sysmap,
+ * and size must be a multiple of CLSIZE.
+ */
+
+void
+pagemove(from, to, size)
+ caddr_t from, to;
+ int size;
+{
+ register pt_entry_t *fpte, *tpte;
+
+ if (size % CLBYTES)
+ panic("pagemove: size=%08x", size);
+
+#ifdef DEBUG_VMMACHDEP
+ if (pmap_debug_level >= 0)
+ printf("pagemove: V%08x to %08x size %08x\n", (u_int)from,
+ (u_int)to, size);
+#endif
+ fpte = vtopte(from);
+ tpte = vtopte(to);
+
+ idcflush();
+
+ while (size > 0) {
+ *tpte++ = *fpte;
+ *fpte++ = 0;
+ size -= NBPG;
+ }
+ tlbflush();
+}
+
+extern vm_map_t phys_map;
+
+/*
+ * Map an IO request into kernel virtual address space. Requests fall into
+ * one of five catagories:
+ *
+ * B_PHYS|B_UAREA: User u-area swap.
+ * Address is relative to start of u-area (p_addr).
+ * B_PHYS|B_PAGET: User page table swap.
+ * Address is a kernel VA in usrpt (Usrptmap).
+ * B_PHYS|B_DIRTY: Dirty page push.
+ * Address is a VA in proc2's address space.
+ * B_PHYS|B_PGIN: Kernel pagein of user pages.
+ * Address is VA in user's address space.
+ * B_PHYS: User "raw" IO request.
+ * Address is VA in user's address space.
+ *
+ * All requests are (re)mapped into kernel VA space via the useriomap
+ * (a name with only slightly more meaning than "kernelmap")
+ */
+
+void
+vmapbuf(bp, len)
+ struct buf *bp;
+ vm_size_t len;
+{
+ vm_offset_t faddr, taddr, off;
+ pt_entry_t *fpte, *tpte;
+ pt_entry_t *pmap_pte __P((pmap_t, vm_offset_t));
+
+ if (pmap_debug_level >= 0)
+ printf("vmapbuf: bp=%08x buf=%08x len=%08x\n", (u_int)bp,
+ (u_int)bp->b_data, (u_int)len);
+
+ if ((bp->b_flags & B_PHYS) == 0)
+ panic("vmapbuf");
+
+ faddr = trunc_page(bp->b_saveaddr = bp->b_data);
+ off = (vm_offset_t)bp->b_data - faddr;
+ len = round_page(off + len);
+ taddr = kmem_alloc_wait(phys_map, len);
+ bp->b_data = (caddr_t)(taddr + off);
+ /*
+ * The region is locked, so we expect that pmap_pte() will return
+ * non-NULL.
+ */
+
+ fpte = pmap_pte(vm_map_pmap(&bp->b_proc->p_vmspace->vm_map), faddr);
+ tpte = pmap_pte(vm_map_pmap(phys_map), taddr);
+
+ idcflush();
+
+ do {
+ *fpte = (*fpte) & ~PT_C;
+ *tpte++ = *fpte++;
+ len -= PAGE_SIZE;
+ } while (len > 0);
+ tlbflush();
+}
+
+/*
+ * Free the io map PTEs associated with this IO operation.
+ * We also invalidate the TLB entries and restore the original b_addr.
+ */
+
+void
+vunmapbuf(bp, len)
+ struct buf *bp;
+ vm_size_t len;
+{
+ vm_offset_t addr, off;
+
+ if (pmap_debug_level >= 0)
+ printf("vunmapbuf: bp=%08x buf=%08x len=%08x\n",
+ (u_int)bp, (u_int)bp->b_data, (u_int)len);
+
+ if ((bp->b_flags & B_PHYS) == 0)
+ panic("vunmapbuf");
+
+ idcflush();
+
+ addr = trunc_page(bp->b_data);
+ off = (vm_offset_t)bp->b_data - addr;
+ len = round_page(off + len);
+ kmem_free_wakeup(phys_map, addr, len);
+ bp->b_data = bp->b_saveaddr;
+ bp->b_saveaddr = 0;
+
+ tlbflush();
+}
+
+/*
+ * Dump the machine specific segment at the start of a core dump.
+ */
+
+int
+cpu_coredump(p, vp, cred, chdr)
+ struct proc *p;
+ struct vnode *vp;
+ struct ucred *cred;
+ struct core *chdr;
+{
+ int error;
+ struct {
+ struct reg regs;
+ struct fpreg fpregs;
+ } cpustate;
+ struct coreseg cseg;
+
+ CORE_SETMAGIC(*chdr, COREMAGIC, MID_ARM6, 0);
+ chdr->c_hdrsize = ALIGN(sizeof(*chdr));
+ chdr->c_seghdrsize = ALIGN(sizeof(cseg));
+ chdr->c_cpusize = sizeof(cpustate);
+
+ /* Save integer registers. */
+ error = process_read_regs(p, &cpustate.regs);
+ if (error)
+ return error;
+ /* Save floating point registers. */
+ error = process_read_fpregs(p, &cpustate.fpregs);
+ if (error)
+ return error;
+
+ CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ARM6, CORE_CPU);
+ cseg.c_addr = 0;
+ cseg.c_size = chdr->c_cpusize;
+
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
+ (off_t)chdr->c_hdrsize, UIO_SYSSPACE,
+ IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p);
+ if (error)
+ return error;
+
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cpustate, sizeof(cpustate),
+ (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
+ IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p);
+ if (error)
+ return error;
+
+ chdr->c_nseg++;
+
+ return error;
+}
+
+/* End of vm_machdep.c */
--- /dev/null
+# $NetBSD: Makefile,v 1.2 1996/02/01 22:29:25 mycroft Exp $
+
+# Copyright (c) 1994,1995 Mark Brinicombe.
+# Copyright (c) 1994 Brini.
+# All rights reserved.
+#
+# This code is derived from software written for Brini by Mark Brinicombe
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Brini.
+# 4. The name of the company nor the name of the author may be used to
+# endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES# LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# RiscBSD kernel project
+#
+# Makefile
+#
+# Makefile for RiscBSD bootloader for RISCOS
+#
+# Created : 14/01/96
+# Last updated : 14/01/96
+#
+# $Id: Makefile,v 1.1.1.1 1996/04/24 11:08:30 deraadt Exp $
+#
+
+S= ../../..
+
+machine-links:
+ -rm -f machine && \
+ ln -s ${.CURDIR}/../include machine
+ -rm -f ${MACHINE_ARCH} && \
+ ln -s ${.CURDIR}/../include ${MACHINE_ARCH}
+
+all: machine-links boot
+
+NOPROG= noprog
+NOMAN= noman
+
+CFLAGS= -O3 -fno-builtin -D_LOCORE -D_KERNEL -I. -I${.CURDIR} -I$S -I${.CURDIR}/../..
+AFLAGS= -D_LOCORE -D_KERNEL -I. -I${.CURDIR} -I$S -I${.CURDIR}/../..
+
+### find out what to use for libkern and libsa
+#SAREL=
+#KERNREL=
+#.include "Makefile.inc"
+.include "$S/lib/libsa/Makefile.inc"
+.include "$S/lib/libkern/Makefile.inc"
+
+all: boot ${SALIB} ${KERNLIB}
+
+#.PATH: $S/lib/libkern
+#.PATH: $S/lib/libkern/arch/arm32
+
+# start.o should be first
+OBJS= start.o strcpy.o strlen.o strncmp.o strstr.o \
+ svc32.o div.o exit.o enteros.o exitos.o setcpsr.o \
+ memcpy.o memset.o ntohl.o _bsdboot.o _main.o \
+ areahand.o vsprintf.o bsdbooter.o swiv.o
+
+boot: ${OBJS}
+ ${LD} -Bstatic -e start -N -Ttext 0x8000 -o boot ${OBJS}
+ cp boot boot.sym
+ @strip boot
+ @sh ${.CURDIR}/rmaouthdr boot boot.tmp
+ @mv -f boot.tmp boot
+ @ls -l boot
+
+CLEANFILES+=boot boot.sym machine ${MACHINE_ARCH}
+
+clean::
+ rm -f a.out [Ee]rrs mklog core *.core
+ rm -f ${PROG} ${OBJS} ${LOBJS} ${CLEANFILES}
+
+.include <bsd.prog.mk>
--- /dev/null
+# $NetBSD: Makefile.inc,v 1.1 1996/01/31 23:17:48 mark Exp $
+#
+# NOTE: $S must correspond to the top of the 'sys' tree
+
+KERNDIR= $S/lib/libkern
+
+KERNDST= lib/kern
+KERNREL?= ../../
+KERNLIB?= ${KERNDST}/libkern.a
+
+${KERNLIB}: .NOTMAIN __always_make_kernlib
+ @echo making sure the kern library is up to date...
+ @(cd ${KERNDST} && ${MAKE} -f ${KERNREL}${KERNDIR}/Makefile \
+ KERNCC="${CC}" \
+ KERNCFLAGS="${CFLAGS}" \
+ KERNREL="${KERNREL}" \
+ KERNDIR="${KERNDIR}" libkern.o)
+
+clean:: .NOTMAIN __always_make_kernlib
+ @echo cleaning the kern library objects
+ @(cd ${KERNDST} && ${MAKE} -f ${KERNREL}${KERNDIR}/Makefile \
+ KERNCC="${CC}" \
+ KERNCFLAGS="${CFLAGS}" \
+ KERNREL="${KERNREL}" \
+ KERNDIR="${KERNDIR}" clean)
+
+__always_make_kernlib: .NOTMAIN
+ @([ -d ${KERNDST} ] || mkdir -p ${KERNDST})
--- /dev/null
+Ok, this is the bootloader source that can be used to boot NetBSD/arm32
+from RISCOS. This code was written for use with Norcroft C and
+objasm under RISCOS. It has been modified to compile under NetBSD/arm32
+but is as yet untested.
+
+It is provided here for the moment as example code for a boot loader
+and will be updated shortly to compile under NetBSD/arm32
--- /dev/null
+/* $NetBSD: _bsdboot.S,v 1.1 1996/01/31 23:17:52 mark Exp $ */
+
+/* Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES * LOSS OF USE, DATA, OR PROFITS * OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * _boot.s
+ *
+ * Kernel entry/exit code
+ *
+ * Created : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/boot/_boot.s
+ *
+ * $Id: _bsdboot.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+#include "regs.h"
+
+ .text
+ .global __bsdboot
+__bsdboot:
+ mov pc, r1
--- /dev/null
+/* $NetBSD: _main.S,v 1.1 1996/01/31 23:17:57 mark Exp $ */
+
+/* Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES * LOSS OF USE, DATA, OR PROFITS * OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * _main.s
+ *
+ * Kernel entry/exit code
+ *
+ * Created : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/boot/_main.s
+ *
+ * $Id: _main.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+#include "regs.h"
+
+ .global ___main
+___main:
+ swi 0x20010
+ mov sp, r1
+ sub sl, sp, #2048
+
+ ldr r3, [pc, #cli_ptr - . - 8]
+ str r0, [r3]
+#if 0
+ LDR a4,[pc,#|__cli_ptr|-.-8]
+ STR a1,[a4,#0]
+ LDR a4,[pc,#|__himem_ptr|-.-8]
+ STR a2,[a4,#0]
+ LDR a4,[pc,#|__stack_ptr|-.-8]
+ STR sl,[a4,#0]
+ LDR a4,[pc,#|__robase_ptr|-.-8]
+ LDR a1,[a4,#0]
+ LDR a4,[pc,#|__base_ptr|-.-8]
+ STR a1,[a4,#0]
+ LDR a4,[pc,#|__rwlimit_ptr|-.-8]
+ LDR a1,[a4,#0]
+ LDR a4,[pc,#|__lomem_ptr|-.-8]
+ STR a1,[a4,#0]
+ LDR a4,[pc,#|__break_ptr|-.-8]
+ STR a1,[a4,#0]
+#endif
+#if 0
+ cmp sl, r0
+ movlss pc, lr /* no stack - exit fast */
+ add sl, sl, #256
+#endif
+ mov fp, #0
+ b __main
+
+cli_ptr:
+ .word ___cli
+
+ .data
+ .global ___cli
+___cli:
+ .word 0
+
+#if 0
+
+|__cli_ptr|
+ DCD |__cli|
+
+|__robase_ptr|
+ DCD |__robase|
+|__base_ptr|
+ DCD |__base|
+|__rwbase_ptr|
+ DCD |__rwbase|
+|__rwlimit_ptr|
+ DCD |__rwlimit|
+|__himem_ptr|
+ DCD |__himem|
+|__lomem_ptr|
+ DCD |__lomem|
+
+|__break_ptr|
+ DCD |__break|
+|__stack_ptr|
+ DCD |__stack|
+
+|__time_ptr|
+ DCD |__time|
+
+ EXPORT |__cli| ; CLI from OS_GetEnv
+|__cli|
+ DCD 0
+
+ EXPORT |__base| ; BASE (application = 0x8000)
+|__base|
+ DCD 0
+ EXPORT |__lomem| ; LOMEM
+|__lomem|
+ DCD 0
+ EXPORT |__himem| ; HIMEM from OS_GetEnv
+|__himem|
+ DCD 0
+
+ EXPORT |__break| ; the 'break'
+|__break|
+ DCD 0
+ EXPORT |__stack| ; stack limit
+|__stack|
+ DCD 0
+
+#endif
--- /dev/null
+/* $NetBSD: areahand.S,v 1.1 1996/01/31 23:18:01 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * areahand.s
+ *
+ *
+ *
+ * Created : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * $Id: areahand.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+#include "regs.h"
+
+ .text
+ .global _kernarea_handler
+/*
+ * r0 - code
+ * r1 - page block
+ * r2 - entries
+ * r3 - size increase
+ * r4 - current size
+ * r5 - pagesize
+ * r12 - arrangement table
+ */
+
+_kernarea_handler:
+/* Is it a pregrow request ? */
+ teq r0, #0x00000000
+ bicnes pc, lr, #1<<28
+
+/* Make sure that the area is currently 0 in size */
+ teq r4, #0x00000000
+ movne r0, #0x000000
+ orrnes pc, lr, #1<<28
+
+ teq r1, #0x00000000
+ biceqs pc, lr, #1<<28
+
+/* Store registers */
+ stmfd sp!, {r0-r12}
+
+/* Get first page number */
+ ldr r8, [r12, #0x0004]
+ sub r8, r8, r2
+ mov r8, #0x00000700
+ str r1, [r12]
+
+loop:
+ str r8, [r1], #0x000c
+ add r8, r8, #0x00000001
+ subs r2, r2, #0x00000001
+ bne loop
+
+ ldmfd sp!, {r0-r12}
+/* bics pc, lr, #1<<28 */
+ adr r0, error1
+ orrs pc, lr, #1<<28
+
+error1:
+ .word 0
+ .asciz "error1"
--- /dev/null
+; ARM6 PSR transfer macros
+
+; Condition code symbols
+
+Cond_EQ * 0 :SHL: 28
+Cond_NE * 1 :SHL: 28
+Cond_CS * 2 :SHL: 28
+Cond_HS * Cond_CS
+Cond_CC * 3 :SHL: 28
+Cond_LO * Cond_CC
+Cond_MI * 4 :SHL: 28
+Cond_PL * 5 :SHL: 28
+Cond_VS * 6 :SHL: 28
+Cond_VC * 7 :SHL: 28
+Cond_HI * 8 :SHL: 28
+Cond_LS * 9 :SHL: 28
+Cond_GE * 10 :SHL: 28
+Cond_LT * 11 :SHL: 28
+Cond_GT * 12 :SHL: 28
+Cond_LE * 13 :SHL: 28
+Cond_AL * 14 :SHL: 28
+Cond_ * Cond_AL
+Cond_NV * 15 :SHL: 28
+
+; New positions of I and F bits in 32-bit PSR
+
+I32_bit * 1 :SHL: 7
+F32_bit * 1 :SHL: 6
+IF32_26Shift * 26-6
+
+; Processor mode numbers
+
+USR26_mode * 2_00000
+FIQ26_mode * 2_00001
+IRQ26_mode * 2_00010
+SVC26_mode * 2_00011
+USR32_mode * 2_10000
+FIQ32_mode * 2_10001
+IRQ32_mode * 2_10010
+SVC32_mode * 2_10011
+ABT32_mode * 2_10111
+UND32_mode * 2_11011
+
+; New register names
+
+r13_abort RN 13
+r14_abort RN 14
+lr_abort RN 14
+
+r13_undef RN 13
+r14_undef RN 14
+lr_undef RN 14
+
+ MACRO
+ mrs $cond, $rd, $psrs
+ LCLA psrtype
+psrtype SETA -1
+ [ "$psrs" = "CPSR" :LOR: "$psrs" = "CPSR_all"
+psrtype SETA 0 :SHL: 22
+ ]
+ [ "$psrs" = "SPSR" :LOR: "$psrs" = "SPSR_all"
+psrtype SETA 1 :SHL: 22
+ ]
+ ASSERT psrtype <> -1
+ ASSERT $rd <> 15
+ & Cond_$cond :OR: 2_00000001000011110000000000000000 :OR: psrtype :OR: ($rd :SHL: 12)
+ MEND
+
+ MACRO
+ msr $cond, $psrl, $op2a, $op2b
+ LCLA psrtype
+ LCLS op2as
+ LCLA op
+ LCLA shift
+psrtype SETA -1
+ [ "$psrl" = "CPSR" :LOR: "$psrl" = "CPSR_all"
+psrtype SETA (0:SHL:22) :OR: (1:SHL:19) :OR: (1:SHL:16)
+ ]
+ [ "$psrl" = "CPSR_flg"
+psrtype SETA (0:SHL:22) :OR: (1:SHL:19) :OR: (0:SHL:16)
+ ]
+ [ "$psrl" = "CPSR_ctl"
+psrtype SETA (0:SHL:22) :OR: (0:SHL:19) :OR: (1:SHL:16)
+ ]
+ [ "$psrl" = "SPSR" :LOR: "$psrl" = "SPSR_all"
+psrtype SETA (1:SHL:22) :OR: (1:SHL:19) :OR: (1:SHL:16)
+ ]
+ [ "$psrl" = "SPSR_flg"
+psrtype SETA (1:SHL:22) :OR: (1:SHL:19) :OR: (0:SHL:16)
+ ]
+ [ "$psrl" = "SPSR_ctl"
+psrtype SETA (1:SHL:22) :OR: (0:SHL:19) :OR: (1:SHL:16)
+ ]
+ ASSERT psrtype <> -1
+ [ ("$op2a" :LEFT: 1) = "#"
+ ; Immediate operand
+
+op2as SETS "$op2a" :RIGHT: ((:LEN: "$op2a")-1)
+op SETA $op2as
+
+ [ "$op2b" = ""
+ ; Rotate not specified in immediate operand
+shift SETA 0
+ WHILE (op :AND: &FFFFFF00)<>0 :LAND: shift<16
+op SETA ((op:SHR:30):AND:3):OR:(op:SHL:2)
+shift SETA shift + 1
+ WEND
+ ASSERT (op :AND: &FFFFFF00)=0
+ |
+ ; Rotate of immediate operand specified explicitly
+ ASSERT (($op2b):AND:&FFFFFFE1)=0
+shift SETA ($opt2b):SHR:1
+ ]
+op SETA (shift :SHL: 8) :OR: op :OR: (1:SHL:25)
+ |
+
+ ; Not an immediate operand
+ [ "$op2b" = ""
+ ; Unshifted register
+op SETA ($op2a) :OR: (0:SHL:25)
+ |
+ ! 1, "Shifted register not yet implemented in this macro!"
+ ]
+ ]
+ & Cond_$cond :OR: 2_00000001001000001111000000000000 :OR: op :OR: psrtype
+ MEND
+
+; SetMode newmode, reg1, regoldpsr
+;
+; Sets processor mode to constant value newmode
+; using register reg1 as a temporary.
+; If regoldpsr is specified, then this register
+; on exit holds the old PSR before the mode change
+; reg1 on exit always holds the new PSR after the mode change
+
+; MACRO
+; SetMode $newmode, $reg1, $regoldpsr
+; [ "$regoldpsr"=""
+; mrs AL, $reg1, CPSR_all
+; BIC $reg1, $reg1, #&1F
+; ORR $reg1, $reg1, #$newmode
+; msr AL, CPSR_all, $reg1
+; |
+; mrs AL, $regoldpsr, CPSR_all
+; BIC $reg1, $regoldpsr, #&1F
+; ORR $reg1, $reg1, #$newmode
+; msr AL, CPSR_all, $reg1
+; ]
+; MEND
+
+ MACRO
+ mrc $cond, $coproc, $op, $rd, $crn, $crm, $info
+ & Cond_$cond :OR: 2_00001110000100000000000000010000 :OR: ($coproc :SHL: 8) :OR: ($op :SHL: 21) :OR: ($rd :SHL: 12) :OR: ($crn :SHL: 16) :OR: $crm :OR: ($info :SHL: 5)
+ MEND
+
+ MACRO
+ mcr $cond, $coproc, $op, $rd, $crn, $crm, $info
+ & Cond_$cond :OR: 2_00001110000000000000000000010000 :OR: ($coproc :SHL: 8) :OR: ($op :SHL: 21) :OR: ($rd :SHL: 12) :OR: ($crn :SHL: 16) :OR: $crm :OR: ($info :SHL: 5)
+ MEND
+
+ END
--- /dev/null
+/* $NetBSD: bsdbooter.c,v 1.1 1996/01/31 23:18:08 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994,1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * bsdbooter.c
+ *
+ * RiscBSD boot loader
+ *
+ * Created : 12/09/94
+ * Last updated : 08/03/95
+ *
+ * Based on kate/boot/boot.c
+ *
+ * $Id: bsdbooter.c,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+/* Include standard header files */
+
+# include <stdlib.h>
+# include <string.h>
+# include <stdarg.h>
+
+/* Include local headers */
+
+#include <sys/types.h>
+#include <sys/exec.h>
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/bootconfig.h>
+#include "swiv.h"
+#include "swis.h"
+
+/*
+ * Declare global variables
+ */
+
+# define VERSION "2.10"
+
+# define USE_MODULEAREA
+
+# define KERNAREA 512
+# define KERNBASE 0xf0000000
+
+# define TABLEAREA 513
+# define LOADAREA 514
+
+# define SCRATCHSIZE 0xc000
+
+
+# define OS_DynamicArea 0x66
+# define OS_Memory 0x68
+# define OS_MMUControl 0x6b
+
+# define FASTBOOT_FILENAME "<BtRiscBSD$Dir>.booter.fastboot"
+
+/*
+ * Declare external variables
+ */
+
+extern char *__cli;
+
+/*
+ * Local vars. Some of these have to be global because they are used after
+ * the processor has been switches to SVC mode local variables would be
+ * lost as they would be on the USR mode stack.
+ */
+
+typedef struct exec aout_t;
+
+BootConfig bootconfig;
+int in[3], out[3];
+char kernelname[1024];
+unsigned char *buffer;
+static aout_t aout;
+unsigned int kernelsize;
+unsigned int logical;
+unsigned int physical;
+unsigned int filesize;
+unsigned int copysize;
+
+/*
+ * Local function prototypes
+ */
+
+void fatal(struct Error *error);
+unsigned char *locate_memory_blocks(void);
+void uprintf(char *formattoken, ...);
+void _bsdboot(BootConfig *bootconfig, unsigned int address);
+int vsprintf(char *buf, const char *fmt, va_list args);
+
+/* Now for the main code */
+
+extern int main (int, char **);
+
+void __exit(int);
+
+void _main(void)
+ {
+ uprintf("_main entered\n");
+ __exit (main (0, (char **)0)); /* ... ignition */
+
+/* not reached */
+ }
+
+/* The main booter code */
+
+int main(int argc, char *argv[])
+ {
+ char *cliptr;
+ int loop;
+ int filehandle;
+ unsigned char *arrangementtable;
+
+ uprintf("main entered\n");
+
+/* Analyse the command line */
+
+ cliptr = __cli;
+
+ uprintf("command line is %s\n", cliptr);
+
+/* Skip the command name */
+
+ while (*cliptr != ' ' && *cliptr != 0)
+ ++cliptr;
+
+/* Skip any spaces */
+
+ while (*cliptr == ' ')
+ ++cliptr;
+
+/* Check for another parameter */
+
+ if (*cliptr != 0)
+ {
+ for (loop = 0; *cliptr != ' ' && *cliptr != 0; ++loop,++cliptr)
+ {
+ kernelname[loop] = *cliptr;
+ }
+ kernelname[loop] = 0;
+ }
+ else
+ strcpy(kernelname, "riscbsd");
+
+ strcpy(bootconfig.kernelname, kernelname);
+
+/* Write the command line used to a fastboot file. Execing or Obeying
+ * this file will boot RiscBSD. This can be used during the RiscOS bootup
+ * to enable a fast boot.
+ */
+
+/*
+ * Open the autoboot file. Just skip if file cannot be opened.
+ */
+
+ swi(OS_Find, IN(R0|R1)|OUT(R0), 0x80, FASTBOOT_FILENAME, &filehandle);
+ if (filehandle != 0)
+ {
+ swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, __cli,
+ strlen(__cli), 0);
+ swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, "\n", 1, 0);
+
+/* Close the file */
+
+ swi(OS_Find, IN(R0|R1), 0, filehandle);
+
+ swi(OS_File, IN(R0|R1|R2), 18, FASTBOOT_FILENAME, 0xfeb);
+ }
+ else
+ {
+ uprintf("Warning: Cannot write fastboot file %s\n\r", FASTBOOT_FILENAME);
+ }
+
+/* Set the screen mode ... */
+
+/* I know this is messy. It is currently just a hack to try things out
+ * Why didn't Acorn add a SWI call to interpret the mode string and return
+ * a mode specifer ?
+ */
+
+/* Also this is temporary as eventually the console driver will set the VIDC
+ * up as required.
+ * It sort of expects the screenmode= options to be at the end of the string.
+ */
+
+ {
+ char *modeptr;
+ int modespec[6];
+
+ modeptr = strstr(__cli, "screenmode=");
+ if (modeptr)
+ {
+ modeptr += 11;
+ modespec[0] = 0x00000001;
+ modespec[1] = 0x00000000;
+ modespec[2] = 0x00000000;
+ modespec[3] = 0x00000003;
+ modespec[4] = 0x00000000;
+ modespec[5] = -1;
+
+ while (*modeptr)
+ {
+ switch (*modeptr)
+ {
+ case 'X':
+ case 'x':
+ ++modeptr;
+ while (*modeptr >= '0' && *modeptr <= '9')
+ {
+ modespec[1] = (modespec[1] * 10) + (*modeptr - '0');
+ ++modeptr;
+ }
+ break;
+
+ case 'Y':
+ case 'y':
+ ++modeptr;
+ while (*modeptr >= '0' && *modeptr <= '9')
+ {
+ modespec[2] = (modespec[2] * 10) + (*modeptr - '0');
+ ++modeptr;
+ }
+ break;
+/*
+ case 'C':
+ case 'c':
+ case 'G':
+ case 'g':
+ ++modeptr;
+ while (*modeptr >= '0' && *modeptr <= '9')
+ {
+ modespec[3] = (modespec[3] * 10) + (*modeptr - '0');
+ ++modeptr;
+ }
+ break;
+*/
+ case 'F':
+ case 'f':
+ ++modeptr;
+ while (*modeptr >= '0' && *modeptr <= '9')
+ {
+ modespec[4] = (modespec[4] * 10) + (*modeptr - '0');
+ ++modeptr;
+ }
+ break;
+
+ default:
+ ++modeptr;
+ break;
+ }
+ }
+ if (modespec[4] == 0) modespec[4] = -1;
+/* uprintf("x=%d y=%d c=%d f=%d\n", modespec[1], modespec[2],
+ modespec[3], modespec[4]);*/
+ fatal(swix(Wimp_SetMode, IN(R0), &modespec));
+ bootconfig.framerate = modespec[4];
+ }
+ else
+ bootconfig.framerate = 0;
+ }
+
+/* Announcement time .. */
+/* Used to be above but now moved to after the mode change */
+
+
+ if (strstr(__cli, "verbose") != 0)
+ uprintf("RiscBSD BootLoader " VERSION " " __DATE__ "\n\r");
+
+/* A bit of info */
+
+ if (strstr(__cli, "verbose") != 0)
+ uprintf("Kernel: %s\n\r", kernelname);
+
+/* Get the machine id */
+
+ fatal(swix(OS_ReadSysInfo, IN(R0)|OUT(R3), 2, &bootconfig.machine_id));
+
+/* Get the display variables. Failure on any of these will abort the boot */
+
+ in[0] = 149;
+ in[1] = 150;
+ in[2] = -1;
+
+ fatal(swix(OS_ReadVduVariables, IN(R0|R1), &in, &out));
+
+ bootconfig.display_start = out[0];
+ bootconfig.display_size = out[1];
+
+ fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 9,
+ &bootconfig.bitsperpixel));
+ fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 11,
+ &bootconfig.width));
+ fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 12,
+ &bootconfig.height));
+
+/* Will the kernel support this mode ? */
+
+ if (bootconfig.bitsperpixel > 3)
+ {
+ swi(OS_Write0, IN(R0),
+ "Error: Only 1, 2, 4 or 8 bpp modes are currently supported\n\r");
+ return(0);
+ }
+
+/* Get the arrangement table for the memory */
+
+ arrangementtable = locate_memory_blocks();
+
+/*
+ * Ok we will support a.out files as well. This means that we need to
+ * identify the format.
+ */
+
+/* Get the size of the file */
+
+ fatal(swix(OS_File, IN(R0|R1)|OUT(R4), 5, kernelname, &filesize));
+
+/*
+ * Read the start of the file so that we change check for the a.out
+ * magic number.
+ */
+
+ swi(OS_Find, IN(R0|R1)|OUT(R0), 0x40, kernelname, &filehandle);
+ if (filehandle == 0)
+ {
+ uprintf("Error: Cannot read kernel file %s\n\r", kernelname);
+ return(0);
+ }
+
+ aout.a_midmag = 0;
+
+ fatal(swix(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, &aout,
+ sizeof(aout_t), 0));
+
+/* Do we have an a.out file ? */
+
+ switch(N_GETMAGIC(aout)) {
+ case NMAGIC:
+ if (strstr(__cli, "verbose") != 0)
+ swi(OS_Write0, IN(R0), "Kernel binary is NMAGIC a.out format\n\r");
+ kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
+ copysize = (unsigned int)(aout.a_text + aout.a_data);
+ break;
+ case OMAGIC:
+ if (strstr(__cli, "verbose") != 0)
+ swi(OS_Write0, IN(R0), "Kernel binary is OMAGIC a.out format\n\r");
+ kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
+ copysize = (unsigned int)(aout.a_text + aout.a_data);
+ break;
+ case ZMAGIC:
+ if (strstr(__cli, "verbose") != 0)
+ swi(OS_Write0, IN(R0), "Kernel binary is ZMAGIC a.out format\n\r");
+ kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss);
+ copysize = (unsigned int)(aout.a_text + aout.a_data);
+ break;
+ default:
+ if (strstr(__cli, "verbose") != 0)
+ swi(OS_Write0, IN(R0), "Kernel binary is AIF format\n\r");
+ kernelsize = filesize;
+ copysize = filesize;
+ break;
+ }
+
+/* Give ourselves 16K of spare space and round off to a page */
+
+/*
+ * This is messy. We should read the memory info first, but I have not
+ * changed things yet. This is part of the hack to support a.out files
+ * as well
+ */
+
+ kernelsize = (kernelsize + 0x4000) & ~(bootconfig.pagesize-1);
+
+/* Set the virtual address of the kernel in the bootconfig structure */
+
+ bootconfig.kernvirtualbase = KERNBASE;
+ bootconfig.kernsize = kernelsize;
+ bootconfig.argvirtualbase = bootconfig.kernvirtualbase
+ + bootconfig.kernsize;
+ bootconfig.argsize = bootconfig.pagesize;
+ bootconfig.scratchvirtualbase = bootconfig.argvirtualbase
+ + bootconfig.argsize;
+ bootconfig.scratchsize = SCRATCHSIZE;
+
+ kernelsize += bootconfig.argsize;
+
+ kernelsize += bootconfig.scratchsize;
+
+/* Verbose info to the user. This is mainly debugging */
+
+ if (strstr(__cli, "verbose") != 0)
+ {
+ uprintf("filesize = %08x\n\r", filesize);
+ uprintf("bootconfig.kernvirtualbase = %08x\n\r",
+ bootconfig.kernvirtualbase);
+ uprintf("bootconfig.kernsize = %08x\n\r", bootconfig.kernsize);
+ uprintf("bootconfig.argvirtualbase = %08x\n\r",
+ bootconfig.argvirtualbase);
+ uprintf("bootconfig.argsize = %08x\n\r", bootconfig.argsize);
+ uprintf("bootconfig.scratchvirtualbase = %08x\n\r",
+ bootconfig.scratchvirtualbase);
+ uprintf("bootconfig.scratchsize = %08x\n\r", bootconfig.scratchsize);
+ uprintf("kernelsize = %08x\n\r", kernelsize);
+ uprintf("copysize = %08x\n\r", copysize);
+ }
+
+# ifdef USE_MODULEAREA
+
+/* Allocate memory in module area to hold the data we are loading */
+
+ fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, filesize, &buffer));
+
+# else
+
+/* Allocate memory to hold the data we are loading */
+
+ swix(OS_DynamicArea, IN(R0|R1), 1, LOADAREA);
+
+ fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0,
+ LOADAREA, filesize, -1, 0x80, filesize, 0, 0, "Kate Data", &buffer));
+
+# endif
+
+/* Load the appropriate part depending on the file type */
+
+ switch (N_GETMAGIC(aout)) {
+ case OMAGIC:
+ case NMAGIC:
+ swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, buffer,
+ filesize, sizeof(aout_t));
+ break;
+ case ZMAGIC:
+ default:
+ swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, buffer,
+ filesize, 0);
+ break;
+ }
+
+/* Close the file */
+
+ fatal(swix(OS_Find, IN(R0|R1), 0, filehandle));
+
+
+/* This is redundant at the moment */
+
+ swix(OS_DynamicArea, IN(R0|R1), 1, KERNAREA);
+
+ fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8), 0,
+ KERNAREA, 0, KERNBASE, 0x80, 0x1000, 0, 0, "Kate Kernel"));
+
+/* Shutdown RiscOS cleanly ... */
+
+/* Close all open files and shutdown filing systems */
+
+ swix(OS_FSControl, IN(R0), 23);
+
+/* Issue a pre-reset service call to reset the podules */
+
+ swix(OS_ServiceCall, IN(R1), 0x45);
+
+/* Kill the etherH module to avoid locks up on reboot */
+
+ swix(OS_Module, IN(R0|R1), 4, "EtherH");
+
+/* More user information describing the memory found */
+
+ if (strstr(__cli, "verbose") != 0)
+ {
+ uprintf("DRAM bank 0a = %08x %08x\n\r", bootconfig.dram[0].address,
+ bootconfig.dram[0].pages * bootconfig.pagesize);
+ uprintf("DRAM bank 0b = %08x %08x\n\r", bootconfig.dram[1].address,
+ bootconfig.dram[1].pages * bootconfig.pagesize);
+ uprintf("DRAM bank 1a = %08x %08x\n\r", bootconfig.dram[2].address,
+ bootconfig.dram[2].pages * bootconfig.pagesize);
+ uprintf("DRAM bank 1b = %08x %08x\n\r", bootconfig.dram[3].address,
+ bootconfig.dram[3].pages * bootconfig.pagesize);
+ uprintf("VRAM bank 0 = %08x %08x\n\r", bootconfig.vram[0].address,
+ bootconfig.vram[0].pages * bootconfig.pagesize);
+ }
+
+/* Hack for 2 Meg VRAM until the new console code is in place */
+
+/* if (strstr(__cli, "vramhack") != 0)
+ {
+ bootconfig.display_size /= 1;
+ bootconfig.vram[0].pages /= 2;
+
+ uprintf("VRAM bank 0 = %08x %08x\n\r", bootconfig.vram[0].address,
+ bootconfig.vram[0].pages * bootconfig.pagesize);
+ }*/
+
+/* Jump to SVC26 mode - remember we have no local vars now ! */
+
+ EnterOS();
+
+/* Find the number of the upper most bank of DRAM available */
+
+ loop = 3;
+ while (bootconfig.dram[loop].address == 0)
+ --loop;
+
+/* Allocate the physical addresses for the kernel in this bank */
+
+ physical = bootconfig.dram[loop].address - kernelsize
+ + bootconfig.dram[loop].pages * bootconfig.pagesize;
+ bootconfig.kernphysicalbase = physical;
+ bootconfig.argphysicalbase = bootconfig.kernphysicalbase
+ + bootconfig.kernsize;
+ bootconfig.scratchphysicalbase = bootconfig.argphysicalbase
+ + bootconfig.argsize;
+
+/* Yet more debugging info */
+
+ if (strstr(__cli, "verbose") != 0)
+ {
+ uprintf("buffer = %08x\n\r", buffer);
+ uprintf("physical = %08x\n\r", physical);
+ uprintf("bootconfig.kernphysicalbase = %08x\n\r",
+ bootconfig.kernphysicalbase);
+ uprintf("bootconfig.argphysicalbase = %08x\n\r",
+ bootconfig.argphysicalbase);
+ uprintf("bootconfig.scratchphysicalbase = %08x\n\r",
+ bootconfig.scratchphysicalbase);
+ }
+
+/*
+ * Ok just check to see if anything is mapped where we are about to map
+ * the kernel.
+ */
+
+/*
+ for (logical = KERNBASE; logical < KERNBASE + kernelsize;
+ logical += bootconfig.pagesize)
+ {
+ if (ReadWord(0x02c00000 + (logical >> 10) & 0xfffffffc) != 0)
+ {
+ uprintf("Error: Memory required for RiscBSD boot not available\n\r");
+ return(0);
+ }
+ }
+*/
+/* Get out clause */
+
+ if (strstr(__cli, "noboot") != 0)
+ {
+ ExitOS();
+ return(0);
+ }
+
+/*
+ * Hook the physical pages to the required virtual address directly by
+ * writing into RiscOS's page tables. This should be done via a
+ * dynamic area handler but I cannot get it to work as documented.
+ */
+
+ for (logical = KERNBASE; logical < KERNBASE + kernelsize;
+ logical += bootconfig.pagesize)
+ {
+ WriteWord(0x02c00000 + (logical >> 10) & 0xfffffffc,
+ 0x00000ffe | (physical & 0xfffff000));
+ physical += bootconfig.pagesize;
+ }
+
+/* Map the IO up high so we can get at it */
+
+ WriteWord(0x02c0c000 + (0xf6000000 >> 18) & 0xfffffffc,
+ 0x00000412 | (0x03200000 & 0xfffff000));
+ WriteWord(0x02c0c000 + (0xf6100000 >> 18) & 0xfffffffc,
+ 0x00000412 | (0x03400000 & 0xfffff000));
+
+ memset((char *)bootconfig.display_start, 0xcc, 0x4000);
+
+/* Disable IRQ and FIQ interrupts */
+
+ SetCPSR(I32_bit | F32_bit, I32_bit | F32_bit);
+
+ memset((char *)bootconfig.display_start + 0x4000, 0x55, 0x4000);
+
+ memcpy((char *)bootconfig.argvirtualbase, __cli, bootconfig.argsize);
+
+ memset((char *)bootconfig.display_start + 0x8000, 0x80, 0x4000);
+
+ memset((char *)bootconfig.argvirtualbase, SCRATCHSIZE, 0);
+
+ memset((char *)bootconfig.display_start + 0xC000, 0xbb, 0x4000);
+
+ memcpy((char *)bootconfig.kernvirtualbase, buffer, copysize);
+
+ memset((char *)bootconfig.display_start + 0x10000, 0xaa, 0x4000);
+
+/* Real late debugging get out clause */
+
+ if (strstr(__cli, "nearboot") != 0)
+ {
+ SetCPSR(I32_bit | F32_bit, 0);
+ ExitOS();
+ return(0);
+ }
+
+/* Punch into SVC32 mode */
+
+ SVC32();
+
+/* Point of no return */
+
+ switch (N_GETMAGIC(aout)) {
+ case OMAGIC:
+ case NMAGIC:
+ case ZMAGIC:
+ _bsdboot(&bootconfig, (unsigned int)aout.a_entry);
+ break;
+ default:
+ _bsdboot(&bootconfig, KERNBASE);
+ break;
+ }
+
+ return(0);
+ }
+
+
+/* Report an error */
+
+void fatal(struct Error *error)
+ {
+ if (error)
+ {
+ swi(OS_GenerateError, IN(R0), error);
+ }
+ }
+
+
+/* Locate all the blocks of memory in the system */
+
+unsigned char *locate_memory_blocks(void)
+ {
+ int loop;
+ int page;
+ int currentpage;
+ int currentpages;
+ int currentaddr;
+ unsigned char *table;
+ unsigned int pagesize;
+ unsigned int tablesize;
+ int dramblocks = 0;
+ int vramblocks = 0;
+
+/* Get table size and page size */
+
+ fatal(swix(OS_Memory, IN(R0)|OUT(R1|R2), 6, &tablesize, &pagesize));
+
+/* Allocate memory for table */
+
+/*# ifdef USE_MODULEAREA*/
+
+ fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, tablesize, &table));
+
+/*# else*/
+
+/* Allocate memory to hold the data we are loading */
+
+/* swix(OS_DynamicArea, IN(R0|R1), 1, TABLEAREA);
+
+ fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0,
+ TABLEAREA, tablesize, -1, 0x80, tablesize, 0, 0, "Kate Table", &table));
+
+# endif*/
+
+
+/* read the table */
+
+ fatal(swix(OS_Memory, IN(R0|R1), 7, table));
+
+/* Loop round locating all the valid blocks of memory */
+
+ currentpage = -1;
+
+ for (loop = 0; loop < tablesize * 2; ++loop)
+ {
+ page = table[loop / 2];
+ if (loop % 2)
+ page = page >> 4;
+
+ page = page & 0x07;
+
+ if (page != currentpage)
+ {
+ switch (currentpage)
+ {
+ case 1:
+ bootconfig.dram[dramblocks].address = currentaddr * pagesize;
+ bootconfig.dram[dramblocks].pages = currentpages;
+ ++dramblocks;
+ break;
+
+ case 2:
+ bootconfig.vram[vramblocks].address = currentaddr * pagesize;
+ bootconfig.vram[vramblocks].pages = currentpages;
+ ++vramblocks;
+ break;
+
+ default :
+ break;
+ }
+
+ currentpage = page;
+ currentaddr = loop;
+ currentpages = 0;
+ }
+ ++currentpages;
+ }
+
+/* Get the number of dram and vram pages */
+
+ fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000108, &bootconfig.drampages));
+ fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000208, &bootconfig.vrampages));
+
+/* Fill in more bootconfig parameters */
+
+ bootconfig.pagesize = pagesize;
+
+ bootconfig.dramblocks = dramblocks;
+ bootconfig.vramblocks = vramblocks;
+
+ return(table);
+ }
+
+
+/* printf ... */
+
+void uprintf(char *formattoken, ...)
+ {
+ va_list ap;
+ char temp[1024];
+
+ temp[0] = '\0';
+
+ va_start(ap, formattoken);
+ vsprintf(temp, formattoken, ap);
+ va_end(ap);
+
+ swi(OS_Write0, IN(R0), temp);
+ }
+
+/* End of bsdbooter.c */
--- /dev/null
+/* $NetBSD: enteros.S,v 1.1 1996/01/31 23:18:11 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * enteros.s
+ *
+ * Created : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/library/enteros.s
+ *
+ * $Id: enteros.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $
+ */
+
+#include "regs.h"
+
+#define OS_EnterOS 0x0016
+
+/*
+ * Enters SVC26 mode
+ */
+
+ .text
+ .global _EnterOS
+_EnterOS:
+ mov r1, lr
+ swi OS_EnterOS
+
+ mov r0, pc
+ mov pc, r1
+
--- /dev/null
+/* $NetBSD: exit.S,v 1.1 1996/01/31 23:18:14 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * _exit.s
+ *
+ * Boot loader exit point
+ *
+ * Created : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/boot/_exit.s
+ *
+ * $Id: exit.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+#include "regs.h"
+
+#define OS_Exit 0x00000011
+
+ .text
+ .global ___exit
+___exit:
+ mov r2, r0
+ ldr r1, [pc, #Lexit_word - . - 8]
+ mov r0, #0x00000000
+ swi OS_Exit
+
+Lexit_word:
+ .word 0x58454241
--- /dev/null
+/* $NetBSD: exitos.S,v 1.1 1996/01/31 23:18:16 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * exitos.s
+ *
+ *
+ *
+ * Created : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/library/exitos.s
+ *
+ * $Id: exitos.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ *
+ */
+
+#include "regs.h"
+
+/*
+ * Returns from SVC26 mode to USR26 mode
+ */
+
+ .text
+ .global _ExitOS
+_ExitOS:
+ mov r2, lr
+ bic r2, r2, #0x00000003
+ movs pc, r2
--- /dev/null
+/* $NetBSD: memcpy.S,v 1.1 1996/01/31 23:18:17 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * memset.S
+ *
+ * optimized memset function
+ *
+ * Created : 16/05/95
+ * Last updated : 16/05/95
+ *
+ * $Id: memcpy.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+ .global _bcopy
+ .global _ovbcopy
+
+_bcopy:
+_ovbcopy:
+ teq r2, #0x00000000
+ moveq r0, #0x00000000
+ moveq pc, lr
+ cmp r0, r1
+ blt bcopy_back
+
+bcopy_loop:
+ ldrb r3, [r0], #0x0001
+ strb r3, [r1], #0x0001
+ subs r2, r2, #0x00000001
+ bne bcopy_loop
+
+ mov pc, r14
+
+bcopy_back:
+ add r0, r0, r2
+ add r1, r1, r2
+
+bcopy_bloop:
+ ldrb r3, [r0, #-0x0001]!
+ strb r3, [r1, #-0x0001]!
+ subs r2, r2, #0x00000001
+ bne bcopy_bloop
+
+ mov pc, r14
+
+
+ .global _memcpy
+
+_memcpy:
+ teq r2, #0x00000000
+ moveq r0, #0x00000000
+ moveq pc, lr
+ cmp r1, r0
+ blt memcpy_back
+
+memcpy_loop:
+ ldrb r3, [r1], #0x0001
+ strb r3, [r0], #0x0001
+ subs r2, r2, #0x00000001
+ bne memcpy_loop
+
+ mov pc, r14
+
+memcpy_back:
+ add r0, r0, r2
+ add r1, r1, r2
+
+memcpy_bloop:
+ ldrb r3, [r1, #-0x0001]!
+ strb r3, [r0, #-0x0001]!
+ subs r2, r2, #0x00000001
+ bne memcpy_bloop
+
+ mov pc, r14
--- /dev/null
+/* $NetBSD: memset.S,v 1.1 1996/01/31 23:18:19 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * memset.S
+ *
+ * optimized memset function
+ *
+ * Created : 16/05/95
+ * Last updated : 16/05/95
+ *
+ * $Id: memset.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+
+ .global _memset
+
+/* Sets a block of memory to the specified value
+ *
+ * r0 - address
+ * r1 - byte to write
+ * r2 - number of bytes to write
+ */
+
+_memset:
+ and r1, r1, #0x000000ff /* We write bytes */
+
+ cmp r2, #0x00000004 /* Do we have less than 4 bytes */
+ blt memset_lessthanfour
+
+/* Ok first we will word align the address */
+
+ ands r3, r0, #0x00000003 /* Get the bottom two bits */
+ beq memset_addraligned /* The address is word aligned */
+
+ rsb r3, r3, #0x00000004
+ sub r2, r2, r3
+ cmp r3, #0x00000002
+ strb r1, [r0], #0x0001 /* Set 1 byte */
+ strgeb r1, [r0], #0x0001 /* Set another byte */
+ strgtb r1, [r0], #0x0001 /* and a third */
+
+ cmp r2, #0x00000004
+ blt memset_lessthanfour
+
+/* Now we must be word aligned */
+
+memset_addraligned:
+
+ orr r3, r1, r1, lsl #8 /* Repeat the byte into a word */
+ orr r3, r3, r3, lsl #16
+
+/* We know we have at least 4 bytes ... */
+
+ cmp r2, #0x00000020 /* If less than 32 then use words */
+ blt memset_lessthan32
+
+/* We have at least 32 so lets use quad words */
+
+ stmfd sp!, {r4-r6} /* Store registers */
+ mov r4, r3 /* Duplicate data */
+ mov r5, r3
+ mov r6, r3
+
+memset_loop16:
+ stmia r0!, {r3-r6} /* Store 16 bytes */
+ sub r2, r2, #0x00000010 /* Adjust count */
+ cmp r2, #0x00000010 /* Still got at least 16 bytes ? */
+ bgt memset_loop16
+
+ ldmfd sp!, {r4-r6} /* Restore registers */
+
+/* Do we need to set some words as well ? */
+
+ cmp r2, #0x00000004
+ blt memset_lessthanfour
+
+/* Have either less than 16 or less than 32 depending on route taken */
+
+memset_lessthan32:
+
+/* We have at least 4 bytes so copy as words */
+
+memset_loop4:
+ str r3, [r0], #0x0004
+ sub r2, r2, #0x0004
+ cmp r2, #0x00000004
+ bge memset_loop4
+
+memset_lessthanfour:
+ cmp r2, #0x00000000
+ moveq pc, lr /* Zero length so exit */
+
+ cmp r2, #0x00000002
+ strb r1, [r0], #0x0001 /* Set 1 byte */
+ strgeb r1, [r0], #0x0001 /* Set another byte */
+ strgtb r1, [r0], #0x0001 /* and a third */
+
+ mov pc, lr /* Exit */
--- /dev/null
+/* $NetBSD: regs.h,v 1.1 1996/01/31 23:18:21 mark Exp $ */
+
+/* Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES * LOSS OF USE, DATA, OR PROFITS * OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * regs.h
+ *
+ * Assembly register definitions
+ *
+ * Created : 14/01/96
+ * Last updated : 14/01/96
+ *
+ * $Id: regs.h,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+fp .req r11
+sl .req r12
+sp .req r13
+lr .req r14
+pc .req r15
--- /dev/null
+#!/bin/sh
+# $NetBSD: rmaouthdr,v 1.1 1996/01/31 23:18:23 mark Exp $
+
+dd if=$1 of=$2 ibs=32 skip=1 obs=1024b
--- /dev/null
+/* $NetBSD: setcpsr.S,v 1.1 1996/01/31 23:18:27 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * setcpsr.S
+ *
+ * Miscellaneous routines to play with the CPSR register
+ *
+ * Eventually this routine can be inline assembly.
+ *
+ * Created : 12/09/94
+ * Last updated : 28/05/95
+ *
+ * Based of kate/display/setcpsr.s
+ *
+ * $Id: setcpsr.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+fp .req r11
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+
+ .global _SetCPSR
+
+/* Sets and clears bits in the CPSR register
+ *
+ * r0 - bic mask
+ * r1 - eor mask
+ */
+
+_SetCPSR:
+/* mov ip, sp
+ stmfd sp!, {fp, ip, lr, pc}
+ sub fp, ip, #4*/
+
+ mrs r3, cpsr_all /* Set the CPSR */
+ bic r2, r3, r0
+ eor r2, r2, r1
+ msr cpsr_all, r2
+
+ mov r0, r3 /* Return the old CPSR */
+
+/* ldmea fp, {fp, sp, pc}*/
+ mov pc, lr
+
+ .global _GetCPSR
+
+/* Gets the CPSR register
+ *
+ * Returns the CPSR in r0
+ */
+
+_GetCPSR:
+ mrs r0, cpsr_all /* Get the CPSR */
+
+ mov pc, lr
+
--- /dev/null
+/* $NetBSD: start.S,v 1.1 1996/01/31 23:18:30 mark Exp $ */
+
+/* Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES * LOSS OF USE, DATA, OR PROFITS * OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * _main.s
+ *
+ * Kernel entry/exit code
+ *
+ * Created : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/boot/_main.s
+ *
+ * $Id: start.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+#include "regs.h"
+
+ .global start
+start:
+ b ___main
--- /dev/null
+/* $NetBSD: strstr.c,v 1.1 1996/01/31 23:18:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: strstr.c,v 1.4 1995/06/15 00:08:43 jtc Exp
+ *
+ * $Id: strstr.c,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/*
+ * Find the first occurrence of find in s.
+ */
+
+char *
+strstr(s, find)
+ register const char *s, *find;
+{
+ register char c, sc;
+ register size_t len;
+
+ if ((c = *find++) != 0) {
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return (NULL);
+ } while (sc != c);
+ } while (strncmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+
+/* End of strstr.c */
--- /dev/null
+/* $NetBSD: svc32.S,v 1.1 1996/01/31 23:18:38 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1955 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES * LOSS OF USE, DATA, OR PROFITS * OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * svc32.s
+ *
+ * Created : 12/09/94
+ * Last updated : 12/09/94
+ *
+ * Based on kate/library/svc32.s
+ *
+ * $Id: svc32.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $
+ */
+
+#include "regs.h"
+#include <machine/cpu.h>
+
+/*
+ * Switches from SVC26 mode to SVC32 mode
+ */
+
+ .text
+ .global _SVC32
+_SVC32:
+ mrs r1, cpsr_all
+ bic r1, r1, #(PSR_MODE)
+ orr r1, r1, #(PSR_SVC32_MODE)
+ msr cpsr_all, r1
+
+ bic lr, lr, #0xfc000000
+
+ mov pc, lr
--- /dev/null
+/*
+ Title: Swi numbers for RiscOs
+ Copyright (C) 1989, Acorn Computers Ltd., Cambridge, England
+ $Revision: 1.1.1.1 $ SWI_LIST 1.00 02-May-89 (Program generated)
+*/
+
+#ifndef __swis_h
+#define __swis_h
+
+#define XOS_Bit 0x020000
+
+#define OS_WriteI 0x000100
+
+#define OS_WriteC 0x000000
+#define OS_WriteS 0x000001
+#define OS_Write0 0x000002
+#define OS_NewLine 0x000003
+#define OS_ReadC 0x000004
+#define OS_CLI 0x000005
+#define OS_Byte 0x000006
+#define OS_Word 0x000007
+#define OS_File 0x000008
+#define OS_Args 0x000009
+#define OS_BGet 0x00000a
+#define OS_BPut 0x00000b
+#define OS_GBPB 0x00000c
+#define OS_Find 0x00000d
+#define OS_ReadLine 0x00000e
+#define OS_Control 0x00000f
+#define OS_GetEnv 0x000010
+#define OS_Exit 0x000011
+#define OS_SetEnv 0x000012
+#define OS_IntOn 0x000013
+#define OS_IntOff 0x000014
+#define OS_CallBack 0x000015
+#define OS_EnterOS 0x000016
+#define OS_BreakPt 0x000017
+#define OS_BreakCtrl 0x000018
+#define OS_UnusedSWI 0x000019
+#define OS_UpdateMEMC 0x00001a
+#define OS_SetCallBack 0x00001b
+#define OS_Mouse 0x00001c
+#define OS_Heap 0x00001d
+#define OS_Module 0x00001e
+#define OS_Claim 0x00001f
+#define OS_Release 0x000020
+#define OS_ReadUnsigned 0x000021
+#define OS_GenerateEvent 0x000022
+#define OS_ReadVarVal 0x000023
+#define OS_SetVarVal 0x000024
+#define OS_GSInit 0x000025
+#define OS_GSRead 0x000026
+#define OS_GSTrans 0x000027
+#define OS_BinaryToDecimal 0x000028
+#define OS_FSControl 0x000029
+#define OS_ChangeDynamicArea 0x00002a
+#define OS_GenerateError 0x00002b
+#define OS_ReadEscapeState 0x00002c
+#define OS_EvaluateExpression 0x00002d
+#define OS_SpriteOp 0x00002e
+#define OS_ReadPalette 0x00002f
+#define OS_ServiceCall 0x000030
+#define OS_ReadVduVariables 0x000031
+#define OS_ReadPoint 0x000032
+#define OS_UpCall 0x000033
+#define OS_CallAVector 0x000034
+#define OS_ReadModeVariable 0x000035
+#define OS_RemoveCursors 0x000036
+#define OS_RestoreCursors 0x000037
+#define OS_SWINumberToString 0x000038
+#define OS_SWINumberFromString 0x000039
+#define OS_ValidateAddress 0x00003a
+#define OS_CallAfter 0x00003b
+#define OS_CallEvery 0x00003c
+#define OS_RemoveTickerEvent 0x00003d
+#define OS_InstallKeyHandler 0x00003e
+#define OS_CheckModeValid 0x00003f
+#define OS_ChangeEnvironment 0x000040
+#define OS_ClaimScreenMemory 0x000041
+#define OS_ReadMonotonicTime 0x000042
+#define OS_SubstituteArgs 0x000043
+#define OS_PrettyPrint 0x000044
+#define OS_Plot 0x000045
+#define OS_WriteN 0x000046
+#define OS_AddToVector 0x000047
+#define OS_WriteEnv 0x000048
+#define OS_ReadArgs 0x000049
+#define OS_ReadRAMFsLimits 0x00004a
+#define OS_ClaimDeviceVector 0x00004b
+#define OS_ReleaseDeviceVector 0x00004c
+#define OS_DelinkApplication 0x00004d
+#define OS_RelinkApplication 0x00004e
+#define OS_HeapSort 0x00004f
+#define OS_ExitAndDie 0x000050
+#define OS_ReadMemMapInfo 0x000051
+#define OS_ReadMemMapEntries 0x000052
+#define OS_SetMemMapEntries 0x000053
+#define OS_AddCallBack 0x000054
+#define OS_ReadDefaultHandler 0x000055
+#define OS_SetECFOrigin 0x000056
+#define OS_SerialOp 0x000057
+#define OS_ReadSysInfo 0x000058
+#define OS_Confirm 0x000059
+#define OS_ChangedBox 0x00005a
+#define OS_CRC 0x00005b
+#define OS_ReadDynamicArea 0x00005c
+#define OS_PrintChar 0x00005d
+#define OS_ChangeRedirection 0x00005e
+#define OS_RemoveCallBack 0x00005f
+#define OS_FindMemMapEntries 0x000060
+#define OS_SetColour 0x000061
+#define OS_ConvertStandardDateAndTime 0x0000c0
+#define OS_ConvertDateAndTime 0x0000c1
+#define OS_ConvertHex1 0x0000d0
+#define OS_ConvertHex2 0x0000d1
+#define OS_ConvertHex4 0x0000d2
+#define OS_ConvertHex6 0x0000d3
+#define OS_ConvertHex8 0x0000d4
+#define OS_ConvertCardinal1 0x0000d5
+#define OS_ConvertCardinal2 0x0000d6
+#define OS_ConvertCardinal3 0x0000d7
+#define OS_ConvertCardinal4 0x0000d8
+#define OS_ConvertInteger1 0x0000d9
+#define OS_ConvertInteger2 0x0000da
+#define OS_ConvertInteger3 0x0000db
+#define OS_ConvertInteger4 0x0000dc
+#define OS_ConvertBinary1 0x0000dd
+#define OS_ConvertBinary2 0x0000de
+#define OS_ConvertBinary3 0x0000df
+#define OS_ConvertBinary4 0x0000e0
+#define OS_ConvertSpacedCardinal1 0x0000e1
+#define OS_ConvertSpacedCardinal2 0x0000e2
+#define OS_ConvertSpacedCardinal3 0x0000e3
+#define OS_ConvertSpacedCardinal4 0x0000e4
+#define OS_ConvertSpacedInteger1 0x0000e5
+#define OS_ConvertSpacedInteger2 0x0000e6
+#define OS_ConvertSpacedInteger3 0x0000e7
+#define OS_ConvertSpacedInteger4 0x0000e8
+#define OS_ConvertFixedNetStation 0x0000e9
+#define OS_ConvertNetStation 0x0000ea
+#define OS_ConvertFixedFileSize 0x0000eb
+#define OS_ConvertFileSize 0x0000ec
+#define IIC_Control 0x000240
+#define Cache_Control 0x000280
+#define Cache_Cacheable 0x000281
+#define Cache_Updateable 0x000282
+#define Cache_Disruptive 0x000283
+#define Cache_Flush 0x000284
+#define Trace_R0 0x00bf00
+#define Trace_R1 0x00bf01
+#define Trace_R2 0x00bf02
+#define Trace_R3 0x00bf03
+#define Trace_R4 0x00bf04
+#define Trace_R5 0x00bf05
+#define Trace_R6 0x00bf06
+#define Trace_R7 0x00bf07
+#define Trace_R8 0x00bf08
+#define Trace_R9 0x00bf09
+#define Trace_R10 0x00bf0a
+#define Trace_R11 0x00bf0b
+#define Trace_R12 0x00bf0c
+#define Trace_R13 0x00bf0d
+#define Trace_R14 0x00bf0e
+#define Trace_R15 0x00bf0f
+#define Trace_Regs 0x00bf10
+#define Trace_WriteC 0x00bf11
+#define Trace_NewLine 0x00bf12
+#define Trace_WriteS 0x00bf13
+#define Trace_Write0 0x00bf14
+#define Font_CacheAddr 0x040080
+#define Font_FindFont 0x040081
+#define Font_LoseFont 0x040082
+#define Font_ReadDefn 0x040083
+#define Font_ReadInfo 0x040084
+#define Font_StringWidth 0x040085
+#define Font_Paint 0x040086
+#define Font_Caret 0x040087
+#define Font_ConverttoOS 0x040088
+#define Font_Converttopoints 0x040089
+#define Font_SetFont 0x04008a
+#define Font_CurrentFont 0x04008b
+#define Font_FutureFont 0x04008c
+#define Font_FindCaret 0x04008d
+#define Font_CharBBox 0x04008e
+#define Font_ReadScaleFactor 0x04008f
+#define Font_SetScaleFactor 0x040090
+#define Font_ListFonts 0x040091
+#define Font_SetFontColours 0x040092
+#define Font_SetPalette 0x040093
+#define Font_ReadThresholds 0x040094
+#define Font_SetThresholds 0x040095
+#define Font_FindCaretJ 0x040096
+#define Font_StringBBox 0x040097
+#define Font_ReadColourTable 0x040098
+#define Font_MakeBitmap 0x040099
+#define Font_UnCacheFile 0x04009a
+#define Font_SetFontMax 0x04009b
+#define Font_ReadFontMax 0x04009c
+#define Font_ReadFontPrefix 0x04009d
+#define Font_SwitchOutputToBuffer 0x04009e
+#define Font_ReadFontMetrics 0x04009f
+#define Font_DecodeMenu 0x0400a0
+#define Font_ScanString 0x0400a1
+#define Font_SetColourTable 0x0400a2
+#define Font_CurrentRGB 0x0400a3
+#define Font_FutureRGB 0x0400a4
+#define Font_ReadEncodingFilename 0x0400a5
+#define Font_FindField 0x0400a6
+#define Font_ApplyFields 0x0400a7
+#define Font_LookupFont 0x0400a8
+#define Wimp_Initialise 0x0400c0
+#define Wimp_CreateWindow 0x0400c1
+#define Wimp_CreateIcon 0x0400c2
+#define Wimp_DeleteWindow 0x0400c3
+#define Wimp_DeleteIcon 0x0400c4
+#define Wimp_OpenWindow 0x0400c5
+#define Wimp_CloseWindow 0x0400c6
+#define Wimp_Poll 0x0400c7
+#define Wimp_RedrawWindow 0x0400c8
+#define Wimp_UpdateWindow 0x0400c9
+#define Wimp_GetRectangle 0x0400ca
+#define Wimp_GetWindowState 0x0400cb
+#define Wimp_GetWindowInfo 0x0400cc
+#define Wimp_SetIconState 0x0400cd
+#define Wimp_GetIconState 0x0400ce
+#define Wimp_GetPointerInfo 0x0400cf
+#define Wimp_DragBox 0x0400d0
+#define Wimp_ForceRedraw 0x0400d1
+#define Wimp_SetCaretPosition 0x0400d2
+#define Wimp_GetCaretPosition 0x0400d3
+#define Wimp_CreateMenu 0x0400d4
+#define Wimp_DecodeMenu 0x0400d5
+#define Wimp_WhichIcon 0x0400d6
+#define Wimp_SetExtent 0x0400d7
+#define Wimp_SetPointerShape 0x0400d8
+#define Wimp_OpenTemplate 0x0400d9
+#define Wimp_CloseTemplate 0x0400da
+#define Wimp_LoadTemplate 0x0400db
+#define Wimp_ProcessKey 0x0400dc
+#define Wimp_CloseDown 0x0400dd
+#define Wimp_StartTask 0x0400de
+#define Wimp_ReportError 0x0400df
+#define Wimp_GetWindowOutline 0x0400e0
+#define Wimp_PollIdle 0x0400e1
+#define Wimp_PlotIcon 0x0400e2
+#define Wimp_SetMode 0x0400e3
+#define Wimp_SetPalette 0x0400e4
+#define Wimp_ReadPalette 0x0400e5
+#define Wimp_SetColour 0x0400e6
+#define Wimp_SendMessage 0x0400e7
+#define Wimp_CreateSubMenu 0x0400e8
+#define Wimp_SpriteOp 0x0400e9
+#define Wimp_BaseOfSprites 0x0400ea
+#define Wimp_BlockCopy 0x0400eb
+#define Wimp_SlotSize 0x0400ec
+#define Wimp_ReadPixTrans 0x0400ed
+#define Wimp_ClaimFreeMemory 0x0400ee
+#define Wimp_CommandWindow 0x0400ef
+#define Wimp_TextColour 0x0400f0
+#define Wimp_TransferBlock 0x0400f1
+#define Wimp_ReadSysInfo 0x0400f2
+#define Wimp_SetFontColours 0x0400f3
+#define Wimp_GetMenuState 0x0400f4
+#define Wimp_RegisterFilter 0x0400f5
+#define Wimp_AddMessages 0x0400f6
+#define Wimp_RemoveMessages 0x0400f7
+#define Wimp_SetColourMapping 0x0400f8
+#define Sound_Configure 0x040140
+#define Sound_Enable 0x040141
+#define Sound_Stereo 0x040142
+#define Sound_Speaker 0x040143
+#define Sound_Volume 0x040180
+#define Sound_SoundLog 0x040181
+#define Sound_LogScale 0x040182
+#define Sound_InstallVoice 0x040183
+#define Sound_RemoveVoice 0x040184
+#define Sound_AttachVoice 0x040185
+#define Sound_ControlPacked 0x040186
+#define Sound_Tuning 0x040187
+#define Sound_Pitch 0x040188
+#define Sound_Control 0x040189
+#define Sound_AttachNamedVoice 0x04018a
+#define Sound_ReadControlBlock 0x04018b
+#define Sound_WriteControlBlock 0x04018c
+#define Sound_QInit 0x0401c0
+#define Sound_QSchedule 0x0401c1
+#define Sound_QRemove 0x0401c2
+#define Sound_QFree 0x0401c3
+#define Sound_QSDispatch 0x0401c4
+#define Sound_QTempo 0x0401c5
+#define Sound_QBeat 0x0401c6
+#define Sound_QInterface 0x0401c7
+#define ADFS_DiscOp 0x040240
+#define ADFS_HDC 0x040241
+#define ADFS_Drives 0x040242
+#define ADFS_FreeSpace 0x040243
+#define ADFS_Retries 0x040244
+#define ADFS_DescribeDisc 0x040245
+#define ADFS_VetFormat 0x040246
+#define ADFS_FlpProcessDCB 0x040247
+#define ADFS_ControllerType 0x040248
+#define ADFS_PowerControl 0x040249
+#define ADFS_SetIDEController 0x04024a
+#define ADFS_IDEUserOp 0x04024b
+#define ADFS_MiscOp 0x04024c
+#define ADFS_ECCSAndRetries 0x040250
+#define Podule_ReadID 0x040280
+#define Podule_ReadHeader 0x040281
+#define Podule_EnumerateChunks 0x040282
+#define Podule_ReadChunk 0x040283
+#define Podule_ReadBytes 0x040284
+#define Podule_WriteBytes 0x040285
+#define Podule_CallLoader 0x040286
+#define Podule_RawRead 0x040287
+#define Podule_RawWrite 0x040288
+#define Podule_HardwareAddress 0x040289
+#define Podule_EnumerateChunksWithInfo 0x04028a
+#define Podule_HardwareAddresses 0x04028b
+#define Podule_ReturnNumber 0x04028c
+#define PCEmMod_KeyEvent_Init 0x0402c0
+#define PCEmMod_KeyEvent_Info 0x0402c1
+#define PCEmMod_KeyEvent_Accept 0x0402c2
+#define PCEmMod_KeyEvent_Ignore 0x0402c3
+#define PCEmMod_KeyEvent_Check 0x0402c4
+#define PCEmMod_KeyEvent_Get 0x0402c5
+#define PCEmMod_KeyEvent_Put 0x0402c6
+#define PCEmMod_MicroTimer_Get 0x0402c7
+#define PCEmMod_PCEvent_Init 0x0402c8
+#define PCEmMod_PCEvent_Accept 0x0402c9
+#define PCEmMod_PCEvent_Ignore 0x0402ca
+#define PCEmMod_PCEvent_Check 0x0402cb
+#define PCEmMod_PCEvent_Get 0x0402cc
+#define PCEmMod_DelayFor 0x0402cd
+#define PCEmMod_CodeBase 0x0402ce
+#define PCEmMod_Profile_Init 0x0402cf
+#define PCEmMod_Profile_On 0x0402d0
+#define PCEmMod_Profile_Off 0x0402d1
+#define PCEmMod_Profile_Write 0x0402d2
+#define PCEmMod_InterceptMouse 0x0402d3
+#define PCEmMod_RestoreMouse 0x0402d4
+#define PCEmMod_ReadMouse 0x0402d5
+#define Debugger_Disassemble 0x040380
+#define SCSI_Version 0x0403c0
+#define SCSI_Initialise 0x0403c1
+#define SCSI_Control 0x0403c2
+#define SCSI_Op 0x0403c3
+#define SCSI_Status 0x0403c4
+#define SCSI_Reserve 0x0403c7
+#define SCSI_List 0x0403c8
+#define FPEmulator_Version 0x040480
+#define FileCore_DiscOp 0x040540
+#define FileCore_Create 0x040541
+#define FileCore_Drives 0x040542
+#define FileCore_FreeSpace 0x040543
+#define FileCore_FloppyStructure 0x040544
+#define FileCore_DescribeDisc 0x040545
+#define FileCore_DiscardReadSectorsCache 0x040546
+#define FileCore_DiscFormat 0x040547
+#define FileCore_LayoutStructure 0x040548
+#define FileCore_MiscOp 0x040549
+#define Shell_Create 0x0405c0
+#define Shell_Destroy 0x0405c1
+#define Hourglass_On 0x0406c0
+#define Hourglass_Off 0x0406c1
+#define Hourglass_Smash 0x0406c2
+#define Hourglass_Start 0x0406c3
+#define Hourglass_Percentage 0x0406c4
+#define Hourglass_LEDs 0x0406c5
+#define Hourglass_Colours 0x0406c6
+#define Draw_ProcessPath 0x040700
+#define Draw_ProcessPathFP 0x040701
+#define Draw_Fill 0x040702
+#define Draw_FillFP 0x040703
+#define Draw_Stroke 0x040704
+#define Draw_StrokeFP 0x040705
+#define Draw_StrokePath 0x040706
+#define Draw_StrokePathFP 0x040707
+#define Draw_FlattenPath 0x040708
+#define Draw_FlattenPathFP 0x040709
+#define Draw_TransformPath 0x04070a
+#define Draw_TransformPathFP 0x04070b
+#define ColourTrans_SelectTable 0x040740
+#define ColourTrans_SelectGCOLTable 0x040741
+#define ColourTrans_ReturnGCOL 0x040742
+#define ColourTrans_SetGCOL 0x040743
+#define ColourTrans_ReturnColourNumber 0x040744
+#define ColourTrans_ReturnGCOLForMode 0x040745
+#define ColourTrans_ReturnColourNumberForMode 0x040746
+#define ColourTrans_ReturnOppGCOL 0x040747
+#define ColourTrans_SetOppGCOL 0x040748
+#define ColourTrans_ReturnOppColourNumber 0x040749
+#define ColourTrans_ReturnOppGCOLForMode 0x04074a
+#define ColourTrans_ReturnOppColourNumberForMode 0x04074b
+#define ColourTrans_GCOLToColourNumber 0x04074c
+#define ColourTrans_ColourNumberToGCOL 0x04074d
+#define ColourTrans_ReturnFontColours 0x04074e
+#define ColourTrans_SetFontColours 0x04074f
+#define ColourTrans_InvalidateCache 0x040750
+#define ColourTrans_SetCalibration 0x040751
+#define ColourTrans_ReadCalibration 0x040752
+#define ColourTrans_ConvertDeviceColour 0x040753
+#define ColourTrans_ConvertDevicePalette 0x040754
+#define ColourTrans_ConvertRGBToCIE 0x040755
+#define ColourTrans_ConvertCIEToRGB 0x040756
+#define ColourTrans_WriteCalibrationToFile 0x040757
+#define ColourTrans_ConvertRGBToHSV 0x040758
+#define ColourTrans_ConvertHSVToRGB 0x040759
+#define ColourTrans_ConvertRGBToCMYK 0x04075a
+#define ColourTrans_ConvertCMYKToRGB 0x04075b
+#define ColourTrans_ReadPalette 0x04075c
+#define ColourTrans_WritePalette 0x04075d
+#define ColourTrans_SetColour 0x04075e
+#define ColourTrans_MiscOp 0x04075f
+#define ColourTrans_WriteLoadingsToFile 0x040760
+#define ColourTrans_SetTextColour 0x040761
+#define ColourTrans_SetOppTextColour 0x040762
+#define ColourTrans_GenerateTable 0x040763
+#define SCSIFS_DiscOp 0x040980
+#define SCSIFS_Drives 0x040982
+#define SCSIFS_FreeSpace 0x040983
+#define SCSIFS_DescribeDisc 0x040985
+#define SCSIFS_TestReady 0x040986
+#define Super_Sample90 0x040d80
+#define Super_Sample45 0x040d81
+#define FilerAction_SendSelectedDirectory 0x040f80
+#define FilerAction_SendSelectedFile 0x040f81
+#define FilerAction_SendStartOperation 0x040f82
+#define SCSI_LogVersion 0x041080
+#define SCSI_LogList 0x041081
+#define MessageTrans_FileInfo 0x041500
+#define MessageTrans_OpenFile 0x041501
+#define MessageTrans_Lookup 0x041502
+#define MessageTrans_MakeMenus 0x041503
+#define MessageTrans_CloseFile 0x041504
+#define MessageTrans_EnumerateTokens 0x041505
+#define MessageTrans_ErrorLookup 0x041506
+#define MessageTrans_GSLookup 0x041507
+#define MessageTrans_CopyError 0x041508
+#define PDumper_Info 0x041b00
+#define PDumper_Claim 0x041b01
+#define PDumper_Free 0x041b02
+#define PDumper_Find 0x041b03
+#define PDumper_StartJob 0x041b04
+#define PDumper_TidyJob 0x041b05
+#define PDumper_SetColour 0x041b06
+#define PDumper_PrepareStrip 0x041b07
+#define PDumper_LookupError 0x041b08
+#define PDumper_CopyFilename 0x041b09
+#define ResourceFS_RegisterFiles 0x041b40
+#define ResourceFS_DeregisterFiles 0x041b41
+#define DragASprite_Start 0x042400
+#define DragASprite_Stop 0x042401
+#define DDEUtils_Prefix 0x042580
+#define DDEUtils_SetCLSize 0x042581
+#define DDEUtils_SetCL 0x042582
+#define DDEUtils_GetCLSize 0x042583
+#define DDEUtils_GetCl 0x042584
+#define DDEUtils_ThrowbackRegister 0x042585
+#define DDEUtils_ThrowbackUnRegister 0x042586
+#define DDEUtils_ThrowbackStart 0x042587
+#define DDEUtils_ThrowbackSend 0x042588
+#define DDEUtils_ThrowbackEnd 0x042589
+#define Filter_RegisterPreFilter 0x042640
+#define Filter_RegisterPostFilter 0x042641
+#define Filter_DeRegisterPreFilter 0x042642
+#define Filter_DeRegisterPostFilter 0x042643
+#define TaskManager_TaskNameFromHandle 0x042680
+#define TaskManager_EnumerateTasks 0x042681
+#define TaskManager_Shutdown 0x042682
+#define Squash_Compress 0x042700
+#define Squash_Decompress 0x042701
+#define DeviceFS_Register 0x042740
+#define DeviceFS_Deregister 0x042741
+#define DeviceFS_RegisterObjects 0x042742
+#define DeviceFS_DeregisterObjects 0x042743
+#define DeviceFS_CallDevice 0x042744
+#define DeviceFS_Threshold 0x042745
+#define DeviceFS_ReceivedCharacter 0x042746
+#define DeviceFS_TransmitCharacter 0x042747
+#define Impulse_Initialise 0x0428c0
+#define Impulse_Decode 0x0428c1
+#define Impulse_SendMessage 0x0428c2
+#define Impulse_TransmitData 0x0428c3
+#define Impulse_FetchData 0x0428c4
+#define Impulse_CloseDown 0x0428c5
+#define Impulse_DeferReply 0x0428c6
+#define Buffer_Create 0x042940
+#define Buffer_Remove 0x042941
+#define Buffer_Register 0x042942
+#define Buffer_Deregister 0x042943
+#define Buffer_ModifyFlags 0x042944
+#define Buffer_LinkDevice 0x042945
+#define Buffer_UnlinkDevice 0x042946
+#define Buffer_GetInfo 0x042947
+#define Buffer_Threshold 0x042948
+#define BASICTrans_HELP 0x042c80
+#define BASICTrans_Error 0x042c81
+#define BASICTrans_Message 0x042c82
+#define Parallel_HardwareAddress 0x042ec0
+#define Parallel_Op 0x042ec1
+#define Territory_Number 0x043040
+#define Territory_Register 0x043041
+#define Territory_Deregister 0x043042
+#define Territory_NumberToName 0x043043
+#define Territory_Exists 0x043044
+#define Territory_AlphabetNumberToName 0x043045
+#define Territory_SelectAlphabet 0x043046
+#define Territory_SetTime 0x043047
+#define Territory_ReadCurrentTimeZone 0x043048
+#define Territory_ConvertTimeToUTCOrdinals 0x043049
+#define Territory_ReadTimeZones 0x04304a
+#define Territory_ConvertDateAndTime 0x04304b
+#define Territory_ConvertStandardDateAndTime 0x04304c
+#define Territory_ConvertStandardDate 0x04304d
+#define Territory_ConvertStandardTime 0x04304e
+#define Territory_ConvertTimeToOrdinals 0x04304f
+#define Territory_ConvertTimeStringToOrdinals 0x043050
+#define Territory_ConvertOrdinalsToTime 0x043051
+#define Territory_Alphabet 0x043052
+#define Territory_AlphabetIdentifier 0x043053
+#define Territory_SelectKeyboardHandler 0x043054
+#define Territory_WriteDirection 0x043055
+#define Territory_CharacterPropertyTable 0x043056
+#define Territory_LowerCaseTable 0x043057
+#define Territory_UpperCaseTable 0x043058
+#define Territory_ControlTable 0x043059
+#define Territory_PlainTable 0x04305a
+#define Territory_ValueTable 0x04305b
+#define Territory_RepresentationTable 0x04305c
+#define Territory_Collate 0x04305d
+#define Territory_ReadSymbols 0x04305e
+#define Territory_ReadCalendarInformation 0x04305f
+#define Territory_NameToNumber 0x043060
+#define Territory_TransformString 0x043061
+#define Territory_Reserved1 0x043062
+#define Territory_Reserved2 0x043063
+#define Territory_Reserved3 0x043064
+#define Territory_Reserved4 0x043065
+#define Territory_Reserved5 0x043066
+#define Territory_Reserved6 0x043067
+#define Territory_Reserved7 0x043068
+#define Territory_Reserved8 0x043069
+#define Territory_Reserved9 0x04306a
+#define Territory_Reserved10 0x04306b
+#define Territory_Reserved11 0x04306c
+#define Territory_Reserved12 0x04306d
+#define Territory_Reserved13 0x04306e
+#define Territory_Reserved14 0x04306f
+#define Territory_Reserved15 0x043070
+#define Territory_Reserved16 0x043071
+#define Territory_Reserved17 0x043072
+#define Territory_Reserved18 0x043073
+#define Territory_Reserved19 0x043074
+#define Territory_ConvertTextToString 0x043075
+#define ScreenBlanker_Control 0x043100
+#define TaskWindow_TaskInfo 0x043380
+#define Free_Register 0x0444c0
+#define Free_DeRegister 0x0444c1
+#define DOSFS_DiscFormat 0x044b00
+#define DOSFS_LayoutStructure 0x044b01
+#define PDriver_Info 0x080140
+#define PDriver_SetInfo 0x080141
+#define PDriver_CheckFeatures 0x080142
+#define PDriver_PageSize 0x080143
+#define PDriver_SetPageSize 0x080144
+#define PDriver_SelectJob 0x080145
+#define PDriver_CurrentJob 0x080146
+#define PDriver_FontSWI 0x080147
+#define PDriver_EndJob 0x080148
+#define PDriver_AbortJob 0x080149
+#define PDriver_Reset 0x08014a
+#define PDriver_GiveRectangle 0x08014b
+#define PDriver_DrawPage 0x08014c
+#define PDriver_GetRectangle 0x08014d
+#define PDriver_CancelJob 0x08014e
+#define PDriver_ScreenDump 0x08014f
+#define PDriver_EnumerateJobs 0x080150
+#define PDriver_SetPrinter 0x080151
+#define PDriver_CancelJobWithError 0x080152
+#define PDriver_SelectIllustration 0x080153
+#define PDriver_InsertIllustration 0x080154
+#define PDriver_DeclareFont 0x080155
+#define PDriver_DeclareDriver 0x080156
+#define PDriver_RemoveDriver 0x080157
+#define PDriver_SelectDriver 0x080158
+#define PDriver_EnumerateDrivers 0x080159
+#define PDriver_MiscOp 0x08015a
+#define PDriver_MiscOpForDriver 0x08015b
+#define PDriver_SetDriver 0x08015c
+#define SharedCLibrary_LibInitAPCS_A 0x080680
+#define SharedCLibrary_LibInitAPCS_R 0x080681
+#define SharedCLibrary_LibInitModule 0x080682
+#define FrontEnd_ExtendedCmdLine 0x081400
+#define FrontEnd_FreeCmdLine 0x081401
+
+#endif
--- /dev/null
+#include "regs.h"
+
+ .text
+
+SWIReturnInst:
+ ldr pc, [sp, #0*4]
+
+ .global _swix
+_swix:
+ orr r0, r0, #0x20000
+
+ .global _swi
+_swi:
+
+/*
+ * Construct a stack frame that looks something like this:
+ * returnval
+ * LDMIA r12!, {r0..rn}
+ * SWI xxxxxx
+ * LDR pc, [sp]
+ * saved r4-r11,lr
+ * saved r1
+ * saved input values (r2...rn)
+ */
+
+ mov pc, lr
+
+ stmfd sp!, {r1-r3} /* Save r1 and put 1st two variadic args on stack */
+ bic r2, r0, #0xff000000
+ orr r2, r2, #0xef000000 /* Construct SWI instruction */
+ adr r0, SWIReturn
+ tst r1, #0x20000 /* bit for write flags */
+ adrne r0, SWIReturnFlags
+ bic r1, r1, #0xff000000 /* Construct LDMIA R12!, {regs} instruction, if */
+ bics r1, r1, #0x00ff0000 /* {regs} = {} (IE no input regs) we must not */
+ orrne r1, r1, #0xe8000000 /* use an LDMIA R12!, {} instruction as this is an */
+ orrne r1, r1, #0x00bc0000 /* invalid instruction, we use a suitable NOP instead */
+ moveq r1, #0 /* 0 = opcode for ANDEQ r0, r0, r0 (a suitable NOP) */
+ ldr r3, SWIReturnInst
+ stmfd sp!, {r0-r9, r11, lr} /* Save regs and set up SWI call routine (in R0-R3) */
+ add r12, sp, #(12+1)*4 /* Point R12 at input regs on stack. */
+ add pc, sp, #4 /* Call routine on stack */
+SWIReturnFlags:
+ ldr r11, [r12], #4
+ str pc, [r11] /* write flags */
+SWIReturn:
+ ldr lr, [sp, #(12+0)*4] /* Fetch reg mask again */
+ movs lr, lr, asl #1 /* Shift out setting C if R0 to be written, N */
+ ldrcs r11, [r12], #4 /* if R1 to be written. */
+ strcs r0, [r11]
+ ldrmi r11, [r12], #4
+ strmi r1, [r11]
+ movs lr, lr, asl #2 /* Shift 2 bits each time for the next 2 regs */
+ ldrcs r11, [r12], #4
+ strcs r2, [r11]
+ ldrmi r11, [r12], #4
+ strmi r3, [r11]
+ movs lr, lr, asl #2
+ ldrcs r11, [r12], #4
+ strcs r4, [r11]
+ ldrmi r11, [r12], #4
+ strmi r5, [r11]
+ movs lr, lr, asl #2
+ ldrcs r11, [r12], #4
+ strcs r6, [r11]
+ ldrmi r11, [r12], #4
+ strmi r7, [r11]
+ movs lr, lr, asl #2
+ ldrcs r11, [r12], #4
+ strcs r8, [r11]
+ ldrmi r11, [r12], #4
+ strmi r9, [r11]
+ ldr r1, [sp, #2*4]
+ tst r1, #0x20000 /* X-bit clear */
+ cmpeq pc, #0x80000000 /* SET V flag if so, so R0 not cleared */
+ movvc r0, #0 /* Clear R0 if no error (or X-bit clear) */
+ add sp, sp, #4*4 /* Drop SWI call routine */
+ ldmia sp!, {r4-r9,r11,lr}
+ add sp, sp, #3*4 /* Drop saved R1 and 1st two variadic args. */
+ movs pc, lr
--- /dev/null
+/* SWI veneers:
+ * Written by Edward Nevill and Jonathan Roach in an idle moment between projects.
+ * Hacked by BDB to add flag returning
+ */
+
+/* Anonymous Error type */
+
+struct Error { int num; char msg[4]; };
+
+typedef struct Error Error;
+
+/* Generic SWI interface
+ * swi(swino,mask,regs...)
+ * swino = SWI number to call as defined in h.swis, X bit set if you wish the
+ * X form of the SWI to be called, clear if you want the non X form.
+ * reg_mask = mask of in / out registers
+ * bits 0-9: Bit N set => Register N specified on input
+ * Bit N clear => Register N unspecified on input
+ * bits 22-31: Bit N set => Register N-22 on output stored
+ * in address specified in varargs list.
+ * ... In order, input registers followed by output registers,
+ * starting at r0 and going up.
+ * returns 0 or errorblock pointer if X-bit set
+ * returns r0 if X-bit clear
+ * swix(swino,mask,regs...)
+ * This behaves identically to 'swi' except that it always calls the X form.
+ *
+ * Eg:
+ * swi(OS_SWINumberToString, IN(R0|R1|R2), n, buf, 255);
+ * e = swi(XOS_SWINumberFromString, IN(R1)|OUT(R0), str, &n);
+ * - Error block pointer (or 0) is returned so must get returned R0
+ * - via argument list.
+ * e = swix(OS_SWINumberFromString, IN(R1)|OUT(R0), str, &n);
+ * - As above but uses the swix function rather that setting the X bit
+ * explicitly (saves one instruction on SWI call).
+ * e = swi(OS_File, IN(R0|R1|R2|R3)|OUT(R4), 255, name, buff, 0, &len);
+ * - We don't care about the load, exec or attrs so don't specify
+ * them in the output registers.
+ */
+
+extern Error *swix(int swino, int reg_mask, ...);
+extern int swi(int swino, int reg_mask, ...);
+
+/* Register mask macros
+ * The bits in the register mask are arranged as follows:
+ * 31 30 29 ... 22 ... 8 ... 2 1 0
+ * O0 O1 O2 ... O9 I9 ... I2 I1 I0 I(N) = bit set if R(N) used on entry
+ * O(N) = bit set if R(N) written on exit
+ * The bits are arranged like this to optimise the case where a SWI is being
+ * called with a small number of input and output registers. For example, a SWI
+ * call which uses R0-R5 on entry and R0-R1 on exit will have a register mask
+ * of 0xC000003f which can be loaded into an ARM register in one instruction
+ * (the compiler performs this optimisation, even when the constant wraps
+ * around between bits 0 and 31). Using the more obvious coding of I0-I9 in bits
+ * 0 - 9 and O0-O9 in bits 16-23 leads to a constant of 0x0003003f which require
+ * two instructions.
+ */
+#define IN(m) (m)
+/* old, incorrect version
+#define OUT(m) ((unsigned)(m&1)<<31|(m&2)<<29|(m&4)<<27|(m&8)<<25|(m&16)<<23|\
+ (m&32)<<21|(m&64)<<19|(m&128)<<17|(m&256)<<15|(m&512)<<13)
+*/
+#define OUT(m) ((unsigned)((m)&1)<<31|((m)&2)<<29|((m)&4)<<27|\
+ ((m)&8)<<25|((m)&16)<<23|((m)&32)<<21|((m)&64)<<19|\
+ ((m)&128)<<17|((m)&256)<<15|((m)&512)<<13|((m)&1024)<<11)
+
+/* The register names
+ * Change these to use different names if you use R0 - R9 elsewhere in your program
+ */
+#define PSW 0x400 /* Use only in OUT, orders BEFORE others */
+#define R0 0x001
+#define R1 0x002
+#define R2 0x004
+#define R3 0x008
+#define R4 0x010
+#define R5 0x020
+#define R6 0x040
+#define R7 0x080
+#define R8 0x100
+#define R9 0x200
--- /dev/null
+#include <stdarg.h>
+#include <string.h>
+
+# define toupper(x) ((x >= 'a' && x <= 'z') ? (x & 0xdf) : x)
+/*# define tolower(x) ((x >= 'A' && x <= 'Z') ? (x | 0x20) : x)*/
+# define islower(x) ((x >= 'a' && x <= 'z') ? 1 : 0)
+# define isdigit(x) ((x >= '0' && x <= '9') ? 1 : 0)
+# define isxdigit(x) (((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F')) ? 1 : 0)
+
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper(*cp) : *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+/* we use this so that we can do without the ctype library */
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+
+static int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (is_digit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */
+
+static unsigned int do_div(unsigned int *n, unsigned int base)
+ {
+ unsigned int d;
+
+ d = *n % base;
+ *n /= base;
+
+ return(d);
+ }
+
+static char * number(char * str, int num, int base, int size, int precision
+ ,int type)
+{
+ char c,sign,tmp[36];
+ const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i;
+
+ if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ if (type&LEFT) type &= ~ZEROPAD;
+ if (base<2 || base>36)
+ return 0;
+ c = (type & ZEROPAD) ? '0' : ' ' ;
+ if (type&SIGN && num<0) {
+ sign='-';
+ num = -num;
+ } else
+ sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
+ if (sign) size--;
+ if (type&SPECIAL) {
+ if (base==16) size -= 2;
+ else if (base==8) size--;
+ }
+ i=0;
+ if (num==0)
+ tmp[i++]='0';
+ else while (num!=0)
+ tmp[i++]=digits[do_div((unsigned int *)&num,base)];
+ if (i>precision) precision=i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT)))
+ while(size-->0)
+ *str++ = ' ';
+ if (sign)
+ *str++ = sign;
+ if (type&SPECIAL) {
+ if (base==8)
+ *str++ = '0';
+ else if (base==16) {
+ *str++ = '0';
+ *str++ = digits[33];
+ }
+ }
+ if (!(type&LEFT))
+ while(size-->0)
+ *str++ = c;
+ while(i<precision--)
+ *str++ = '0';
+ while(i-->0)
+ *str++ = tmp[i];
+ while(size-->0)
+ *str++ = ' ';
+ return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ int len;
+ int i;
+ char * str;
+ char *s;
+ int *ip;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+
+ for (str=buf ; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ *str++ = *fmt;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (is_digit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (is_digit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+ qualifier = *fmt;
+ ++fmt;
+ }
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT))
+ while (--field_width > 0)
+ *str++ = ' ';
+ *str++ = (unsigned char) va_arg(args, int);
+ while (--field_width > 0)
+ *str++ = ' ';
+ break;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s)
+ s = "<NULL>";
+ len = strlen(s);
+ if (precision < 0)
+ precision = len;
+ else if (len > precision)
+ len = precision;
+
+ if (!(flags & LEFT))
+ while (len < field_width--)
+ *str++ = ' ';
+ for (i = 0; i < len; ++i)
+ *str++ = *s++;
+ while (len < field_width--)
+ *str++ = ' ';
+ break;
+
+ case 'o':
+ str = number(str, va_arg(args, unsigned long), 8,
+ field_width, precision, flags);
+ break;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 8;
+ flags |= ZEROPAD;
+ }
+ str = number(str,
+ (unsigned long) va_arg(args, void *), 16,
+ field_width, precision, flags);
+ break;
+
+ case 'x':
+ flags |= SMALL;
+ case 'X':
+ str = number(str, va_arg(args, unsigned long), 16,
+ field_width, precision, flags);
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ str = number(str, va_arg(args, unsigned long), 10,
+ field_width, precision, flags);
+ break;
+
+ case 'n':
+ ip = va_arg(args, int *);
+ *ip = (str - buf);
+ break;
+
+ default:
+ if (*fmt != '%')
+ *str++ = '%';
+ if (*fmt)
+ *str++ = *fmt;
+ else
+ --fmt;
+ break;
+ }
+ }
+ *str = '\0';
+ return str-buf;
+}
+
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
--- /dev/null
+$NetBSD: .keep_me,v 1.1 1996/01/31 23:19:04 mark Exp $
+
+This file must remain so that 'cvs checkout' makes the compile directory.
--- /dev/null
+#
+# BETA -- Kernel configuration used for beta kernels
+#
+
+include "std.arm32"
+
+# estimated number of users
+
+maxusers 8
+
+# Standard system options
+
+options TIMEZONE=0 # time zone to adjust RTC time by
+options DST=0 # daylight savings time used by RTC
+options SWAPPAGER # paging; REQUIRED
+options VNODEPAGER # mmap() of files
+options DEVPAGER # mmap() of devices
+
+# CPU options
+
+options CPU_ARM6
+options CPU_LATE_ABORT # ARM7XX compatibility
+
+# FPA options
+
+options FPE # Single precision FPE
+options ARMFPE # ARM Ltd FPE
+
+# File system options
+
+options FFS # UFS
+#options QUOTA # UFS quotas
+#options LFS # log-structured file system
+#options MFS # memory file system
+
+options CD9660 # ISO 9660 + Rock Ridge file system
+options MSDOSFS # MS-DOS file system
+options FDESC # /dev/fd
+options FIFO # FIFOs; RECOMMENDED
+options KERNFS # /kern
+#options NULLFS # loopback file system
+#options PORTAL # ?
+options PROCFS # /proc
+#options UMAPFS # NULLFS + uid and gid remapping
+options UNION # union file system
+
+# Networking options
+
+options NFSCLIENT
+options NFSSERVER
+#options GATEWAY # packet forwarding
+options INET # IP + ICMP + TCP + UDP
+#options NS # XNS
+#options ISO,TPIP # OSI
+#options EON # OSI tunneling over IP
+#options CCITT,LLC,HDLC # X.25
+
+# Compatibility options
+
+options COMPAT_43
+options COMPAT_10
+options COMPAT_09
+options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options SYSVMSG # System V-like message queues
+#options SYSVSEM # System V-like semaphores
+#options SYSVSHM # System V-like memory sharing
+#options SHMMAXPGS=1024 # 1024 pages is the default
+
+# Device options
+
+options RAMDISK_HOOKS # boottime setup of ramdisk
+options RAMDISK_SIZE=0 # Size in KBytes
+options PLIP # Build plip device into lpt driver
+
+# Development options
+
+options DIAGNOSTIC # internally consistency checks
+options KTRACE # system call tracing, a la ktrace(1)
+options IRQSTATS # IRQ statistics
+options POSTMORTEM # perform postmortem on panic
+#options ROTTEN_INNARDS # show the gory bit of the postmortem
+options KSHELL # kernel developemnt shell (debug)
+#options LKM # loadable kernel modules
+#options DEBUGTERM # create a debug console
+#options KGDB # remote kernel debugging
+#options DDB # in-kernel debugger
+#makeoptions DEBUG="-g" # compile full symbol table
+
+config netbsd swap generic
+options GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The vidc
+vidcvideo0 at mainbus?
+
+# generic VT console device
+vt0 at mainbus?
+vt1 at mainbus?
+vt2 at mainbus?
+vt3 at mainbus?
+vt4 at mainbus?
+vt5 at mainbus?
+
+# IDE disk controller
+wdc0 at mainbus? base 0x002107c0 irq 9
+wd0 at wdc? drive ?
+wd1 at wdc? drive ?
+
+# Floppy disk controller
+fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0 at fdc? drive ?
+
+# kbd via IOMD
+kbd0 at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0 at mainbus? base 0x00000000
+
+# Serial ports
+com0 at mainbus? base 0x00210fe0 irq 10
+#com1 at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0 at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0 at mainbus? base 0x00000000
+
+# IIC bus device
+iic0 at mainbus?
+
+# RTC device
+rtc0 at iic? addr 0xa0
+
+# Podule bus device
+podulebus0 at root
+
+asc0 at podulebus? # Acorn SCSI card
+scsibus* at asc?
+
+csc0 at podulebus? # Cumana SCSI II card
+scsibus* at csc?
+
+ptsc0 at podulebus? # Power-Tec SCSI II card
+scsibus* at ptsc?
+
+oak0 at podulebus? # Oak SCSI I card
+scsibus* at oak?
+
+sd* at scsibus? target ? lun ? # SCSI disk drives
+st* at scsibus? target ? lun ? # SCSI tape drives
+cd* at scsibus? target ? lun ? # SCSI CD-ROM drives
+ch* at scsibus? target ? lun ? # SCSI auto-changers
+uk* at scsibus? target ? lun ? # SCSI unknown device
+
+#kie* at podulebus? slot ? offset ?
+
+ea0 at podulebus? # Ether3 podules
+eb0 at podulebus? # EtherB network slot cards
+eh0 at podulebus? # EtherH network slot cards
+ie0 at podulebus? # Ether1 podules
+
+pseudo-device loop 1 # network loopback
+pseudo-device bpfilter 8 # packet filter
+pseudo-device sl 2 # CSLIP
+pseudo-device ppp 2 # PPP
+pseudo-device tun 2 # network tunneling over tty
+
+pseudo-device pty 32 # pseudo-terminals
+pseudo-device tb 1 # tablet line discipline
+pseudo-device vnd 4 # paging to files
+pseudo-device ccd 2 # concatenated disk devices
+
+pseudo-device rd 1 # Ramdisk driver
+
+makeoptions MONITOR="Taxan875+LR"
+#makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
--- /dev/null
+#
+# CLAIRE -- Nut's development machine
+#
+
+include "std.arm32"
+
+# estimated number of users
+
+maxusers 8
+
+# Standard system options
+
+options TIMEZONE=0 # time zone to adjust RTC time by
+options DST=0 # daylight savings time used by RTC
+options SWAPPAGER # paging; REQUIRED
+options VNODEPAGER # mmap() of files
+options DEVPAGER # mmap() of devices
+
+# CPU options
+
+options CPU_ARM6
+options CPU_LATE_ABORT # ARM7XX compatibility
+
+# FPA options
+
+options FPE # Single precision FPE
+options ARMFPE # ARM Ltd FPE
+
+# File system options
+
+options FFS # UFS
+#options QUOTA # UFS quotas
+#options LFS # log-structured file system
+#options MFS # memory file system
+
+options CD9660 # ISO 9660 + Rock Ridge file system
+options MSDOSFS # MS-DOS file system
+#options FDESC # /dev/fd
+options FIFO # FIFOs; RECOMMENDED
+options KERNFS # /kern
+#options NULLFS # loopback file system
+#options PORTAL # ?
+options PROCFS # /proc
+#options UMAPFS # NULLFS + uid and gid remapping
+#options UNION # union file system
+
+# Networking options
+
+options NFSCLIENT
+options NFSSERVER
+options GATEWAY # packet forwarding
+options INET # IP + ICMP + TCP + UDP
+#options NS # XNS
+#options ISO,TPIP # OSI
+#options EON # OSI tunneling over IP
+#options CCITT,LLC,HDLC # X.25
+
+# Compatibility options
+
+options COMPAT_43
+options COMPAT_10
+options COMPAT_09
+options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options SYSVMSG # System V-like message queues
+#options SYSVSEM # System V-like semaphores
+#options SYSVSHM # System V-like memory sharing
+#options SHMMAXPGS=1024 # 1024 pages is the default
+
+# Device options
+
+options RAMDISK_HOOKS # boottime setup of ramdisk
+options RAMDISK_SIZE=0 # Size in KBytes
+options PLIP # Build plip device into lpt driver
+
+# Development options
+
+options DIAGNOSTIC # internally consistency checks
+options KTRACE # system call tracing, a la ktrace(1)
+options IRQSTATS # IRQ statistics
+options POSTMORTEM # perform postmortem on panic
+#options ROTTEN_INNARDS # show the gory bit of the postmortem
+options KSHELL # kernel developemnt shell (debug)
+options LKM # loadable kernel modules
+#options DEBUGTERM # create a debug console
+#options KGDB # remote kernel debugging
+#options DDB # in-kernel debugger
+#makeoptions DEBUG="-g" # compile full symbol table
+
+config netbsd swap generic
+options GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The vidc
+vidcvideo0 at mainbus?
+
+# generic VT console device
+vt0 at mainbus?
+vt1 at mainbus?
+vt2 at mainbus?
+vt3 at mainbus?
+vt4 at mainbus?
+vt5 at mainbus?
+
+# IDE disk controller
+wdc0 at mainbus? base 0x002107c0 irq 9
+wd0 at wdc? drive ?
+wd1 at wdc? drive ?
+
+# Floppy disk controller
+fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0 at fdc? drive ?
+
+# kbd via IOMD
+kbd0 at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0 at mainbus? base 0x00000000
+
+# Serial ports
+com0 at mainbus? base 0x00210fe0 irq 10
+#com1 at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0 at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0 at mainbus? base 0x00000000
+
+# IIC bus device
+iic0 at mainbus?
+
+# RTC device
+rtc0 at iic? addr 0xa0
+
+# Podule bus device
+podulebus0 at root
+
+#asc0 at podulebus? # Acorn SCSI card
+#scsibus* at asc?
+
+#csc0 at podulebus? # Cumana SCSI II card
+#scsibus* at csc?
+
+#ptsc0 at podulebus? # Power-Tec SCSI II card
+#scsibus* at ptsc?
+
+oak0 at podulebus? # Oak SCSI I card
+scsibus* at oak?
+
+sd* at scsibus? target ? lun ? # SCSI disk drives
+st* at scsibus? target ? lun ? # SCSI tape drives
+cd* at scsibus? target ? lun ? # SCSI CD-ROM drives
+ch* at scsibus? target ? lun ? # SCSI auto-changers
+uk* at scsibus? target ? lun ? # SCSI unknown device
+
+#kie* at podulebus? slot ? offset ?
+
+#ea0 at podulebus? # Ether3 podules
+#eb0 at podulebus? # EtherB network slot cards
+eh0 at podulebus? # EtherH network slot cards
+ie0 at podulebus? # Ether1 podules
+
+pseudo-device loop 1 # network loopback
+pseudo-device bpfilter 8 # packet filter
+pseudo-device sl 2 # CSLIP
+pseudo-device ppp 2 # PPP
+pseudo-device tun 2 # network tunneling over tty
+
+pseudo-device pty 32 # pseudo-terminals
+pseudo-device tb 1 # tablet line discipline
+pseudo-device vnd 4 # paging to files
+pseudo-device ccd 2 # concatenated disk devices
+
+pseudo-device rd 1 # Ramdisk driver
+
+makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
--- /dev/null
+#
+# GENERIC -- everything that's currently supported
+#
+
+include "std.arm32"
+
+# estimated number of users
+
+maxusers 32
+
+# Standard system options
+
+options TIMEZONE=0 # time zone to adjust RTC time by
+options DST=0 # daylight savings time used by RTC
+options SWAPPAGER # paging; REQUIRED
+options VNODEPAGER # mmap() of files
+options DEVPAGER # mmap() of devices
+
+# CPU options
+
+options CPU_ARM6
+options CPU_LATE_ABORT # ARM7XX compatibility
+
+# FPA options
+
+options FPE # Single precision FPE
+options ARMFPE # ARM Ltd FPE
+
+# File system options
+
+options FFS # UFS
+options QUOTA # UFS quotas
+options LFS # log-structured file system
+options MFS # memory file system
+
+options CD9660 # ISO 9660 + Rock Ridge file system
+options MSDOSFS # MS-DOS file system
+options FDESC # /dev/fd
+options FIFO # FIFOs; RECOMMENDED
+options KERNFS # /kern
+options NULLFS # loopback file system
+options PORTAL # ?
+options PROCFS # /proc
+options UMAPFS # NULLFS + uid and gid remapping
+options UNION # union file system
+
+# Networking options
+
+options NFSCLIENT
+options NFSSERVER
+options GATEWAY # packet forwarding
+options INET # IP + ICMP + TCP + UDP
+options NS # XNS
+options ISO,TPIP # OSI
+options EON # OSI tunneling over IP
+options CCITT,LLC,HDLC # X.25
+
+# Compatibility options
+
+options COMPAT_43
+options COMPAT_10
+options COMPAT_09
+options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options SYSVMSG # System V-like message queues
+#options SYSVSEM # System V-like semaphores
+#options SYSVSHM # System V-like memory sharing
+#options SHMMAXPGS=1024 # 1024 pages is the default
+
+# Device options
+
+options RAMDISK_HOOKS # boottime setup of ramdisk
+options RAMDISK_SIZE=0 # Size in KBytes
+options PLIP # Build plip device into lpt driver
+
+# Development options
+
+options DIAGNOSTIC # internally consistency checks
+options KTRACE # system call tracing, a la ktrace(1)
+options IRQSTATS # IRQ statistics
+options POSTMORTEM # perform postmortem on panic
+#options ROTTEN_INNARDS # show the gory bit of the postmortem
+options KSHELL # kernel developemnt shell (debug)
+options LKM # loadable kernel modules
+#options DEBUGTERM # create a debug console
+#options KGDB # remote kernel debugging
+options DDB # in-kernel debugger
+#makeoptions DEBUG="-g" # compile full symbol table
+
+config netbsd swap generic
+options GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The hydra multiprocessor device
+#hydrabus0 at mainbus?
+
+#cpu1 at hydrabus?
+#cpu2 at hydrabus?
+#cpu3 at hydrabus?
+#cpu4 at hydrabus?
+
+# The vidc
+vidcvideo0 at mainbus?
+
+# generic VT console device
+vt0 at mainbus?
+vt1 at mainbus?
+vt2 at mainbus?
+vt3 at mainbus?
+vt4 at mainbus?
+vt5 at mainbus?
+
+# IDE disk controller
+wdc0 at mainbus? base 0x002107c0 irq 9
+wd0 at wdc? drive ?
+wd1 at wdc? drive ?
+
+# Floppy disk controller
+fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0 at fdc? drive ?
+
+# kbd via IOMD
+kbd0 at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0 at mainbus? base 0x00000000
+
+# PS2 mouse
+pms0 at mainbus? base 0x00000000
+
+# Serial ports
+com0 at mainbus? base 0x00210fe0 irq 10
+#com1 at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0 at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0 at mainbus? base 0x00000000
+
+# IIC bus device
+iic0 at mainbus?
+
+# RTC device
+rtc0 at iic? addr 0xa0
+
+# Podule bus device
+podulebus0 at root
+
+asc0 at podulebus? # Acorn SCSI card
+scsibus* at asc?
+
+#csc0 at podulebus? # Cumana SCSI II card
+#scsibus* at csc?
+
+ptsc0 at podulebus? # Power-Tec SCSI II card
+scsibus* at ptsc?
+
+oak0 at podulebus? # Oak SCSI I card
+scsibus* at oak?
+
+sd* at scsibus? target ? lun ? # SCSI disk drives
+st* at scsibus? target ? lun ? # SCSI tape drives
+cd* at scsibus? target ? lun ? # SCSI CD-ROM drives
+ch* at scsibus? target ? lun ? # SCSI auto-changers
+uk* at scsibus? target ? lun ? # SCSI unknown device
+ss* at scsibus? target ? lun ? # SCSI scanner
+
+#kie* at podulebus? slot ? offset ?
+
+ea0 at podulebus? # Ether3 podules
+eb0 at podulebus? # EtherB network slot cards
+eh0 at podulebus? # EtherH network slot cards
+ie0 at podulebus? # Ether1 podules
+
+pseudo-device loop 1 # network loopback
+pseudo-device bpfilter 8 # packet filter
+pseudo-device sl 2 # CSLIP
+pseudo-device ppp 2 # PPP
+pseudo-device tun 2 # network tunneling over tty
+
+pseudo-device pty 32 # pseudo-terminals
+pseudo-device tb 1 # tablet line discipline
+pseudo-device vnd 4 # paging to files
+pseudo-device ccd 2 # concatenated disk devices
+
+pseudo-device rd 1 # Ramdisk driver
+
+makeoptions MONITOR="Taxan875+LR"
+#makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
--- /dev/null
+# $NetBSD: Makefile.arm32,v 1.10 1996/02/29 20:55:24 cgd Exp $
+
+# Makefile for NetBSD
+#
+# This makefile is constructed from a machine description:
+# config machineid
+# Most changes should be made in the machine description
+# /sys/arch/arm32/conf/``machineid''
+# after which you should do
+# config machineid
+# Machine generic makefile changes should be made in
+# /sys/arch/arm32/conf/Makefile.arm32
+# after which config should be rerun for all machines of that type.
+#
+# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE
+# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
+#
+# -DTRACE compile in kernel tracing hooks
+# -DQUOTA compile in file system quotas
+
+# DEBUG is set to -g if debugging.
+# PROF is set to -pg if profiling.
+
+AS?= as
+CC?= cc
+CPP?= cpp
+LD?= ld
+STRIP?= strip -d
+TOUCH?= touch -f -c
+
+# source tree is located via $S relative to the compilation directory
+S= ../../../..
+ARM32= ../..
+
+INCLUDES= -I. -I$S/arch -I$S
+CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL -Darm32
+CFLAGS= ${DEBUG} -O2 -Werror -fno-builtin
+AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE
+LINKFLAGS= -Ttext F0000020 -e start
+
+### find out what to use for libkern
+.include "$S/lib/libkern/Makefile.inc"
+.ifndef PROF
+LIBKERN= ${KERNLIB}
+.else
+LIBKERN= ${KERNLIB_PROF}
+.endif
+
+### find out what to use for libcompat
+.include "$S/compat/common/Makefile.inc"
+.ifndef PROF
+LIBCOMPAT= ${COMPATLIB}
+.else
+LIBCOMPAT= ${COMPATLIB_PROF}
+.endif
+
+# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP}
+# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix,
+# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file
+# is marked as config-dependent.
+
+NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $<
+NORMAL_S_C= ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -c $<
+
+%OBJS
+
+%CFILES
+
+%SFILES
+
+# load lines for config "xxx" will be emitted as:
+# xxx: ${SYSTEM_DEP} swapxxx.o
+# ${SYSTEM_LD_HEAD}
+# ${SYSTEM_LD} swapxxx.o
+# ${SYSTEM_LD_TAIL}
+SYSTEM_OBJ= locore.o modedefs.o \
+ param.o ioconf.o ${OBJS} ${LIBKERN} ${LIBCOMPAT}
+SYSTEM_DEP= Makefile ${SYSTEM_OBJ}
+SYSTEM_LD_HEAD= rm -f $@
+SYSTEM_LD= @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_OBJ}' vers.o; \
+ ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_OBJ} vers.o
+SYSTEM_LD_TAIL= @size $@; chmod 755 $@
+
+DEBUG?=
+.if ${DEBUG} == "-g"
+LINKFLAGS+= -X
+SYSTEM_LD_TAIL+=; \
+ echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \
+ echo ${STRIP} $@; ${STRIP} $@
+.else
+LINKFLAGS+= -x
+.endif
+
+%LOAD
+
+assym.h: genassym
+ ./genassym >assym.h
+
+genassym: genassym.o
+ ${CC} -o $@ genassym.o
+
+genassym.o: ${ARM32}/arm32/genassym.c
+ ${NORMAL_C_C}
+
+param.c: $S/conf/param.c
+ rm -f param.c
+ cp $S/conf/param.c .
+
+param.o: param.c Makefile
+ ${NORMAL_C_C}
+
+ioconf.o: ioconf.c
+ ${NORMAL_C}
+
+newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
+ sh $S/conf/newvers.sh
+ ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c
+
+
+clean::
+ rm -f eddep *netbsd netbsd.gdb tags *.[io] [a-z]*.s \
+ [Ee]rrs linterrs makelinks genassym genassym.o assym.h
+
+lint:
+ @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} ${PARAM} -UKGDB \
+ ${ARM32}/arm32/Locore.c ${CFILES} ${ARM32}/arm32/swapgeneric.c \
+ ioconf.c param.c | \
+ grep -v 'static function .* unused'
+
+tags:
+ @echo "see $S/kern/Makefile for tags"
+
+links:
+ egrep '#if' ${CFILES} | sed -f $S/conf/defines | \
+ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink
+ echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \
+ sort -u | comm -23 - dontlink | \
+ sed 's,../.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' > makelinks
+ sh makelinks && rm -f dontlink
+
+SRCS= ${ARM32}/arm32/locore.S modedefs.c \
+ param.c ioconf.c ${CFILES} ${SFILES}
+depend: .depend
+.depend: ${SRCS} assym.h param.c
+ mkdep ${AFLAGS} ${CPPFLAGS} ${ARM32}/arm32/locore.S
+ mkdep -a ${CFLAGS} ${CPPFLAGS} modedefs.c
+ mkdep -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES}
+ mkdep -a ${AFLAGS} ${CPPFLAGS} ${SFILES}
+ mkdep -a ${CFLAGS} ${CPPFLAGS} ${PARAM} ${ARM32}/arm32/genassym.c
+
+
+# depend on root or device configuration
+autoconf.o conf.o: Makefile
+
+# depend on network or filesystem configuration
+uipc_proto.o vfs_conf.o: Makefile
+
+# depend on maxusers
+genassym.o machdep.o: Makefile
+
+# depend on CPU configuration
+cpuswitch.o fault.o machdep.o: Makefile
+
+
+locore.o: ${ARM32}/arm32/locore.S assym.h
+ ${NORMAL_S}
+
+modedefs.c: makemodes ${ARM32}/conf/monitors/${MONITOR} Makefile
+ ./makemodes ${ARM32}/conf/monitors/${MONITOR} modedefs.c ${MODES}
+
+modedefs.o: modedefs.c
+ ${NORMAL_C}
+
+makemodes: makemodes.o
+ ${CC} -o $@ makemodes.o
+
+makemodes.o: ${ARM32}/arm32/makemodes.c
+ ${NORMAL_C_C}
+
+%RULES
--- /dev/null
+#
+# PHARM -- Mark's development machine in the office
+#
+
+include "std.arm32"
+
+# estimated number of users
+
+maxusers 32
+
+# Standard system options
+
+options TIMEZONE=0 # time zone to adjust RTC time by
+options DST=0 # daylight savings time used by RTC
+options SWAPPAGER # paging; REQUIRED
+options VNODEPAGER # mmap() of files
+options DEVPAGER # mmap() of devices
+
+# CPU options
+
+options CPU_ARM6
+options CPU_LATE_ABORT # ARM7XX compatibility
+
+# FPA options
+
+#options FPE # Single precision FPE
+options ARMFPE # ARM Ltd FPE
+
+# File system options
+
+options FFS # UFS
+#options QUOTA # UFS quotas
+#options LFS # log-structured file system
+#options MFS # memory file system
+
+options CD9660 # ISO 9660 + Rock Ridge file system
+options MSDOSFS # MS-DOS file system
+options FDESC # /dev/fd
+options FIFO # FIFOs; RECOMMENDED
+options KERNFS # /kern
+#options NULLFS # loopback file system
+#options PORTAL # ?
+options PROCFS # /proc
+#options UMAPFS # NULLFS + uid and gid remapping
+options UNION # union file system
+
+# Networking options
+
+options NFSCLIENT
+options NFSSERVER
+options GATEWAY # packet forwarding
+options INET # IP + ICMP + TCP + UDP
+#options NS # XNS
+#options ISO,TPIP # OSI
+#options EON # OSI tunneling over IP
+#options CCITT,LLC,HDLC # X.25
+
+# Compatibility options
+
+options COMPAT_43
+options COMPAT_10
+options COMPAT_09
+options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options SYSVMSG # System V-like message queues
+#options SYSVSEM # System V-like semaphores
+#options SYSVSHM # System V-like memory sharing
+#options SHMMAXPGS=1024 # 1024 pages is the default
+
+# Device options
+
+options RAMDISK_HOOKS # boottime setup of ramdisk
+options RAMDISK_SIZE=0 # Size in KBytes
+options PLIP # Build plip device into lpt driver
+
+# Development options
+
+options DIAGNOSTIC # internally consistency checks
+options KTRACE # system call tracing, a la ktrace(1)
+options IRQSTATS # IRQ statistics
+options POSTMORTEM # perform postmortem on panic
+#options ROTTEN_INNARDS # show the gory bit of the postmortem
+options KSHELL # kernel developemnt shell (debug)
+options LKM # loadable kernel modules
+#options DEBUGTERM # create a debug console
+#options KGDB # remote kernel debugging
+options DDB # in-kernel debugger
+#makeoptions DEBUG="-g" # compile full symbol table
+
+config netbsd swap generic
+options GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The hydra multiprocessor device
+#hydrabus0 at mainbus?
+
+#cpu1 at hydrabus?
+#cpu2 at hydrabus?
+#cpu3 at hydrabus?
+#cpu4 at hydrabus?
+
+# The vidc
+vidcvideo0 at mainbus?
+
+# generic VT console device
+vt0 at mainbus?
+vt1 at mainbus?
+vt2 at mainbus?
+vt3 at mainbus?
+vt4 at mainbus?
+vt5 at mainbus?
+
+# IDE disk controller
+wdc0 at mainbus? base 0x002107c0 irq 9
+wd0 at wdc? drive ?
+wd1 at wdc? drive ?
+
+# Floppy disk controller
+fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0 at fdc? drive ?
+
+# kbd via IOMD
+kbd0 at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0 at mainbus? base 0x00000000
+
+# Serial ports
+com0 at mainbus? base 0x00210fe0 irq 10
+#com1 at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0 at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0 at mainbus? base 0x00000000
+
+# IIC bus device
+iic0 at mainbus?
+
+# RTC device
+rtc0 at iic? addr 0xa0
+
+# Podule bus device
+podulebus0 at root
+
+#asc0 at podulebus? # Acorn SCSI card
+#scsibus* at asc?
+
+#csc0 at podulebus? # Cumana SCSI II card
+#scsibus* at csc?
+
+ptsc0 at podulebus? # Power-Tec SCSI II card
+scsibus* at ptsc?
+
+#oak0 at podulebus? # Oak SCSI I card
+#scsibus* at oak?
+
+sd* at scsibus? target ? lun ? # SCSI disk drives
+st* at scsibus? target ? lun ? # SCSI tape drives
+cd* at scsibus? target ? lun ? # SCSI CD-ROM drives
+ch* at scsibus? target ? lun ? # SCSI auto-changers
+uk* at scsibus? target ? lun ? # SCSI unknown device
+
+#kie* at podulebus? slot ? offset ?
+
+#ea0 at podulebus? # Ether3 podules
+eb0 at podulebus? # EtherB network slot cards
+#eh0 at podulebus? # EtherH network slot cards
+#ie0 at podulebus? # Ether1 podules
+
+pseudo-device loop 1 # network loopback
+pseudo-device bpfilter 8 # packet filter
+pseudo-device sl 2 # CSLIP
+pseudo-device ppp 2 # PPP
+pseudo-device tun 2 # network tunneling over tty
+
+pseudo-device pty 32 # pseudo-terminals
+pseudo-device tb 1 # tablet line discipline
+pseudo-device vnd 4 # paging to files
+pseudo-device ccd 2 # concatenated disk devices
+
+pseudo-device rd 1 # Ramdisk driver
+
+makeoptions MONITOR="Taxan875+LR"
+#makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
--- /dev/null
+#
+# REMY -- Scott's development machine
+#
+
+include "std.arm32"
+
+# estimated number of users
+
+maxusers 8
+
+# Standard system options
+
+options TIMEZONE=0 # time zone to adjust RTC time by
+options DST=0 # daylight savings time used by RTC
+options SWAPPAGER # paging; REQUIRED
+options VNODEPAGER # mmap() of files
+options DEVPAGER # mmap() of devices
+
+# CPU options
+
+options CPU_ARM6
+options CPU_LATE_ABORT # ARM7XX compatibility
+
+# FPA options
+
+options FPE # Single precision FPE
+options ARMFPE # ARM Ltd FPE
+
+# File system options
+
+options FFS # UFS
+#options QUOTA # UFS quotas
+#options LFS # log-structured file system
+#options MFS # memory file system
+
+options CD9660 # ISO 9660 + Rock Ridge file system
+options MSDOSFS # MS-DOS file system
+options FDESC # /dev/fd
+options FIFO # FIFOs; RECOMMENDED
+options KERNFS # /kern
+#options NULLFS # loopback file system
+#options PORTAL # ?
+options PROCFS # /proc
+#options UMAPFS # NULLFS + uid and gid remapping
+options UNION # union file system
+
+# Networking options
+
+options NFSCLIENT
+options NFSSERVER
+#options GATEWAY # packet forwarding
+options INET # IP + ICMP + TCP + UDP
+#options NS # XNS
+#options ISO,TPIP # OSI
+#options EON # OSI tunneling over IP
+#options CCITT,LLC,HDLC # X.25
+
+# Compatibility options
+
+options COMPAT_43
+options COMPAT_10
+options COMPAT_09
+options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options SYSVMSG # System V-like message queues
+#options SYSVSEM # System V-like semaphores
+#options SYSVSHM # System V-like memory sharing
+#options SHMMAXPGS=1024 # 1024 pages is the default
+
+# Device options
+
+options RAMDISK_HOOKS # boottime setup of ramdisk
+options RAMDISK_SIZE=0 # Size in KBytes
+options PLIP # Build plip device into lpt driver
+
+# Development options
+
+options DIAGNOSTIC # internally consistency checks
+options KTRACE # system call tracing, a la ktrace(1)
+options IRQSTATS # IRQ statistics
+options POSTMORTEM # perform postmortem on panic
+#options ROTTEN_INNARDS # show the gory bit of the postmortem
+options KSHELL # kernel developemnt shell (debug)
+options LKM # loadable kernel modules
+#options DEBUGTERM # create a debug console
+#options KGDB # remote kernel debugging
+#options DDB # in-kernel debugger
+#makeoptions DEBUG="-g" # compile full symbol table
+
+config netbsd swap generic
+options GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The vidc
+vidcvideo0 at mainbus?
+
+# generic VT console device
+vt0 at mainbus?
+vt1 at mainbus?
+vt2 at mainbus?
+vt3 at mainbus?
+vt4 at mainbus?
+vt5 at mainbus?
+
+# IDE disk controller
+wdc0 at mainbus? base 0x002107c0 irq 9
+wd0 at wdc? drive ?
+wd1 at wdc? drive ?
+
+# Floppy disk controller
+fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0 at fdc? drive ?
+
+# kbd via IOMD
+kbd0 at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0 at mainbus? base 0x00000000
+
+# Serial ports
+com0 at mainbus? base 0x00210fe0 irq 10
+#com1 at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0 at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0 at mainbus? base 0x00000000
+
+# IIC bus device
+iic0 at mainbus?
+
+# RTC device
+rtc0 at iic? addr 0xa0
+
+# Podule bus device
+podulebus0 at root
+
+sd* at scsibus? target ? lun ? # SCSI disk drives
+st* at scsibus? target ? lun ? # SCSI tape drives
+cd* at scsibus? target ? lun ? # SCSI CD-ROM drives
+ch* at scsibus? target ? lun ? # SCSI auto-changers
+uk* at scsibus? target ? lun ? # SCSI unknown device
+
+asc0 at podulebus0 slot 0 # Acorn SCSI card
+asc1 at podulebus0 slot 1 # Acorn SCSI card
+asc2 at podulebus0 slot 2 # Acorn SCSI card
+asc3 at podulebus0 slot 3 # Acorn SCSI card
+csc0 at podulebus0 slot 0 # Cumana SCSI card
+csc1 at podulebus0 slot 1 # Cumana SCSI card
+csc2 at podulebus0 slot 2 # Cumana SCSI card
+csc3 at podulebus0 slot 3 # Cumana SCSI card
+ptsc0 at podulebus0 slot 0 # Power-tec SCSI card
+ptsc1 at podulebus0 slot 1 # Power-tec SCSI card
+ptsc2 at podulebus0 slot 2 # Power-tec SCSI card
+ptsc3 at podulebus0 slot 3 # Power-tec SCSI card
+#oak0 at podulebus0 slot 0 # Oak SCSI card
+#oak1 at podulebus0 slot 1 # Oak SCSI card
+#oak2 at podulebus0 slot 2 # Oak SCSI card
+#oak3 at podulebus0 slot 3 # Oak SCSI card
+
+scsibus0 at asc0
+scsibus1 at asc1
+scsibus2 at asc2
+scsibus3 at asc3
+scsibus0 at csc0
+scsibus1 at csc1
+scsibus2 at csc2
+scsibus3 at csc3
+scsibus0 at ptsc0
+scsibus1 at ptsc1
+scsibus2 at ptsc2
+scsibus3 at ptsc3
+#scsibus0 at oak0
+#scsibus1 at oak1
+#scsibus2 at oak2
+#scsibus3 at oak3
+
+# First SCSI bus
+sd0 at scsibus0 target 0 lun ? # SCSI disk drive
+sd1 at scsibus0 target 1 lun ? # SCSI disk drive
+sd2 at scsibus0 target 2 lun ? # SCSI disk drive
+sd3 at scsibus0 target 3 lun ? # SCSI disk drive
+sd4 at scsibus0 target 4 lun ? # SCSI disk drive
+sd5 at scsibus0 target 5 lun ? # SCSI disk drive
+sd6 at scsibus0 target 6 lun ? # SCSI disk drive
+st0 at scsibus0 target 0 lun ? # SCSI tape drive
+st1 at scsibus0 target 1 lun ? # SCSI tape drive
+st2 at scsibus0 target 2 lun ? # SCSI tape drive
+st3 at scsibus0 target 3 lun ? # SCSI tape drive
+st4 at scsibus0 target 4 lun ? # SCSI tape drive
+st5 at scsibus0 target 5 lun ? # SCSI tape drive
+st6 at scsibus0 target 6 lun ? # SCSI tape drive
+cd0 at scsibus0 target 0 lun ? # SCSI CD-ROM drive
+cd1 at scsibus0 target 1 lun ? # SCSI CD-ROM drive
+cd2 at scsibus0 target 2 lun ? # SCSI CD-ROM drive
+cd3 at scsibus0 target 3 lun ? # SCSI CD-ROM drive
+cd4 at scsibus0 target 4 lun ? # SCSI CD-ROM drive
+cd5 at scsibus0 target 5 lun ? # SCSI CD-ROM drive
+cd6 at scsibus0 target 6 lun ? # SCSI CD-ROM drive
+uk0 at scsibus0 target 0 lun ? # SCSI Unknown device
+uk1 at scsibus0 target 1 lun ? # SCSI Unknown device
+uk2 at scsibus0 target 2 lun ? # SCSI Unknown device
+uk3 at scsibus0 target 3 lun ? # SCSI Unknown device
+uk4 at scsibus0 target 4 lun ? # SCSI Unknown device
+uk5 at scsibus0 target 5 lun ? # SCSI Unknown device
+uk6 at scsibus0 target 6 lun ? # SCSI Unknown device
+
+# Second SCSI bus
+sd8 at scsibus1 target 0 lun ? # SCSI disk drive
+sd9 at scsibus1 target 1 lun ? # SCSI disk drive
+sd10 at scsibus1 target 2 lun ? # SCSI disk drive
+sd11 at scsibus1 target 3 lun ? # SCSI disk drive
+sd12 at scsibus1 target 4 lun ? # SCSI disk drive
+sd13 at scsibus1 target 5 lun ? # SCSI disk drive
+sd14 at scsibus1 target 6 lun ? # SCSI disk drive
+st8 at scsibus1 target 0 lun ? # SCSI tape drive
+st9 at scsibus1 target 1 lun ? # SCSI tape drive
+st10 at scsibus1 target 2 lun ? # SCSI tape drive
+st11 at scsibus1 target 3 lun ? # SCSI tape drive
+st12 at scsibus1 target 4 lun ? # SCSI tape drive
+st13 at scsibus1 target 5 lun ? # SCSI tape drive
+st14 at scsibus1 target 6 lun ? # SCSI tape drive
+cd8 at scsibus1 target 0 lun ? # SCSI CD-ROM drive
+cd9 at scsibus1 target 1 lun ? # SCSI CD-ROM drive
+cd10 at scsibus1 target 2 lun ? # SCSI CD-ROM drive
+cd11 at scsibus1 target 3 lun ? # SCSI CD-ROM drive
+cd12 at scsibus1 target 4 lun ? # SCSI CD-ROM drive
+cd13 at scsibus1 target 5 lun ? # SCSI CD-ROM drive
+cd14 at scsibus1 target 6 lun ? # SCSI CD-ROM drive
+uk8 at scsibus1 target 0 lun ? # SCSI Unknown device
+uk9 at scsibus1 target 1 lun ? # SCSI Unknown device
+uk10 at scsibus1 target 2 lun ? # SCSI Unknown device
+uk11 at scsibus1 target 3 lun ? # SCSI Unknown device
+uk12 at scsibus1 target 4 lun ? # SCSI Unknown device
+uk13 at scsibus1 target 5 lun ? # SCSI Unknown device
+uk14 at scsibus1 target 6 lun ? # SCSI Unknown device
+
+# Third SCSI bus
+sd16 at scsibus2 target 0 lun ? # SCSI disk drive
+sd17 at scsibus2 target 1 lun ? # SCSI disk drive
+sd18 at scsibus2 target 2 lun ? # SCSI disk drive
+sd19 at scsibus2 target 3 lun ? # SCSI disk drive
+sd20 at scsibus2 target 4 lun ? # SCSI disk drive
+sd21 at scsibus2 target 5 lun ? # SCSI disk drive
+sd22 at scsibus2 target 6 lun ? # SCSI disk drive
+st16 at scsibus2 target 0 lun ? # SCSI tape drive
+st17 at scsibus2 target 1 lun ? # SCSI tape drive
+st18 at scsibus2 target 2 lun ? # SCSI tape drive
+st19 at scsibus2 target 3 lun ? # SCSI tape drive
+st20 at scsibus2 target 4 lun ? # SCSI tape drive
+st21 at scsibus2 target 5 lun ? # SCSI tape drive
+st22 at scsibus2 target 6 lun ? # SCSI tape drive
+cd16 at scsibus2 target 0 lun ? # SCSI CD-ROM drive
+cd17 at scsibus2 target 1 lun ? # SCSI CD-ROM drive
+cd18 at scsibus2 target 2 lun ? # SCSI CD-ROM drive
+cd19 at scsibus2 target 3 lun ? # SCSI CD-ROM drive
+cd20 at scsibus2 target 4 lun ? # SCSI CD-ROM drive
+cd21 at scsibus2 target 5 lun ? # SCSI CD-ROM drive
+cd22 at scsibus2 target 6 lun ? # SCSI CD-ROM drive
+uk16 at scsibus2 target 0 lun ? # SCSI Unknown device
+uk17 at scsibus2 target 1 lun ? # SCSI Unknown device
+uk18 at scsibus2 target 2 lun ? # SCSI Unknown device
+uk19 at scsibus2 target 3 lun ? # SCSI Unknown device
+uk20 at scsibus2 target 4 lun ? # SCSI Unknown device
+uk21 at scsibus2 target 5 lun ? # SCSI Unknown device
+uk22 at scsibus2 target 6 lun ? # SCSI Unknown device
+
+# Fourth SCSI bus
+sd24 at scsibus3 target 0 lun ? # SCSI disk drive
+sd25 at scsibus3 target 1 lun ? # SCSI disk drive
+sd26 at scsibus3 target 2 lun ? # SCSI disk drive
+sd27 at scsibus3 target 3 lun ? # SCSI disk drive
+sd28 at scsibus3 target 4 lun ? # SCSI disk drive
+sd29 at scsibus3 target 5 lun ? # SCSI disk drive
+sd30 at scsibus3 target 6 lun ? # SCSI disk drive
+st24 at scsibus3 target 0 lun ? # SCSI tape drive
+st25 at scsibus3 target 1 lun ? # SCSI tape drive
+st26 at scsibus3 target 2 lun ? # SCSI tape drive
+st27 at scsibus3 target 3 lun ? # SCSI tape drive
+st28 at scsibus3 target 4 lun ? # SCSI tape drive
+st29 at scsibus3 target 5 lun ? # SCSI tape drive
+st30 at scsibus3 target 6 lun ? # SCSI tape drive
+cd24 at scsibus3 target 0 lun ? # SCSI CD-ROM drive
+cd25 at scsibus3 target 1 lun ? # SCSI CD-ROM drive
+cd26 at scsibus3 target 2 lun ? # SCSI CD-ROM drive
+cd27 at scsibus3 target 3 lun ? # SCSI CD-ROM drive
+cd28 at scsibus3 target 4 lun ? # SCSI CD-ROM drive
+cd29 at scsibus3 target 5 lun ? # SCSI CD-ROM drive
+cd30 at scsibus3 target 6 lun ? # SCSI CD-ROM drive
+uk24 at scsibus3 target 0 lun ? # SCSI Unknown device
+uk25 at scsibus3 target 1 lun ? # SCSI Unknown device
+uk26 at scsibus3 target 2 lun ? # SCSI Unknown device
+uk27 at scsibus3 target 3 lun ? # SCSI Unknown device
+uk28 at scsibus3 target 4 lun ? # SCSI Unknown device
+uk29 at scsibus3 target 5 lun ? # SCSI Unknown device
+uk30 at scsibus3 target 6 lun ? # SCSI Unknown device
+
+ch* at scsibus? target ? lun ? # SCSI auto-changers
+
+#kie* at podulebus? slot ? offset ?
+
+#ea0 at podulebus? # Ether3 podules
+#eb0 at podulebus? # EtherB network slot cards
+#eh0 at podulebus? # EtherH network slot cards
+#ie0 at podulebus? # Ether1 podules
+
+pseudo-device loop 1 # network loopback
+pseudo-device bpfilter 8 # packet filter
+pseudo-device sl 2 # CSLIP
+pseudo-device ppp 2 # PPP
+pseudo-device tun 2 # network tunneling over tty
+
+pseudo-device pty 32 # pseudo-terminals
+pseudo-device tb 1 # tablet line discipline
+pseudo-device vnd 4 # paging to files
+pseudo-device ccd 2 # concatenated disk devices
+
+pseudo-device rd 1 # Ramdisk driver
+
+makeoptions MONITOR="AKF85"
+makeoptions MODES="1280,1024 1024,768,60 1024,768,70 800,600,60 640,480,60 1152,900"
--- /dev/null
+#
+# VOYAGER -- Mark's master development machine
+#
+
+include "std.arm32"
+
+# estimated number of users
+
+maxusers 32
+
+# Standard system options
+
+options TIMEZONE=0 # time zone to adjust RTC time by
+options DST=0 # daylight savings time used by RTC
+options SWAPPAGER # paging; REQUIRED
+options VNODEPAGER # mmap() of files
+options DEVPAGER # mmap() of devices
+
+# CPU options
+
+options CPU_ARM6
+options CPU_LATE_ABORT # ARM7XX compatibility
+
+# FPA options
+
+#options FPE # Single precision FPE
+options ARMFPE # ARM Ltd FPE
+
+# File system options
+
+options FFS # UFS
+#options QUOTA # UFS quotas
+#options LFS # log-structured file system
+options MFS # memory file system
+
+options CD9660 # ISO 9660 + Rock Ridge file system
+options MSDOSFS # MS-DOS file system
+options FDESC # /dev/fd
+options FIFO # FIFOs; RECOMMENDED
+options KERNFS # /kern
+options NULLFS # loopback file system
+#options PORTAL # ?
+options PROCFS # /proc
+#options UMAPFS # NULLFS + uid and gid remapping
+options UNION # union file system
+
+# Networking options
+
+options NFSCLIENT
+options NFSSERVER
+options GATEWAY # packet forwarding
+options INET # IP + ICMP + TCP + UDP
+#options NS # XNS
+#options ISO,TPIP # OSI
+#options EON # OSI tunneling over IP
+#options CCITT,LLC,HDLC # X.25
+
+# Compatibility options
+
+options COMPAT_43
+options COMPAT_10
+options COMPAT_09
+options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD
+
+# Shared memory options
+
+#options SYSVMSG # System V-like message queues
+#options SYSVSEM # System V-like semaphores
+#options SYSVSHM # System V-like memory sharing
+#options SHMMAXPGS=1024 # 1024 pages is the default
+
+# Device options
+
+options RAMDISK_HOOKS # boottime setup of ramdisk
+options RAMDISK_SIZE=0 # Size in KBytes
+options PLIP # Build plip device into lpt driver
+
+# Development options
+
+options DIAGNOSTIC # internally consistency checks
+options KTRACE # system call tracing, a la ktrace(1)
+options IRQSTATS # IRQ statistics
+options POSTMORTEM # perform postmortem on panic
+#options ROTTEN_INNARDS # show the gory bit of the postmortem
+options KSHELL # kernel developemnt shell (debug)
+options LKM # loadable kernel modules
+#options DEBUGTERM # create a debug console
+#options KGDB # remote kernel debugging
+options DDB # in-kernel debugger
+#makeoptions DEBUG="-g" # compile full symbol table
+
+config netbsd swap generic
+options GENERIC
+
+# The main bus device
+mainbus0 at root
+
+# The boot cpu
+cpu0 at mainbus?
+
+# The hydra multiprocessor device
+hydrabus0 at mainbus?
+
+#cpu1 at hydrabus?
+#cpu2 at hydrabus?
+#cpu3 at hydrabus?
+#cpu4 at hydrabus?
+
+# The vidc
+vidcvideo0 at mainbus?
+
+# generic VT console device
+vt0 at mainbus?
+vt1 at mainbus?
+vt2 at mainbus?
+vt3 at mainbus?
+vt4 at mainbus?
+vt5 at mainbus?
+
+# IDE disk controller
+wdc0 at mainbus? base 0x002107c0 irq 9
+wd* at wdc? drive ?
+
+# Floppy disk controller
+fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000
+fd0 at fdc? drive ?
+
+# kbd via IOMD
+kbd0 at mainbus? base 0x00000000
+
+# quadrature mouse
+quadmouse0 at mainbus? base 0x00000000
+
+# PS2 mouse
+pms0 at mainbus? base 0x00000000
+
+# Serial ports
+com0 at mainbus? base 0x00210fe0 irq 10
+#com1 at mainbus? base 0x00210be0
+
+# Parallel ports
+lpt0 at mainbus? base 0x002109e0 irq 0
+
+# Crude sound device
+beep0 at mainbus? base 0x00000000
+
+# IIC bus device
+iic0 at mainbus?
+
+# RTC device
+rtc0 at iic? addr 0xa0
+
+# Podule bus device
+podulebus0 at root
+
+asc0 at podulebus? # Acorn SCSI card
+scsibus* at asc?
+
+csc0 at podulebus? # Cumana SCSI II card
+scsibus* at csc?
+
+ptsc0 at podulebus? # Power-Tec SCSI II card
+scsibus* at ptsc?
+
+oak0 at podulebus? # Oak SCSI I card
+scsibus* at oak?
+
+sd* at scsibus? target ? lun ? # SCSI disk drives
+st* at scsibus? target ? lun ? # SCSI tape drives
+cd* at scsibus? target ? lun ? # SCSI CD-ROM drives
+ch* at scsibus? target ? lun ? # SCSI auto-changers
+uk* at scsibus? target ? lun ? # SCSI unknown device
+ss* at scsibus? target ? lun ? # SCSI scanner
+
+#kie* at podulebus? slot ? offset ?
+
+ea0 at podulebus? # Ether3 podules
+eb0 at podulebus? # EtherB network slot cards
+eh0 at podulebus? # EtherH network slot cards
+ie0 at podulebus? # Ether1 podules
+
+pseudo-device loop 1 # network loopback
+pseudo-device bpfilter 8 # packet filter
+pseudo-device sl 2 # CSLIP
+pseudo-device ppp 2 # PPP
+pseudo-device tun 2 # network tunneling over tty
+
+pseudo-device pty 32 # pseudo-terminals
+pseudo-device tb 1 # tablet line discipline
+pseudo-device vnd 4 # paging to files
+pseudo-device ccd 2 # concatenated disk devices
+
+pseudo-device rd 1 # Ramdisk device
+
+makeoptions MONITOR="Taxan875+LR"
+#makeoptions MONITOR="AKF60"
+makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900"
--- /dev/null
+#
+# First try for arm-specific configuration info
+#
+
+maxpartitions 8
+maxusers 2 8 64
+
+device mainbus { [base = -1], [dack = -1], [irq = -1] }
+attach mainbus at root
+file arch/arm32/mainbus/mainbus.c mainbus
+
+device hydrabus { [slot = -1] }
+attach hydrabus at mainbus
+file arch/arm32/mainbus/exp/hydra.c hydrabus needs-flag
+file arch/arm32/mainbus/exp/hydraboot.S hydrabus
+
+device cpu
+attach cpu at mainbus, hydrabus
+file arch/arm32/mainbus/cpu.c cpu needs-flag
+major {cpu = 38}
+
+#Standard NetBSD wd driver
+device wdc {drive = -1}
+attach wdc at mainbus
+device wd: disk
+attach wd at wdc
+file arch/arm32/mainbus/wd.c wdc needs-flag
+major {wd = 16}
+
+#Hacked NetBSD wd driver with cd and atapi support - nasty hack atm
+#device wdc {drive = -1}
+#attach wdc at mainbus
+#device wd: disk
+#attach wd at wdc
+#file arch/arm32/mainbus/exp/wd.c wdc needs-flag
+#major {wd = 16}
+
+device atapi: disk
+attach atapi at mainbus
+file arch/arm32/mainbus/exp/atapi.c atapi needs-flag
+
+device wcd: disk
+attach wcd at mainbus
+file arch/arm32/mainbus/exp/wcd.c wcd needs-flag
+major {wcd = 20}
+
+#Standard NetBSD fd driver
+device fdc {drive = -1}
+attach fdc at mainbus
+device fd: disk
+attach fd at fdc
+file arch/arm32/mainbus/fd.c fdc needs-flag
+major {fd = 17}
+
+# RAM disk driver
+pseudo-device rd
+file dev/ramdisk.c rd needs-count
+file arch/arm32/dev/rd_hooks.c rd | ramdisk_hooks
+major {rd = 18}
+
+device lpt: tty, ether, ifnet
+attach lpt at mainbus
+file arch/arm32/mainbus/lpt.c lpt needs-flag
+major {lpt = 8}
+
+device com: tty
+attach com at mainbus
+file arch/arm32/mainbus/com.c com needs-flag
+major {com = 12}
+
+# Mouse devices
+device quadmouse: tty
+attach quadmouse at mainbus
+file arch/arm32/mainbus/qmouse.c quadmouse needs-flag
+major {quadmouse = 9}
+
+device pms: tty
+attach pms at mainbus
+file arch/arm32/mainbus/pms.c pms needs-flag
+major {pms = 40}
+
+# Audio devices
+device beep
+attach beep at mainbus
+file arch/arm32/mainbus/beep.c beep needs-flag
+major {beep = 10}
+
+device audio: audio
+attach audio at mainbus
+file arch/arm32/mainbus/vidcaudio.c vidcaudio needs-flag
+major {audio = 36}
+
+device kbd
+attach kbd at mainbus
+file arch/arm32/mainbus/kbd.c kbd needs-flag
+major {kbd = 11}
+
+# Podule bus device
+device podulebus { [slot = -1] }
+attach podulebus at root
+file arch/arm32/podulebus/podulebus.c podulebus
+
+# Ethernet devices
+device ea: ether, ifnet
+attach ea at podulebus
+file arch/arm32/podulebus/if_ea.c ea
+
+device eb: ether, ifnet
+attach eb at podulebus
+file arch/arm32/podulebus/if_eb.c eb
+
+device eh: ether, ifnet
+attach eh at podulebus
+file arch/arm32/podulebus/if_eh.c eh
+
+device ie: ether, ifnet
+attach ie at podulebus
+file arch/arm32/podulebus/if_ie.c ie
+
+# IIC/RTC files
+device iic { addr = -1 }
+attach iic at mainbus
+file arch/arm32/mainbus/iic_asm.S iic
+file arch/arm32/mainbus/iic.c iic needs-flag
+
+device rtc
+attach rtc at iic
+file arch/arm32/mainbus/rtc.c rtc needs-count
+
+#define kgdb
+
+#device kie: kgdb
+#attach kie at podule
+#file arch/arm32/podulebus/kgdb_ie.c kie
+
+#file arch/arm32/arm32/kgdb_glue.c kgdb
+#file arch/arm32/arm32/kgdb_step.c kgdb
+
+#
+# Machine-independent SCSI drivers
+#
+
+include "../../../scsi/files.scsi"
+major {sd = 24}
+major {st = 25}
+major {cd = 26}
+major {ch = 27}
+major {uk = 28}
+major {ss = 29}
+
+# Generic sbic (WD3393) driver
+define sbic
+file arch/arm32/podulebus/sbic.c sbic
+
+# Acorn SCSI I specific layer for sbic
+device asc: scsi, sbic
+attach asc at podulebus
+file arch/arm32/podulebus/asc.c asc
+
+# Generic fas216 + esp216 driver
+define sfas
+file arch/arm32/podulebus/sfas.c sfas
+
+# Cumana specific layer for sfas
+device csc: scsi, sfas
+attach csc at podulebus
+file arch/arm32/podulebus/exp/csc.c csc
+
+device ptsc: scsi, sfas
+attach ptsc at podulebus
+file arch/arm32/podulebus/ptsc.c ptsc
+
+# Generic NCR driver
+define ncr
+file arch/arm32/podulebus/ncr5380sbc.c ncr
+
+# Oak specific layer for ncr
+device oak: scsi, ncr
+attach oak at podulebus
+file arch/arm32/podulebus/oak.c oak
+
+device vidcvideo
+attach vidcvideo at mainbus
+major {vidcvideo = 37}
+device vt: tty
+attach vt at mainbus
+file arch/arm32/dev/console/console.c vt needs-count
+file arch/arm32/dev/console/vidcconsole.c vt needs-count
+file arch/arm32/dev/console/vidc_mc.S vt needs-count
+file arch/arm32/dev/console/vidc.c vt needs-count
+file arch/arm32/dev/console/vt220.c vt needs-count
+file arch/arm32/dev/console/debugconsole.c vt needs-count
+file arch/arm32/dev/console/dumb.c vt needs-count
+
+file arch/arm32/arm32/autoconf.c
+file arch/arm32/arm32/blockio.S
+file arch/arm32/arm32/clock.c
+file arch/arm32/arm32/conf.c
+file arch/arm32/arm32/cpuswitch.S
+file arch/arm32/arm32/disksubr.c disk
+file arch/arm32/arm32/stubs.c
+file arch/arm32/arm32/exception.S
+file arch/arm32/arm32/syscall.c
+file arch/arm32/arm32/ast.c
+file arch/arm32/arm32/fault.c
+file arch/arm32/arm32/undefined.c
+file arch/arm32/arm32/mem.c
+file arch/arm32/arm32/scratch.S
+file arch/arm32/arm32/process_machdep.c
+file arch/arm32/arm32/machdep.c
+file arch/arm32/arm32/sys_machdep.c
+file arch/arm32/arm32/vm_machdep.c
+file arch/arm32/arm32/pmap.c
+file arch/arm32/arm32/fusu.c
+
+file netinet/in_cksum.c inet
+file netns/ns_cksum.c ns
+
+# IRQ/FIQ files
+file arch/arm32/arm32/spl.S
+file arch/arm32/arm32/irq.S
+file arch/arm32/arm32/irqhandler.c
+file arch/arm32/arm32/fiq.S
+
+# library functions
+file arch/arm32/arm32/strstr.c
+file arch/arm32/arm32/strtoul.c
+file arch/arm32/arm32/memset.S
+file arch/arm32/arm32/bcopy_page.S
+file arch/arm32/arm32/bcopy.S
+file arch/arm32/arm32/bcopyinout.S
+file arch/arm32/arm32/copystr.S
+file arch/arm32/arm32/coproc15.S
+file arch/arm32/arm32/setcpsr.S
+file arch/arm32/arm32/setstack.S
+
+# files related to the shell
+file arch/arm32/kshell/shell_input.c kshell
+file arch/arm32/kshell/shell_shell.c kshell
+file arch/arm32/kshell/shell_disassem.c kshell
+file arch/arm32/kshell/strchr.c kshell
+file arch/arm32/kshell/dumphex.c kshell
+
+# files related to debugging
+file arch/arm32/arm32/debug.c
+file arch/arm32/arm32/disassem.c
+file arch/arm32/arm32/postmortem.c
+
+file dev/cons.c
+file dev/cninit.c
+
+# Signal precision FPE
+file arch/arm32/fpe-sp/fpe.c fpe
+file arch/arm32/fpe-sp/fpeadd.S fpe
+file arch/arm32/fpe-sp/fpesub.S fpe
+file arch/arm32/fpe-sp/fpemul.S fpe
+file arch/arm32/fpe-sp/fpediv.S fpe
+file arch/arm32/fpe-sp/fpefix.S fpe
+file arch/arm32/fpe-sp/fpecmf.S fpe
+file arch/arm32/fpe-sp/fpetoe.S fpe
+
+# ARM FPE
+file arch/arm32/fpe-arm/armfpe_glue.S armfpe
+file arch/arm32/fpe-arm/armfpe_init.c armfpe
+file arch/arm32/fpe-arm/armfpe.s armfpe
+
+# DDB
+file arch/arm32/arm32/db_disasm.c ddb
+file arch/arm32/arm32/db_interface.c ddb
+file arch/arm32/arm32/db_trace.c ddb
+file arch/arm32/arm32/db_machdep.c ddb
--- /dev/null
+# Modefile written by !MakeModes version 0.19 (22-Aug-1994)
+# Monitor description file for Acorn AKF60 monitor
+# Line rate: 30 - 50 kHz
+
+file_format:1
+monitor_title:Acorn AKF60
+DPMS_state:1
+
+# Letterbox modes
+
+# 240 x 352 (70Hz)
+startmode
+mode_name:
+x_res:240
+y_res:352
+pixel_rate:9440
+h_timings:18,16,8,240,8,10
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 320 x 250 (70Hz - Modes 6,7)
+# Low band
+startmode
+mode_name:
+x_res:320
+y_res:250
+pixel_rate:12587
+h_timings:36,14,12,320,12,6
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 320 x 256 (70Hz - Modes 1,2,5,9,10,13)
+# Low band
+startmode
+mode_name:
+x_res:320
+y_res:256
+pixel_rate:12587
+h_timings:36,14,12,320,12,6
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 384 x 288 (70Hz)
+# Low band
+startmode
+mode_name:
+x_res:384
+y_res:288
+pixel_rate:18881
+h_timings:64,16,66,384,66,4
+v_timings:2,58,32,288,32,37
+sync_pol:2
+endmode
+
+# 480 x 352 (70Hz)
+# Low band
+startmode
+mode_name:480 x 352
+x_res:480
+y_res:352
+pixel_rate:18881
+h_timings:64,16,18,480,18,4
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 640 x 200 (70Hz - Modes 44,45,46)
+# Low band
+startmode
+mode_name:
+x_res:640
+y_res:200
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,134,0,200,0,113
+sync_pol:2
+endmode
+
+# 640 x 250 (70Hz - Modes 3,11,14)
+# Low band
+startmode
+mode_name:
+x_res:640
+y_res:250
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 640 x 256 (70Hz - Modes 0,4,8,12,15)
+# Low band
+startmode
+mode_name:
+x_res:640
+y_res:256
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 640 x 352 (70Hz - Modes 41,42,43)
+# Low band
+startmode
+mode_name:
+x_res:640
+y_res:352
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# Other modes (some also numbered)
+
+# 320 x 480 (60Hz - Games modes 48,49)
+# Low band
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:12587
+h_timings:36,14,12,320,12,6
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 320 x 480 (72Hz)
+# Mid band
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:28,30,16,320,16,6
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 320 x 480 (75Hz)
+# Mid band
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:26,34,16,320,16,8
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 360 x 480 (60Hz - PCSoft mode 47)
+# Low band
+startmode
+mode_name:
+x_res:360
+y_res:480
+pixel_rate:16783
+h_timings:62,44,16,360,16,34
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (60Hz - Modes 25,26,27,28)
+# Low band
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:25175
+h_timings:88,22,22,640,22,6
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (72Hz)
+# Mid band
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:52,64,30,640,30,14
+# VESA:40,128,0,640,0,24
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 640 x 480 (75Hz)
+# Mid band
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:62,64,30,640,30,14
+# VESA:64,120,0,640,0,16
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 800 x 600 (56Hz - Modes 29,30,31)
+# Mid band
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:36000
+h_timings:70,74,34,800,34,12
+# VESA:72,128,0,800,0,24
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (60Hz)
+# Mid band
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:40000
+h_timings:112,64,40,800,40,0
+# VESA:128,88, 0,800,0,40
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (72Hz)
+# High band
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:50000
+h_timings:88,34,42,800,42,34
+# VESA:120,64, 0,800,0,56
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# 800 x 600 (75Hz)
+# High band
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:49500
+h_timings:80,46,42,800,42,46
+# VESA:80,160,0,800,0,16
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
+# 1024 x 768 (60Hz)
+# High band
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:65000
+h_timings:128,36,60,1024,60,36
+# VESA:136,160,0,1024,0,24
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# Pixel-doubled modes
+
+# 1280 x 480 (60Hz)
+# Low band
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:50350
+h_timings:176,44,44,1280,44,12
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 1280 x 480 (72Hz)
+# Mid band
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:104,128,60,1280,60,28
+# VESA:80,256,0,1280,0,48
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 1280 x 480 (75Hz)
+# Mid band
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:124,128,60,1280,60,28
+# VESA:128,240,0,1280,0,32
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 1600 x 600 (56Hz)
+# Mid band
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:72000
+h_timings:140,148,68,1600,68,24
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (60Hz)
+# Mid band
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:80000
+h_timings:224,128,80,1600,80,0
+# VESA:256,176, 0,1600,0,80
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (72Hz)
+# High band
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:100000
+h_timings:176,68,84,1600,84,68
+# VESA:240,128, 0,1600,0,112
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# 1600 x 600 (75Hz)
+# High band
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:99000
+h_timings:160,92,84,1600,84,92
+# VESA:160,320,0,1600,0,32
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
--- /dev/null
+# Modefile written by !MakeModes version 0.19 (22-Aug-1994)
+# Monitor description file for Acorn AKF85 monitor
+# Line rate: 30 - 82 kHz
+# Frame rate: 50 - 120 Hz
+# Dot rate: Up to 135 MHz
+
+
+file_format:1
+monitor_title:Acorn AKF85
+DPMS_state:0
+
+# 240 x 352 (70Hz)
+startmode
+mode_name:
+x_res:240
+y_res:352
+pixel_rate:9440
+h_timings:20,16,8,240,8,8
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 320 x 250 (70Hz)
+startmode
+mode_name:
+x_res:320
+y_res:250
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 320 x 256 (70Hz)
+startmode
+mode_name:
+x_res:320
+y_res:256
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 320 x 480 (60Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 320 x 480 (73Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:24,40,16,320,16,0
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 320 x 480 (75Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:24,44,16,320,16,0
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 360 x 480 (60Hz)
+startmode
+mode_name:
+x_res:360
+y_res:480
+pixel_rate:16783
+h_timings:64,46,16,360,16,30
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 384 x 288 (70Hz)
+startmode
+mode_name:
+x_res:384
+y_res:288
+pixel_rate:18881
+h_timings:68,16,66,384,66,0
+v_timings:2,58,32,288,32,37
+sync_pol:2
+endmode
+
+# 480 x 352 (70Hz)
+startmode
+mode_name:480 x 352
+x_res:480
+y_res:352
+pixel_rate:18881
+h_timings:68,16,18,480,18,0
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 640 x 200 (70Hz)
+startmode
+mode_name:
+x_res:640
+y_res:200
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,134,0,200,0,113
+sync_pol:2
+endmode
+
+# 640 x 250 (70Hz)
+startmode
+mode_name:
+x_res:640
+y_res:250
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 640 x 256 (70Hz)
+startmode
+mode_name:
+x_res:640
+y_res:256
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 640 x 352 (70Hz)
+startmode
+mode_name:
+x_res:640
+y_res:352
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 640 x 480 (60Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:25175
+h_timings:94,22,22,640,22,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (73Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:48,84,30,640,30,0
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 640 x 480 (75Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:64,76,30,640,30,0
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 640 x 480 (120Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:52600
+h_timings:64,76,30,640,46,18
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 800 x 600 (60Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:40000
+h_timings:128,48,40,800,40,0
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (75Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:49500
+h_timings:80,92,42,800,42,0
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (100Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:69350
+h_timings:100,104,0,800,66,42
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
+# 1024 x 768 (60Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:65000
+h_timings:136,64,60,1024,60,0
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# 1024 x 768 (70Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:75000
+h_timings:124,36,72,1024,72,0
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# 1024 x 768 (75Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:80310
+h_timings:122,86,30,1024,76,0
+v_timings:3,28,0,768,0,1
+sync_pol:0
+endmode
+
+# 1024 x 768 (102Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:119000
+h_timings:130,96,46,1024,106,50
+v_timings:3,28,0,768,0,1
+sync_pol:0
+endmode
+
+# 1152 x 900 (55Hz)
+startmode
+mode_name:1152 x 900
+x_res:1152
+y_res:900
+pixel_rate:80000
+h_timings:156,40,98,1152,124,0
+v_timings:1,28,0,900,0,3
+sync_pol:0
+endmode
+
+# 1152 x 900 (86Hz)
+startmode
+mode_name:1152 x 900
+x_res:1152
+y_res:900
+pixel_rate:134480
+h_timings:132,70,124,1152,124,70
+v_timings:1,28,0,900,0,3
+sync_pol:0
+endmode
+
+# 1280 x 480 (60Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:50350
+h_timings:188,44,44,1280,44,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 1280 x 480 (73Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:96,172,58,1280,58,0
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 1280 x 480 (75Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:128,156,58,1280,58,0
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 1280 x 1024 (76Hz)
+startmode
+mode_name:1280 x 1024
+x_res:1280
+y_res:1024
+pixel_rate:139000
+h_timings:166,90,96,1280,96,0
+v_timings:3,32,0,1024,0,3
+sync_pol:0
+endmode
+
+# 1600 x 600 (56Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:72000
+h_timings:144,168,68,1600,68,0
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (60Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:80000
+h_timings:256,98,78,1600,78,2
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (72Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:100000
+h_timings:226,58,84,1600,84,28
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# 1600 x 600 (75Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:99000
+h_timings:160,188,82,1600,82,0
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 1200 (50Hz)
+startmode
+mode_name:1600 x 1200
+x_res:1600
+y_res:1200
+pixel_rate:131000
+h_timings:166,90,96,1600,128,44
+v_timings:3,32,0,1200,0,3
+sync_pol:0
+endmode
+
+# End
--- /dev/null
+# Modefile written by !MakeModes version 0.19 (22-Aug-1994)
+# Monitor description file for Taxan 875+LR monitor
+# Line rate: 30 - 82 kHz
+# Frame rate: 50 - 120 Hz
+# Dot rate: Up to 135 MHz
+
+file_format:1
+monitor_title:Taxan 875+LR
+DPMS_state:0
+
+# Letterbox modes
+
+# 240 x 352 (70Hz)
+startmode
+mode_name:
+x_res:240
+y_res:352
+pixel_rate:9440
+h_timings:20,16,8,240,8,8
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 320 x 250 (70Hz - Modes 6,7)
+startmode
+mode_name:
+x_res:320
+y_res:250
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 320 x 256 (70Hz - Modes 1,2,5,9,10,13)
+startmode
+mode_name:
+x_res:320
+y_res:256
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 384 x 288 (70Hz)
+startmode
+mode_name:
+x_res:384
+y_res:288
+pixel_rate:18881
+h_timings: 68,16,66,384,66,0
+v_timings: 2,58,32,288,32,37
+sync_pol:2
+endmode
+
+# 480 x 352 (70Hz)
+startmode
+mode_name:480 x 352
+x_res:480
+y_res:352
+pixel_rate:18881
+h_timings: 68,16,18,480,18,0
+v_timings: 2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# 640 x 200 (70Hz - Modes 44,45,46)
+startmode
+mode_name:
+x_res:640
+y_res:200
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,134,0,200,0,113
+sync_pol:2
+endmode
+
+# 640 x 250 (70Hz - Modes 3,11,14)
+startmode
+mode_name:
+x_res:640
+y_res:250
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,109,0,250,0,88
+sync_pol:2
+endmode
+
+# 640 x 256 (70Hz - Modes 0,4,8,12,15)
+startmode
+mode_name:
+x_res:640
+y_res:256
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,106,0,256,0,85
+sync_pol:2
+endmode
+
+# 640 x 352 (70Hz - Modes 41,42,43)
+startmode
+mode_name:
+x_res:640
+y_res:352
+pixel_rate:25175
+h_timings:92,24,22,640,22,0
+v_timings:2,58,0,352,0,37
+sync_pol:2
+endmode
+
+# Other modes (some also numbered)
+
+# 320 x 480 (60Hz - Games modes 48,49)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:12587
+h_timings:42,14,12,320,12,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 320 x 480 (72Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:24,40,16,320,16,0
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 320 x 480 (75Hz)
+startmode
+mode_name:
+x_res:320
+y_res:480
+pixel_rate:15750
+h_timings:24,44,16,320,16,0
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 360 x 480 (60Hz - PCSoft mode 47)
+startmode
+mode_name:
+x_res:360
+y_res:480
+pixel_rate:16783
+h_timings:64,46,16,360,16,30
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (60Hz - Modes 25,26,27,28)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:25175
+h_timings:94,22,22,640,22,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 640 x 480 (72Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:48,84,30,640,30,0
+# VESA:40,128,0,640,0,24
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 640 x 480 (75Hz)
+startmode
+mode_name:640 x 480
+x_res:640
+y_res:480
+pixel_rate:31500
+h_timings:64,76,30,640,30,0
+# VESA:64,120,0,640,0,16
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 800 x 600 (56Hz - Modes 29,30,31)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:36000
+h_timings:72,84,34,800,34,0
+# VESA:72,128,0,800,0,24
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (60Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:40000
+h_timings:128,48,40,800,40,0
+# VESA:128,88, 0,800,0,40
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 800 x 600 (72Hz)
+startmode
+mode_name:800 x 600
+x_res:800
+y_res:600
+pixel_rate:50000
+h_timings:100,42,42,800,42,14
+# VESA:120,64, 0,800,0,56
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# Stick with just the 72Hz mode as this is a factory default
+# 800 x 600 (75Hz)
+#startmode
+#mode_name:800 x 600
+#x_res:800
+#y_res:600
+#pixel_rate:49500
+#h_timings:80,92,42,800,42,0
+# VESA:80,160,0,800,0,16
+#v_timings:3,21,0,600,0,1
+#sync_pol:0
+#endmode
+
+# 1024 x 768 (60Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:65000
+h_timings:136,64,60,1024,60,0
+# VESA:136,160,0,1024,0,24
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# 1024 x 768 (70Hz)
+startmode
+mode_name:1024 x 768
+x_res:1024
+y_res:768
+pixel_rate:75000
+h_timings:124,36,72,1024,72,0
+# VESA:136,144,0,1024,0,24
+v_timings:6,29,0,768,0,3
+sync_pol:0
+endmode
+
+# this has been removed so that it does not get selected for the 16 colour
+# version. 70Hz 1024x768 is a build in setting, 75Hz ain't !
+# 1024 x 768 (75Hz)
+#startmode
+#mode_name:1024 x 768
+#x_res:1024
+#y_res:768
+#pixel_rate:80310
+# VESA:78750
+#h_timings:122,86,30,1024,76,0
+# VESA: 96,176,0,1024,0,16
+#v_timings:3,28,0,768,0,1
+#sync_pol:0
+#endmode
+
+# 1152 x 900 (53Hz)
+startmode
+mode_name:1152 x 900
+x_res:1152
+y_res:900
+pixel_rate:76000
+h_timings:152,64,60,1152,100,0
+v_timings:6,29,0,900,0,3
+sync_pol:3
+endmode
+
+# 1152 x 900 (76Hz)
+startmode
+mode_name:1152 x 900
+x_res:1152
+y_res:900
+pixel_rate:117000
+h_timings:170,96,96,1152,104,12
+v_timings:3,33,0,900,0,3
+sync_pol:3
+endmode
+
+# 1280 x 1024 (60Hz)
+startmode
+mode_name:1280 x 1024
+x_res:1280
+y_res:1024
+pixel_rate:110000
+h_timings:166,90,96,1280,96,0
+#h_timings:128,256,0,1280,0,64
+v_timings:3,32,0,1024,0,3
+sync_pol:0
+endmode
+
+# The taxan has a 70Hz 1280 x 768 build in just got to find it.
+# 1280 x 1024 (70Hz)
+startmode
+mode_name:1280 x 1024
+x_res:1280
+y_res:1024
+pixel_rate:128000
+h_timings:160,88,96,1280,96,0
+#h_timings:166,90,96,1280,96,0
+#h_timings:128,256,0,1280,0,64
+v_timings:3,32,0,1024,0,3
+sync_pol:0
+endmode
+
+# Pixel-doubled modes
+
+# 1280 x 480 (60Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:50350
+h_timings:188,44,44,1280,44,0
+v_timings:2,32,0,480,0,11
+sync_pol:3
+endmode
+
+# 1280 x 480 (72Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:96,172,58,1280,58,0
+# VESA:80,256,0,1280,0,48
+v_timings:3,28,0,480,0,9
+sync_pol:3
+endmode
+
+# 1280 x 480 (75Hz)
+startmode
+mode_name:1280 x 480
+x_res:1280
+y_res:480
+pixel_rate:63000
+h_timings:128,156,58,1280,58,0
+# VESA:128,240,0,1280,0,32
+v_timings:3,16,0,480,0,1
+sync_pol:3
+endmode
+
+# 1600 x 600 (56Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:72000
+h_timings:144,168,68,1600,68,0
+v_timings:2,22,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (60Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:80000
+h_timings:256,98,78,1600,78,2
+# VESA:256,176, 0,1600,0,80
+v_timings:4,23,0,600,0,1
+sync_pol:0
+endmode
+
+# 1600 x 600 (72Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:100000
+h_timings:226,58,84,1600,84,28
+# VESA:240,128, 0,1600,0,112
+v_timings:6,23,0,600,0,37
+sync_pol:0
+endmode
+
+# 1600 x 600 (75Hz)
+startmode
+mode_name:1600 x 600
+x_res:1600
+y_res:600
+pixel_rate:99000
+h_timings:160,188,82,1600,82,0
+# VESA:160,320,0,1600,0,32
+v_timings:3,21,0,600,0,1
+sync_pol:0
+endmode
+
--- /dev/null
+# standard NetBSD/arm32 options
+
+machine arm32
+
+options MACHINE_NONCONTIG # temporary kludge
--- /dev/null
+/* $NetBSD: console.c,v 1.6 1996/04/19 20:03:37 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * console.c
+ *
+ * Console functions
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/tty.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <sys/syslog.h>
+
+#include <dev/cons.h>
+
+#include <machine/vidc.h>
+#include <machine/vconsole.h>
+#include <machine/katelib.h>
+
+#include "vt.h"
+
+#define CONSOLE_VERSION "[V203C] "
+
+/*
+ * Externals
+ */
+
+extern struct tty *constty;
+extern int debug_flags;
+#define consmap_col(x) (x & 0x3)
+#define CONSMAP_BOLD 8
+#define CONSMAP_ITALIC 16
+
+/*
+ * Local variables (to this file)
+ */
+
+int locked=0; /* Nut - is this really safe ? */
+struct tty *physcon_tty[NVT];
+struct vconsole vconsole_master_store;
+struct vconsole *vconsole_master = &vconsole_master_store;
+struct vconsole *vconsole_current;
+struct vconsole *vconsole_head;
+struct vconsole *vconsole_default;
+struct cfdriver rpc_cd;
+extern struct vconsole *debug_vc; /* rename this to vconsole_debug */
+int physcon_major=4;
+static char undefined_string[] = "UNDEFINED";
+int lastconsole;
+static int printing=0;
+static int want_switch=-1;
+
+/*
+ * Prototypes
+ */
+
+int physcon_switch __P((u_int /*number*/));
+void physconstart __P((struct tty */*tp*/));
+static struct vconsole *vconsole_spawn __P((dev_t , struct vconsole *));
+int physconparam __P((struct tty */*tp*/, struct termios */*t*/));
+void consinit __P((void));
+int physcon_switchup __P((void));
+int physcon_switchdown __P((void));
+
+/*
+ * Exported variables
+ */
+
+#define BLANKINIT (10*60*60)
+int vconsole_pending=0;
+int vconsole_blankinit=BLANKINIT;
+int vconsole_blankcounter=BLANKINIT;
+
+/*
+ * Now list all my render engines and terminal emulators
+ */
+
+extern struct render_engine vidcconsole;
+extern struct terminal_emulator vt220;
+
+/*
+ * These find functions should move the console it finds to the top of
+ * the list to achieve a caching type of operation. A doubly
+ * linked list would be faster methinks.
+ */
+
+struct tty *
+find_tp(dev)
+ dev_t dev;
+{
+ struct vconsole *vc;
+ struct vconsole *last=0;
+ int unit = minor (dev);
+ int s;
+
+ s = spltty();
+ for (vc=vconsole_head; vc != NULL; vc=vc->next) {
+ if (vc->number==unit) {
+ if (vc != vconsole_head) {
+ last->next = vc->next;
+ vc->next = vconsole_head;
+ vconsole_head = vc;
+ }
+ (void)splx(s);
+ return vc->tp;
+ }
+ last = vc;
+ }
+ (void)splx(s);
+ return NULL;
+}
+
+struct vconsole *
+find_vc(dev)
+ dev_t dev;
+{
+ struct vconsole *vc;
+ struct vconsole *last=NULL;
+ int unit = minor (dev);
+ int s;
+
+ s = spltty();
+
+ for (vc=vconsole_head; vc!=NULL; vc=vc->next) {
+ if (vc->number==unit) {
+ if (vc!=vconsole_head) {
+ last->next = vc->next;
+ vc->next = vconsole_head;
+ vconsole_head = vc;
+ }
+ (void)splx(s);
+ return vc;
+ }
+ last=vc;
+ }
+ (void)splx(s);
+ return NULL;
+}
+
+struct tty *console_tty = NULL;
+
+/*
+ * Place a graphics driver under virtual console switching control.
+ */
+
+struct vconsole *
+vconsole_spawn_re(dev, vc)
+ dev_t dev;
+ struct vconsole *vc;
+{
+ struct vconsole *new;
+ register int num = minor(dev);
+
+ MALLOC(new, struct vconsole *, sizeof(struct vconsole),
+ M_DEVBUF,M_NOWAIT );
+
+ bzero ( (char *)new, sizeof(struct vconsole) );
+ *new = *vc;
+ new->number = num;
+ new->next = vconsole_head;
+ new->tp = vc->tp; /* Implied */
+ new->data=0;
+ new->t_scrolledback=0;
+ new->r_scrolledback=0;
+ new->r_data=0;
+ new->flags=LOSSY;
+ new->vtty = 0;
+ vconsole_head = new;
+ new->R_INIT ( new );
+ new->SPAWN ( new );
+ new->data = 0;
+ /*new->charmap = 0;*/
+ new->flags=LOSSY;
+ new->proc = curproc;
+ new->vtty = 0;
+ return new;
+}
+
+static struct vconsole *
+vconsole_spawn(dev, vc)
+ dev_t dev;
+ struct vconsole *vc;
+{
+ struct vconsole *new;
+ register int num = minor(dev);
+
+ if ( find_vc ( dev ) != 0 )
+ return 0;
+
+ MALLOC(new, struct vconsole *, sizeof(struct vconsole),
+ M_DEVBUF, M_NOWAIT );
+
+ bzero ( (char *)new, sizeof(struct vconsole) );
+ *new = *vc;
+ new->number = num;
+ new->next = vconsole_head;
+ new->tp=NULL;
+ new->opened=0;
+ new->data=0;
+ new->t_scrolledback=0;
+ new->r_scrolledback=0;
+ new->r_data=0;
+ new->vtty = 1;
+ vconsole_head = new;
+ new->R_INIT ( new );
+ new->FLASH ( new, 1 );
+ new->CURSOR_FLASH ( new, 1 );
+ new->SPAWN ( new );
+ new->vtty = 1;
+
+ MALLOC (new->charmap, int *, sizeof(int)*((new->xchars)*(new->ychars)),
+ M_DEVBUF, M_NOWAIT );
+
+ if (new->charmap==0)
+ return 0;
+ {
+ int counter=0;
+ for ( counter=0; counter<((new->xchars)*(new->ychars)); counter++ )
+ (new->charmap)[counter]=' ';
+ }
+ new->TERM_INIT ( new );
+ new->proc = curproc;
+ return new;
+}
+
+void
+vconsole_addcharmap(vc)
+ struct vconsole *vc;
+{
+ int counter=0;
+
+ MALLOC (vc->charmap, int *, sizeof(int)*((vc->xchars)*(vc->ychars)),
+ M_DEVBUF, M_NOWAIT );
+ for ( counter=0; counter<((vc->xchars)*(vc->ychars)); counter++ )
+ (vc->charmap)[counter]=' ';
+}
+
+int
+physconopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct vconsole *new;
+
+ struct vconsole *vc;
+ int unit = minor(dev);
+ int found=0;
+ int majorhack=0;
+ int ret;
+
+ /*
+ * To allow the raw consoles a permanat hook for ioctls
+ * Spawning another virtual console will actuall configure it
+ */
+
+ if ( unit >= NVT ) {
+ if ( find_vc(dev)==0 )
+ return ENXIO;
+ }
+/*
+ if (unit >= rpc_cd.cd_ndevs || !rpc_cd.cd_devs[unit])
+ return ENXIO;
+*/
+
+ /* If this virtual console is the real virtual console and hasn't got */
+ /* a charmap then to allocate it one. We can be sure addcharmap works */
+ /* here since this is the open routine. This is incase the console */
+ /* was initialised before the system was brought up */
+
+ if ((unit==0)&&(vconsole_master->charmap==0)) {
+ if (vconsole_master==vconsole_current)
+ majorhack=1;
+ vconsole_addcharmap ( vconsole_master );
+ vconsole_master->flags &= ~LOSSY;
+ }
+
+ /* Check to see if this console has already been spawned */
+
+ for ( vc = vconsole_head; vc!=NULL; vc=vc->next ) {
+ if ( vc->number == unit ) {
+ found=1;
+ break;
+ }
+ }
+
+ /* Sanity check. If we have no default console, set it to the master one */
+
+ if ( vconsole_default==0 )
+ vconsole_default = vconsole_master;
+
+ /* Ensure we have a vconsole structure. Allocate one if we dont already */
+
+ if (found==0)
+ new = vconsole_spawn ( dev, vconsole_default );
+ else
+ new = vc;
+
+ new->proc = p;
+
+ /* Initialise the terminal subsystem for this device */
+
+#define TP (new->tp)
+
+ if (TP == NULL)
+ TP = ttymalloc();
+
+ physcon_tty[unit] = TP;
+
+ TP->t_oproc = physconstart;
+ TP->t_param = physconparam;
+ TP->t_dev = dev;
+ if ((TP->t_state & TS_ISOPEN) == 0) {
+ TP->t_state |= TS_WOPEN;
+ ttychars(TP);
+ TP->t_iflag = TTYDEF_IFLAG;
+ TP->t_oflag = TTYDEF_OFLAG;
+ TP->t_cflag = TTYDEF_CFLAG;
+ TP->t_lflag = TTYDEF_LFLAG;
+ TP->t_ispeed = TP->t_ospeed = TTYDEF_SPEED;
+ physconparam(TP, &TP->t_termios);
+ ttsetwater(TP);
+ } else if (TP->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
+ return EBUSY;
+ TP->t_state |= TS_CARR_ON;
+
+ new->opened=1;
+
+ TP->t_winsize.ws_col = new->xchars;
+ TP->t_winsize.ws_row = new->ychars;
+ ret = ((*linesw[TP->t_line].l_open)(dev, TP));
+
+ if ( majorhack==1 ) {
+ struct vconsole *vc_store;
+ int counter;
+ int end;
+ int lines;
+ int xs;
+
+ end = msgbufp->msg_bufx-1;
+ if (end>=MSG_BSIZE) end-=MSG_BSIZE;
+
+ /*
+ * Try some cute things. Count the number of lines in the msgbuf
+ * then scroll the real screen up, just to fit the msgbuf on the
+ * screen, then sink all output, and spew the msgbuf to the
+ * new consoles charmap!
+ */
+
+ lines = 0; xs=0;
+
+ for (counter=0;counter<end;counter++) {
+ xs++;
+ if (*((msgbufp->msg_bufc)+counter)==0x0a) {
+ if (xs>vc->xchars) lines++;
+ lines++;
+ xs=0;
+ }
+ }
+
+ if ( lines < vc->ychars ) {
+ counter=vc->ycur;
+ while ( (counter--) > lines )
+ new->PUTSTRING ( "\x0a", 1, new );
+ }
+
+ new->SLEEP(new);
+
+ vc_store = vconsole_current;
+ vconsole_current = 0; /* !!! */
+
+ /* HAHA, cant do this */
+ /* new->CLS ( new ); */
+
+ new->PUTSTRING ( "\x0c", 1, new );
+
+ /*
+ * Hmmm, I could really pass the whole damn thing to putstring
+ * since it doesn't have zeros, but I need to do the crlf
+ * conversion
+ */
+
+ xs=0;
+
+ if ( end < 0 )
+ panic ( "msgbuf trashed reboot and try again" );
+
+ for (counter=0;counter<end;counter++) {
+ if (*((msgbufp->msg_bufc)+counter)==0x0a) {
+ new->PUTSTRING ( "\x0d", 1, new );
+ xs=0;
+ }
+ if ( (xs++)<new->xchars )
+ new->PUTSTRING ((msgbufp->msg_bufc)+counter, 1, new );
+ }
+ vconsole_master->ycur = lines;
+ vconsole_current = vc_store;
+ new->WAKE(new);
+ vconsole_current->xcur = 0;
+
+ printf ( "\x0a" );
+ }
+
+ return(ret);
+}
+
+/*
+ * int physconclose(dev_t dev, int flag, int mode, struct proc *p)
+ *
+ * Close the physical console
+ */
+
+int
+physconclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ register struct tty *tp;
+
+ tp = find_tp ( dev );
+ if (tp == NULL) {
+ printf("physconclose: tp=0 dev=%04x\n", dev);
+ return(ENXIO);
+ }
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ ttyclose(tp);
+
+ return(0);
+}
+
+int
+physconread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ register struct tty *tp = find_tp ( dev );
+ if (tp == NULL) {
+ printf("physconread: tp=0 dev=%04x\n", dev);
+ return(ENXIO);
+ }
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+physconwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ register struct tty *tp;
+
+ tp = find_tp(dev);
+
+ if (tp == NULL) {
+ printf("physconwrite: tp=0 dev=%04x\n", dev);
+ return(ENXIO);
+ }
+
+ return((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+struct tty *
+physcontty(dev)
+ dev_t dev;
+{
+ return(find_tp(dev));
+}
+
+int ioctlconsolebug;
+
+int
+physconioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct vconsole vconsole_new;
+ struct tty *tp=(struct tty *)0xDEADDEAD ;
+ int error;
+ int s;
+ struct vconsole *vc = find_vc(dev);
+
+ ioctlconsolebug = cmd;
+
+ tp = find_tp(dev);
+
+ if ((vc==0)||(tp==0))
+ return ENXIO;
+
+ switch ( cmd ) {
+ case CONSOLE_SWITCHUP:
+ physcon_switchup ();
+ return 0;
+ case CONSOLE_SWITCHDOWN:
+ physcon_switchdown ();
+ return 0;
+ case CONSOLE_SWITCHTO:
+ if (!physcon_switch ( *(int *)data ))
+ return 0;
+ else
+ return EINVAL;
+ case CONSOLE_SWITCHPREV:
+ physcon_switch ( lastconsole );
+ return 0;
+ case CONSOLE_CREATE:
+ if ( vconsole_spawn ( makedev ( physcon_major, *(int *)data ),
+ vconsole_default ) == 0 )
+ return ENOMEM;
+ else
+ return 0;
+ break;
+
+ case CONSOLE_RENDERTYPE:
+ strncpy ( (char *)data, vc->T_NAME, 20 );
+ return 0;
+
+ case CONSOLE_TERMTYPE:
+ strncpy ( (char *)data, vc->T_NAME, 20 );
+ return 0;
+
+ case CONSOLE_LOCK:
+ s = spltty();
+ locked++;
+ (void)splx(s);
+ return 0;
+ case CONSOLE_UNLOCK:
+ s = spltty();
+ locked--;
+ if ( locked<0 )
+ locked=0;
+ (void)splx(s);
+ return 0;
+ case CONSOLE_SPAWN_VIDC:
+/*
+ vconsole_new = *vconsole_default;
+*/
+ vconsole_new = *vc;
+ vconsole_new.render_engine = &vidcconsole;
+ if ( vconsole_spawn_re (
+ makedev ( physcon_major, *(int *)data ),
+ &vconsole_new ) == 0 )
+ return ENOMEM;
+ else
+ return 0;
+
+ case CONSOLE_GETVC:
+ {
+/* struct vconsole *vc_p;
+ vc_p = find_vc(dev);
+ *(int *)data = vc_p->number;*/
+ *(int *)data = vconsole_current->number;
+ return 0;
+ }
+
+ case CONSOLE_CURSORFLASHRATE:
+ vc->CURSORFLASHRATE ( vc, *(int *)data );
+ return 0;
+
+ case CONSOLE_BLANKTIME:
+ vconsole_blankinit = *(int *)data;
+ return 0;
+
+ case CONSOLE_DEBUGPRINT:
+ {
+ struct vconsole *vc_p;
+
+ vc_p = find_vc(makedev(physcon_major,*(int*)data));
+ if (vc_p==0) return EINVAL;
+ printf ( "DEBUGPRINT for console %d\n", *(int*)data );
+ printf ( "flags %08x vtty %01x\n", vc_p->flags, vc_p->vtty );
+ printf ( "TTY INFO - winsize (%d, %d)\n",
+ vc_p->tp->t_winsize.ws_col,
+ vc_p->tp->t_winsize.ws_row);
+ vc_p->R_DEBUGPRINT ( vc_p );
+ vc_p->T_DEBUGPRINT ( vc_p );
+ return 0;
+ }
+
+ default:
+ error = vc->IOCTL ( vc, dev, cmd, data, flag, p );
+ if ( error >=0 )
+ return error;
+ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return error;
+ error = ttioctl(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return error;
+ }
+ return(ENOTTY);
+}
+
+int
+physconmmap(dev, offset, nprot)
+ dev_t dev;
+ int offset;
+ int nprot;
+{
+ struct vconsole *vc = find_vc(dev);
+ u_int physaddr;
+
+ if (minor(dev) < 64) {
+ log(LOG_WARNING, "You should no longer use ttyv to mmap a frame buffer\n");
+ log(LOG_WARNING, "For vidc use /dev/vidcvideo0\n");
+ }
+ physaddr = vc->MMAP(vc, offset, nprot);
+ return(physaddr);
+}
+
+/*
+ * Perform output on specified tty stream
+ */
+
+void
+physconstart(tp)
+ struct tty *tp;
+{
+ int s, len;
+ struct clist *cl;
+ struct vconsole *vc;
+ u_char buf[128];
+
+ s = spltty();
+
+ vc = find_vc ( tp->t_dev );
+
+ /* Are we ready to perform output */
+
+ if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) {
+ (void)splx(s);
+ return;
+ }
+
+ tp->t_state |= TS_BUSY;
+
+ /* Fill our buffer with the data to print */
+
+ cl = &tp->t_outq;
+
+ if ( vc->r_scrolledback ) vc->R_SCROLLBACKEND ( vc );
+ if ( vc->t_scrolledback ) vc->T_SCROLLBACKEND ( vc );
+
+ (void)splx(s);
+
+ /* Apparently we do this out of spl since it _IS_ fairly expensive */
+ /* and it stops the serial ports overflowing */
+
+ while ( (len = q_to_b(cl, buf, 128)) ) {
+ if ( vc!=NULL )
+ vc->PUTSTRING(buf, len, vc);
+ }
+
+ s = spltty ();
+
+ tp->t_state &= ~TS_BUSY;
+
+ if (cl->c_cc) {
+ tp->t_state |= TS_TIMEOUT;
+ timeout(ttrstrt, tp, 1);
+ }
+
+ if (cl->c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup(cl);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+
+ if ( want_switch != -1 ) {
+ physcon_switch ( want_switch );
+ want_switch=-1;
+ }
+
+ (void)splx(s);
+}
+
+int
+physconparam(tp, t)
+ struct tty *tp;
+ struct termios *t;
+{
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+ return(0);
+}
+
+void
+physconstop(tp, flag)
+ struct tty *tp;
+ int flag;
+{
+ /* Nothing necessary */
+}
+
+int
+physconkbd(key)
+ int key;
+{
+ char *string;
+ register struct tty *tp;
+ int s;
+
+ s = spltty();
+
+ tp = vconsole_current->tp;
+
+ if (tp == NULL) return(1);
+
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ (void)splx(s);
+ return(1);
+ }
+
+ if (key < 0x100)
+ (*linesw[tp->t_line].l_rint)(key, tp);
+ else {
+ switch (key) {
+ case 0x100:
+ string = "\x1b[A";
+ break;
+ case 0x101:
+ string = "\x1b[B";
+ break;
+ case 0x102:
+ string = "\x1b[D";
+ break;
+ case 0x103:
+ string = "\x1b[C";
+ break;
+ case 0x104:
+ string = "\x1b[6~";
+ break;
+ case 0x105:
+ string = "\x1b[5~";
+ break;
+ case 0x108:
+ string = "\x1b[2~";
+ break;
+ case 0x109:
+ string = "\x7f";
+ break;
+ default:
+ string = "";
+ break;
+ }
+ while (*string != 0) {
+ (*linesw[tp->t_line].l_rint)(*string, tp);
+ ++string;
+ }
+ }
+ (void)splx(s);
+ return(0);
+}
+
+static int physconinit_called = 0;
+
+void
+physconinit(cp)
+ struct consdev *cp;
+{
+ int *test;
+ int counter;
+
+ /*
+ * Incase we're called more than once. All routines below here
+ * undergo once time initialisation
+ */
+
+ if ( physconinit_called )
+ return;
+
+ physconinit_called=1;
+
+ locked=0;
+
+ physcon_major = major ( cp->cn_dev );
+
+ /*
+ * Create the master console
+ */
+
+ vconsole_master->next = NULL;
+ vconsole_master->number = 0;
+ vconsole_master->opened = 1;
+ vconsole_master->tp = NULL;
+
+ /*
+ * Right, here I can choose some render routines
+ */
+
+ vconsole_master->render_engine = &vidcconsole;
+ vconsole_master->terminal_emulator = &vt220;
+
+ /*
+ * We will very soon loose the master console, and number 0 will
+ * become the current console so as not to waste a struct vconsole
+ */
+ vconsole_current = vconsole_head = vconsole_master;
+ vconsole_master->data = NULL;
+ vconsole_master->vtty = 1;
+
+ /*
+ * Perform initial checking
+ */
+
+ if ( vconsole_master->terminal_emulator->name == 0 )
+ vconsole_master->terminal_emulator->name = undefined_string;
+ if ( vconsole_master->render_engine->name == 0 )
+ vconsole_master->render_engine->name = undefined_string;
+
+ /*
+ * Right, I have to assume the init and print procedures are ok
+ * or there's nothing else that can be done
+ */
+
+ vconsole_master->R_INIT ( vconsole_master);
+ vconsole_master->SPAWN ( vconsole_master );
+ vconsole_master->TERM_INIT (vconsole_master);
+ vconsole_master->flags = LOSSY;
+
+ /*
+ * Now I can do some productive verification
+ */
+
+ /* Ensure there are no zeros in the termulation and render_engine */
+
+ test = (int *) vconsole_master->render_engine;
+ for ( counter=0; counter<(sizeof(struct render_engine)/4)-1; counter++ )
+ if (test[counter]==0)
+ panic ( "Render engine %i is missins a routine",
+ vconsole_master->render_engine->name );
+
+ test = (int *) vconsole_master->terminal_emulator;
+ for ( counter=0; counter<(sizeof(struct terminal_emulator)/4)-1; counter++ )
+ if (test[counter]==0)
+ panic ( "Render engine %i is missing a routine",
+ vconsole_master->terminal_emulator->name );
+}
+
+/*
+ * void physconputstring(char *string, int length)
+ *
+ * Render a string on the physical console
+ */
+
+void
+physconputstring(string, length)
+ char *string;
+ int length;
+{
+ vconsole_current->PUTSTRING(string, length, vconsole_current);
+}
+
+/*
+ * void physcongetchar(void)
+ *
+ * Get a character from the physical console
+ */
+
+int getkey_polled __P(());
+
+char
+physcongetchar(void)
+{
+ return(getkey_polled());
+}
+
+void
+consinit(void)
+{
+ static int consinit_called = 0;
+
+ if (consinit_called != 0)
+ return;
+
+ consinit_called = 1;
+ cninit();
+
+/* Ok get our start up message in early ! */
+
+ printf("\x0cRiscBSD booting...\n%s\n", version);
+}
+
+void
+rpcconsolecnprobe(cp)
+ struct consdev *cp;
+{
+ int major;
+
+/* printf("rpcconsoleprobe: pc=%08x\n", cp);*/
+
+/*
+ * Locate the major number for the physical console device
+ * We do this by searching the character device list until we find
+ * the device with the open function for the physical console
+ */
+
+ for (major = 0; major < nchrdev; ++major) {
+ if (cdevsw[major].d_open == physconopen)
+ break;
+ }
+
+/* Initialise the required fields */
+
+ cp->cn_dev = makedev(major, 0);
+ cp->cn_pri = CN_INTERNAL;
+}
+
+#define RPC_BUF_LEN (64)
+char rpc_buf[RPC_BUF_LEN];
+int rpc_buf_ptr = 0;
+
+#define RPC_BUF_FLUSH \
+{ \
+ vconsole_current->PUTSTRING ( rpc_buf, rpc_buf_ptr, vconsole_current ); \
+ rpc_buf_ptr=0; \
+}
+
+void
+rpcconsolecninit(cp)
+ struct consdev *cp;
+{
+ physconinit(cp); /* woo Woo WOO!!!, woo, woo, yes ok bye */
+}
+
+void
+rpcconsolecnputc(dev, character)
+ dev_t dev;
+ char character;
+{
+ extern int cold;
+
+ if (( rpc_buf_ptr==RPC_BUF_LEN ) || (cold==0) )
+ RPC_BUF_FLUSH
+
+ rpc_buf[rpc_buf_ptr++] = character;
+
+ if ((character == 0x0a )||(character==0x0d)||(character=='.'))
+ RPC_BUF_FLUSH
+}
+
+int
+console_switchdown()
+{
+ physcon_switchdown ();
+ return 0;
+}
+
+int
+console_switchup()
+{
+ physcon_switchup ();
+ return 0;
+}
+
+int
+console_unblank()
+{
+ vconsole_blankcounter = vconsole_blankinit;
+ vconsole_current->BLANK ( vconsole_current, BLANK_NONE );
+ return 0;
+}
+
+int
+console_scrollback ()
+{
+ if (vconsole_current==NULL)
+ return 0;
+ if ( vconsole_current->R_SCROLLBACK(vconsole_current) ==-1 ) {
+ if ( vconsole_current->T_SCROLLBACK(vconsole_current)==-1 ) {
+ }
+ }
+ return 0;
+}
+
+int
+console_scrollforward ()
+{
+ if (vconsole_current==NULL)
+ return 0;
+ if ( vconsole_current->R_SCROLLFORWARD(vconsole_current) ==-1 ) {
+ if ( vconsole_current->T_SCROLLFORWARD(vconsole_current)==-1 ) {
+ }
+ }
+ return 0;
+}
+
+int
+console_switchlast ()
+{
+ return (physcon_switch ( lastconsole ));
+}
+
+int
+physcon_switchdown ()
+{
+ int start;
+ int next = (vconsole_current->number);
+ start=next;
+ do {
+ next--;
+ next = next&0xff;
+ if (next==start) return 0;
+ } while (physcon_switch ( next ));
+ return 0;
+}
+
+int
+physcon_switchup ()
+{
+ int start;
+ int next = (vconsole_current->number);
+ start=next;
+ do {
+ next++;
+ next = next&0xff;
+ if (next==start) return 0;
+ } while (physcon_switch ( next ));
+ return 0;
+}
+
+void
+console_switch(number)
+ u_int number;
+{
+ physcon_switch ( number );
+}
+
+/* switchto */
+int
+physcon_switch(number)
+ u_int number;
+{
+ register struct vconsole *vc;
+ int s = spltty ();
+ int ret;
+
+ if ( locked!=0 ) {
+ ret=0;
+ goto out;
+ }
+
+ if ( printing ) {
+ want_switch = number;
+ ret=0;
+ goto out;
+ }
+
+ vc = find_vc ( makedev ( physcon_major, number ) );
+
+ if ( vc==0 ) {
+ ret = 1;
+ goto out;
+ }
+
+ if ( vc==vconsole_current ) {
+ ret = 1;
+ goto out;
+ }
+
+ /* Point of no return */
+
+ locked++; /* We cannot reenter this routine now */
+
+ /* De-activate the render engine functions */
+ if ( vconsole_current->vtty==1 ) {
+ vconsole_current->SLEEP(vconsole_current);
+ vconsole_current->FLASH ( vc, 0 );
+ vconsole_current->CURSOR_FLASH ( vc, 0 );
+ }
+
+ /* Swap in the new consoles state */
+
+ lastconsole = vconsole_current->number;
+ vconsole_current=vc;
+ vconsole_current->R_SWAPIN ( vc );
+
+ /* Re-activate the render engine functions */
+
+ if ( vconsole_current->vtty==1 ) {
+ vconsole_current->T_SWAPIN ( vc );
+ vconsole_current->WAKE(vconsole_current);
+ vconsole_current->FLASH ( vc, 1 );
+ vconsole_current->CURSOR_FLASH ( vc, 1 );
+ }
+
+ locked--;
+
+ /* Tell the process about the switch, like the X server */
+
+ if ( vc->proc )
+ psignal ( vc->proc, SIGIO );
+
+ ret = 0;
+out:
+ (void)splx(s);
+ return(ret);
+}
+
+char
+rpcconsolecngetc(dev)
+ dev_t dev;
+{
+ return( physcongetchar () );
+}
+
+void
+rpcconsolecnpollc(dev, on)
+ dev_t dev;
+ int on;
+{
+ RPC_BUF_FLUSH
+}
+
+int
+rpcprobe(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ return(1);
+}
+
+void
+rpcattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ printf(" riscbsd generic console driver %susing %s %s\n",
+ CONSOLE_VERSION, vconsole_master->terminal_emulator->name,
+ vconsole_master->render_engine->name);
+
+ vconsole_master->T_ATTACH(vconsole_master, parent, self, aux);
+ vconsole_master->R_ATTACH(vconsole_master, parent, self, aux);
+}
+
+/*
+struct cfattach rpc_ca = {
+ sizeof(struct device), rpcprobe, rpcattach
+};
+
+struct cfdriver rpc_cd = {
+ NULL, "rpc", DV_TTY
+};
+*/
+
+struct cfattach vt_ca = {
+ sizeof(struct device), rpcprobe, rpcattach
+};
+
+struct cfdriver vt_cd = {
+ NULL, "rpc", DV_TTY
+};
+
+extern struct terminal_emulator vt220;
+
+struct render_engine *render_engine_tab[] = {
+ &vidcconsole,
+};
+
+struct terminal_emulator *terminal_emulator_tab[] = {
+ &vt220,
+};
--- /dev/null
+/* $NetBSD: debugconsole.c,v 1.2 1996/03/18 19:33:04 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * debugconsole.c
+ *
+ * Console functions
+ *
+ * Created : 17/09/94
+ */
+
+#ifdef DEBUGTERM
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/tty.h>
+#include <machine/stdarg.h>
+#include <machine/vconsole.h>
+
+#define TOTTY 0x02
+
+/*
+ * This code allows the kernel developer to have a 'nice' virtual
+ * console for debugging information.
+ *
+ * It is more useful than say, printf since the output is
+ *
+ * a) isolated
+ *
+ */
+
+struct vconsole *debug_vc=0;
+struct tty *debug_tty=0;
+
+void
+dprintf(fmt, va_alist)
+ char *fmt;
+{
+ if ( debug_vc==0 )
+ return;
+
+ dumb_putstring ( fmt, strlen(fmt), debug_vc );
+/*
+ va_list *ap;
+
+ if ( debug_tty == NULL )
+ return;
+
+ va_start(ap, fmt);
+ kprintf(fmt, TOTTY, debug_tty, ap);
+ va_end(ap);
+*/
+}
+
+#endif
+
--- /dev/null
+/* $NetBSD: dumb.c,v 1.2 1996/03/18 19:33:05 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * dumb.c
+ *
+ * Console functions
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <machine/param.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/bootconfig.h>
+#include <machine/iomd.h>
+#include <machine/vidc.h>
+#include <machine/vconsole.h>
+
+#define TERMTYPE_PUTSTRING dumb_putstring
+#define TERMTYPE_INIT dumb_init
+
+int
+TERMTYPE_INIT(vc)
+ struct vconsole *vc;
+{
+ /* This dumb termial is so dumb it requires very little init */
+ return 0;
+}
+
+static void
+do_scrollup(vc)
+ struct vconsole *vc;
+{
+
+ if (vc==vconsole_current)
+ vc->SCROLLUP ( vc, 0, vc->ychars-1 );
+
+ vc->ycur=vc->ychars-1;
+
+ if ( ((vc->flags)&(LOSSY)) == 0 ) {
+ int counter;
+ for ( counter=vc->xchars; counter < ((vc->ychars)*(vc->xchars)); counter++ ) {
+ vc->charmap[counter-vc->xchars] = vc->charmap[counter];
+ }
+ for ( counter=vc->xchars*(vc->ychars-1); counter < (vc->xchars*vc->ychars); counter++ ) {
+ vc->charmap[counter]=0x20;
+ }
+ }
+}
+
+static int
+do_render(c, vc)
+ char c;
+ struct vconsole *vc;
+{
+ /* THE RENDER STAGE **********************************/
+ if ((c>=0x20)&&(c<=0x7f)) {
+ if (((vc->flags)&(LOSSY))==0) {
+ vc->charmap[ vc->xcur + vc->ycur*vc->xchars ] = c | 7<<8;
+ }
+
+ if ( vc==vconsole_current )
+ vc->RENDER ( vc, c );
+
+ vc->xcur++;
+ }
+
+ if ( vc->xcur >= vc->xchars ) {
+ vc->xcur=0;
+ vc->ycur++;
+ }
+
+ if ( vc->ycur >= vc->ychars ) {
+ do_scrollup ( vc );
+ vc->xcur=0;
+ vc->ycur=vc->ychars-1;
+ }
+}
+
+int
+TERMTYPE_PUTSTRING(string, length, vc)
+ char *string;
+ int length;
+ struct vconsole *vc;
+{
+ char c;
+
+ while ( ((c=*(string++))!=0) && ((length--)>0)) {
+ if ((c<31)||(c>127)) c='*';
+ switch (c) {
+ case 0x0a:
+ vc->ycur++;
+ if ( vc->ycur>=vc->ychars ) {
+ do_scrollup ( vc );
+ vc->ycur=vc->ychars-1;
+ }
+ break;
+
+ case 0x0d:
+ vc->xcur=0;
+ break;
+
+ default:
+ do_render ( c, vc );
+ break;
+ }
+ }
+}
--- /dev/null
+/* $NetBSD: font_bold.h,v 1.1 1996/01/31 23:20:07 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * font_terminal14_bold.h
+ *
+ * Font for physical console driver
+ *
+ * Created : 18/09/94
+ * Last updated : 15/10/94
+ *
+ * Based on kate/display/14bold.h
+ *
+ * $Id: font_bold.h,v 1.1.1.1 1996/04/24 11:08:37 deraadt Exp $
+ */
+
+unsigned char font_terminal_14bold_data[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x7e, 0x24, 0x7e, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x0c, 0x38, 0x60, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x6c, 0x76, 0x3c, 0x30, 0x18, 0x78, 0xdc, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x34, 0x34, 0x98, 0x7c, 0x66, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x66, 0x66, 0x66, 0x66, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x1a, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x70, 0x38, 0x1c, 0x0e, 0x66, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x38, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x70, 0x68, 0x64, 0x66, 0xfe, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x06, 0x06, 0x3e, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x8e, 0xe6, 0xb6, 0xb6, 0xe6, 0x0e, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x76, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc6, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x6e, 0x6e, 0x76, 0x76, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x3c, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x36, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x3e, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0x7c, 0x28, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x60, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x0c, 0x3e, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x46, 0x3e, 0x7c, 0x62, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3e, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x2c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x70, 0x38, 0x1c, 0x0e, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x30, 0x1c, 0x30, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0e, 0x18, 0x18, 0x0c, 0x38, 0x0c, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x4c, 0x7e, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x36, 0x36, 0x76, 0x36, 0x36, 0x36, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xd6, 0xf6, 0x16, 0xd6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c, 0x66, 0x06, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x78, 0x4c, 0x0c, 0x3e, 0x0c, 0x0c, 0xde, 0x7a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3c, 0x66, 0x0e, 0x3c, 0x66, 0x66, 0x3c, 0x70, 0x66, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc3, 0xdb, 0xcb, 0xcb, 0xdb, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1c, 0x30, 0x3c, 0x36, 0x3c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7e, 0x7e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3c, 0x7e, 0x81, 0x9d, 0xad, 0x9d, 0xad, 0x81, 0x7e, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1c, 0x32, 0x30, 0x1c, 0x06, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1c, 0x32, 0x18, 0x30, 0x32, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfe, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xfc, 0x5e, 0x5e, 0x5e, 0x5e, 0x5c, 0x58, 0x58, 0x58, 0x58, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x1c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1c, 0x36, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x0e, 0x8c, 0x4c, 0x3e, 0x10, 0x68, 0x74, 0x6a, 0xfd, 0x60, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x0e, 0x8c, 0x4c, 0x3e, 0x10, 0x68, 0xd4, 0xc2, 0x61, 0x30, 0xf0, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x1e, 0x98, 0x4c, 0x38, 0x1e, 0x6c, 0x74, 0x6a, 0xfd, 0x60, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x0c, 0x46, 0x66, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x18, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x18, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x3c, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5c, 0x3a, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x66, 0x66, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x2c, 0x2c, 0x18, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x36, 0x36, 0x76, 0x3e, 0x36, 0x36, 0xf6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x10, 0x18, 0x00, 0x00,
+ 0x00, 0x18, 0x30, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x60, 0x30, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x3c, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x18, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x18, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x3c, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x66, 0x66, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1c, 0x2c, 0x4c, 0x4c, 0x5e, 0x4c, 0x2c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5c, 0x3a, 0x00, 0x66, 0x66, 0x6e, 0x6e, 0x76, 0x76, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5c, 0x3a, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x78, 0x6c, 0x6c, 0x7c, 0x7c, 0x6c, 0x6c, 0x3c, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x3c, 0x6c, 0x6c, 0x3c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x36, 0x66, 0x66, 0x66, 0x36, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x30, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x6e, 0x3c, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xb2, 0xfc, 0x36, 0xb6, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x10, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x36, 0x36, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x1c, 0x30, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x3a, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5c, 0x3a, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x6c, 0x7c, 0x7c, 0x6c, 0x3a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x3c, 0x0c, 0x0c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+ 0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0xff, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0xff, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+font_struct font_terminal_14bold = {
+ 199,
+ 1,
+ 16,
+ 8,
+ 16,
+ 8,
+ 16,
+ 3184,
+ font_terminal_14bold_data
+};
+
+/* End of font14bold.h */
--- /dev/null
+/* $NetBSD: font_italic.h,v 1.1 1996/01/31 23:20:13 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * font_terminal14_italic.h
+ *
+ * Font for physical console driver
+ *
+ * Created : 18/09/94
+ * Last updated : 15/10/94
+ *
+ * Based on kate/display/14norm.h
+ *
+ * $Id: font_italic.h,v 1.1.1.1 1996/04/24 11:08:37 deraadt Exp $
+ */
+
+unsigned char font_terminal_14italic_data[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x18, 0x30, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x3a, 0x14, 0x10, 0x08, 0x28, 0x54, 0x24, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x14, 0x08, 0x54, 0x22, 0x22, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x38, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x28, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x3e, 0x42, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x72, 0x4a, 0x4a, 0x72, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x72, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x44, 0x24, 0x14, 0x0c, 0x0c, 0x14, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0xaa, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x4a, 0x52, 0x3c, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3c, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x92, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc6, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1c, 0x22, 0x22, 0x1c, 0x02, 0x3c, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x22, 0x12, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x92, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x4c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x3c, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x24, 0x18, 0x18, 0x24, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x08, 0x08, 0x10, 0x0c, 0x10, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x08, 0x30, 0x08, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x12, 0x12, 0x72, 0x12, 0x12, 0x12, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0xf2, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x24, 0x24, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x14, 0x54, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x08, 0x08, 0x3c, 0x08, 0x8c, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x7c, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x44, 0x44, 0x38, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0xb2, 0x8a, 0x8a, 0xb2, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x1c, 0x12, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0x9a, 0xaa, 0x9a, 0xaa, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x08, 0x04, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x24, 0x12, 0x12, 0x6d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7c, 0x2e, 0x2e, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x12, 0x0c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x48, 0x64, 0x52, 0xf8, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x68, 0x94, 0x42, 0x20, 0xf0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0c, 0x12, 0x08, 0x52, 0x2c, 0x50, 0x68, 0x54, 0xfa, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x08, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4c, 0x32, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x24, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x24, 0x18, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0x14, 0x72, 0x1e, 0x12, 0x12, 0xf2, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x10, 0x08, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x48, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x28, 0x28, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x28, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x5c, 0x48, 0x48, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4c, 0x32, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4c, 0x32, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x42, 0x62, 0x52, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x08, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x26, 0x44, 0x44, 0x44, 0x34, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x44, 0x38, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x90, 0xfc, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x08, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x12, 0x0c, 0x0c, 0x12, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7c, 0x62, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x30, 0x10, 0x12, 0x0c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x28, 0x10, 0x12, 0x0c, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+ 0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0xff, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0xff, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+font_struct font_terminal_14italic = {
+ 199,
+ 1,
+ 16,
+ 8,
+ 16,
+ 8,
+ 16,
+ 3184,
+ font_terminal_14italic_data
+};
+
+/* End of font14norm.h */
--- /dev/null
+/* $NetBSD: font_normal.h,v 1.1 1996/01/31 23:20:16 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * font_terminal14_normal.h
+ *
+ * Font for physical console driver
+ *
+ * Created : 18/09/94
+ * Last updated : 15/10/94
+ *
+ * Based on kate/display/14norm.h
+ *
+ * $Id: font_normal.h,v 1.1.1.1 1996/04/24 11:08:38 deraadt Exp $
+ */
+
+unsigned char font_terminal_14normal_data[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x18, 0x30, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x3a, 0x14, 0x10, 0x08, 0x28, 0x54, 0x24, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x14, 0x08, 0x54, 0x22, 0x22, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x38, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x28, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x3e, 0x42, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x72, 0x4a, 0x4a, 0x72, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x72, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x44, 0x24, 0x14, 0x0c, 0x0c, 0x14, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0xaa, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x4a, 0x52, 0x3c, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3c, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x92, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc6, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1c, 0x22, 0x22, 0x1c, 0x02, 0x3c, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x22, 0x12, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x92, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x4c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x3c, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x24, 0x18, 0x18, 0x24, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x42, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x08, 0x08, 0x10, 0x0c, 0x10, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x08, 0x30, 0x08, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x4c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x12, 0x12, 0x72, 0x12, 0x12, 0x12, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0xf2, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x24, 0x24, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x14, 0x54, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x08, 0x08, 0x3c, 0x08, 0x8c, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x7c, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x44, 0x44, 0x38, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0xb2, 0x8a, 0x8a, 0xb2, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x1c, 0x12, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0x9a, 0xaa, 0x9a, 0xaa, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x08, 0x04, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x24, 0x12, 0x12, 0x6d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7c, 0x2e, 0x2e, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x12, 0x0c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x48, 0x64, 0x52, 0xf8, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x68, 0x94, 0x42, 0x20, 0xf0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0c, 0x12, 0x08, 0x52, 0x2c, 0x50, 0x68, 0x54, 0xfa, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x08, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4c, 0x32, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x24, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x24, 0x18, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0x14, 0x72, 0x1e, 0x12, 0x12, 0xf2, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x10, 0x08, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x48, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x28, 0x28, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x28, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x5c, 0x48, 0x48, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4c, 0x32, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4c, 0x32, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x42, 0x62, 0x52, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x08, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x26, 0x44, 0x44, 0x44, 0x34, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x44, 0x38, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x90, 0xfc, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x08, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x12, 0x0c, 0x0c, 0x12, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7c, 0x62, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x30, 0x10, 0x12, 0x0c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x28, 0x10, 0x12, 0x0c, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+ 0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0xff, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0xff, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+font_struct font_terminal_14normal = {
+ 199,
+ 1,
+ 16,
+ 8,
+ 16,
+ 8,
+ 16,
+ 3184,
+ font_terminal_14normal_data
+};
+
+/* End of font14norm.h */
--- /dev/null
+/* $NetBSD: font_wide.h,v 1.1 1996/01/31 23:20:22 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * font_terminal14_wide.h
+ *
+ * Font for physical console driver
+ *
+ * Created : 18/09/94
+ * Last updated : 15/10/94
+ *
+ * Based on kate/display/14widen.h
+ *
+ * $Id: font_wide.h,v 1.1.1.1 1996/04/24 11:08:38 deraadt Exp $
+ */
+
+unsigned char font_terminal_14widen_data[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60,
+ 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x98, 0x01, 0xfe, 0x07, 0x98,
+ 0x01, 0xfe, 0x07, 0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xfc, 0x03, 0x66, 0x04, 0xfc,
+ 0x03, 0x60, 0x06, 0x66, 0x06, 0xfc, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x06, 0x44, 0x03, 0xb8, 0x01, 0xc0,
+ 0x00, 0x60, 0x00, 0xb0, 0x03, 0x58, 0x04, 0x8c, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0xf0,
+ 0x04, 0x8c, 0x05, 0x06, 0x03, 0x06, 0x03, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30,
+ 0x00, 0x30, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x66, 0x06, 0xf8, 0x01, 0xf8,
+ 0x01, 0x66, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe,
+ 0x07, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0,
+ 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78,
+ 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x00, 0x06, 0x80,
+ 0x03, 0xe0, 0x01, 0x78, 0x00, 0x1e, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x00, 0x06, 0xe0,
+ 0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x01, 0xa0, 0x01, 0x90,
+ 0x01, 0x88, 0x01, 0x84, 0x01, 0xfe, 0x07, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x06, 0x00, 0x06, 0x00, 0xfe,
+ 0x03, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x0c, 0x00, 0x06, 0x00, 0xfe,
+ 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x03, 0x80, 0x01, 0xc0,
+ 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0xfc,
+ 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0xfc, 0x07, 0x00, 0x06, 0x00, 0x03, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x30,
+ 0x00, 0x0c, 0x00, 0x30, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x30, 0x00, 0xc0,
+ 0x00, 0x00, 0x03, 0xc0, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x00, 0x06, 0xc0,
+ 0x03, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0xc6, 0x07, 0x66,
+ 0x06, 0x66, 0x06, 0xc6, 0x07, 0x06, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x0c,
+ 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0xfe,
+ 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x00, 0x06,
+ 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x0c, 0x00, 0x0c, 0x00, 0xfc,
+ 0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x0c, 0x00, 0x0c, 0x00, 0x0c,
+ 0x00, 0xfc, 0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x00, 0x06,
+ 0x00, 0x86, 0x07, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfe,
+ 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x60, 0x00, 0x60, 0x00, 0x60,
+ 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0x01, 0x86, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x86, 0x01, 0x66, 0x00, 0x1e,
+ 0x00, 0x1e, 0x00, 0x66, 0x00, 0x86, 0x01, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c,
+ 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0e, 0x07, 0x9e, 0x07, 0xf6,
+ 0x06, 0x66, 0x06, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0e, 0x06, 0x1e, 0x06, 0x36,
+ 0x06, 0x66, 0x06, 0xc6, 0x06, 0x86, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0xfe, 0x03, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x86, 0x07, 0xfc, 0x03, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0xfe, 0x03, 0x86, 0x01, 0x06, 0x03, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x00, 0xfc,
+ 0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x60, 0x00, 0x60, 0x00, 0x60,
+ 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66,
+ 0x06, 0x66, 0x06, 0xf6, 0x06, 0x9c, 0x03, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0,
+ 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0,
+ 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x60,
+ 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30,
+ 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xf0, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60,
+ 0x00, 0xc0, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
+ 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf8, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x98, 0x01, 0x06, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00,
+ 0x06, 0xfc, 0x07, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x0d, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xf6, 0x03, 0x0e,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x0e, 0x06, 0xf6, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06,
+ 0x06, 0x06, 0x00, 0x06, 0x00, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0xfc, 0x06, 0x06,
+ 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xfc, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06,
+ 0x06, 0xfe, 0x07, 0x06, 0x00, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x18, 0x00, 0x18, 0x00, 0xfe,
+ 0x03, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x07, 0x00, 0x06, 0x00, 0x03, 0xfc, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xf6, 0x03, 0x0e,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x78, 0x00, 0x60,
+ 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xf8, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x86, 0x01, 0x66,
+ 0x00, 0x1e, 0x00, 0x66, 0x00, 0x86, 0x01, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60,
+ 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x03, 0x66,
+ 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x03, 0x0e,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x03, 0x0e,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x0e, 0x06, 0xf6, 0x03, 0x06, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06,
+ 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xfc, 0x06, 0x00, 0x06, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x03, 0x38,
+ 0x06, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06,
+ 0x04, 0xfc, 0x03, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0xfe, 0x01, 0x18,
+ 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xfc, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06,
+ 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06,
+ 0x06, 0x66, 0x06, 0x66, 0x06, 0xf6, 0x06, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x07, 0x98,
+ 0x01, 0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0e, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06,
+ 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x1c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00,
+ 0x07, 0xc0, 0x01, 0x70, 0x00, 0x1c, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x30, 0x00, 0x30, 0x00, 0x60, 0x00, 0x3c,
+ 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xe0, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0,
+ 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x80,
+ 0x07, 0xc0, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x66, 0x06, 0xc6, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x66, 0x00, 0x66, 0x00, 0xe6,
+ 0x01, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x66,
+};
+
+font_struct font_terminal_14widen = {
+ 193,
+ 2,
+ 13,
+ 12,
+ 13,
+ 12,
+ 13,
+ 5018,
+ font_terminal_14widen_data
+};
+
+/* End of font14widen.h */
--- /dev/null
+/* $NetBSD: vidc.c,v 1.2 1996/03/18 19:33:07 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * vidc.c
+ *
+ * Old console ioctl declarations
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/types.h>
+#include <machine/vidc.h>
+#include <machine/katelib.h>
+
+/* VIDC STUFF */
+
+/*
+ * A structure containing ALL the information required to restore
+ * the VIDC20 to any given state. ALL vidc transactions should
+ * go through these procedures, which record the vidc's state.
+ * it may be an idea to set the permissions of the vidc base address
+ * so we get a fault, so the fault routine can record the state but
+ * I guess that's not really necessary for the time being, since we
+ * can make the kernel more secure later on. Also, it is possible
+ * to write a routine to allow 'reading' of the vidc registers.
+ */
+
+struct vidc_state vidc_lookup = {
+ { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
+ },
+
+ VIDC_PALREG,
+ VIDC_BCOL,
+ VIDC_CP1 ,
+ VIDC_CP2,
+ VIDC_CP3,
+ VIDC_HCR,
+ VIDC_HSWR,
+ VIDC_HBSR,
+ VIDC_HDSR,
+ VIDC_HDER,
+ VIDC_HBER,
+ VIDC_HCSR,
+ VIDC_HIR,
+ VIDC_VCR,
+ VIDC_VSWR,
+ VIDC_VBSR,
+ VIDC_VDSR,
+ VIDC_VDER,
+ VIDC_VBER,
+ VIDC_VCSR,
+ VIDC_VCER,
+ VIDC_EREG,
+ VIDC_FSYNREG,
+ VIDC_CONREG,
+ VIDC_DCTL
+};
+
+struct vidc_state vidc_current[1];
+
+int
+vidc_write(reg, value)
+ u_int reg;
+ int value;
+{
+ int counter;
+
+ int *current;
+ int *tab;
+
+ tab = (int *)&vidc_lookup;
+ current = (int *)vidc_current;
+
+ /* End higly doddgy code */
+/*
+WriteWord ( VIDC_BASE, reg | value );
+return 1;
+*/
+
+ /*
+ * OK, the VIDC_PALETTE register is handled differently
+ * to the others on the VIDC, so take that into account here
+ */
+ if (reg==VIDC_PALREG) {
+ vidc_current->palreg = 0;
+ WriteWord ( VIDC_BASE, reg | value );
+ return 0;
+ }
+
+ if (reg==VIDC_PALETTE) {
+ WriteWord ( VIDC_BASE, reg | value );
+ vidc_current->palette[vidc_current->palreg] = value;
+ vidc_current->palreg++;
+ vidc_current->palreg = vidc_current->palreg & 0xff;
+ return 0;
+ }
+
+ /*
+ * Undefine SAFER if you wish to speed things up (a little)
+ * although this means the function will assume things abou
+ * the structure of vidc_state. i.e. the first 256 words are
+ * the palette array
+ */
+
+#define SAFER
+
+#ifdef SAFER
+#define INITVALUE 0
+#else
+#define INITVALUE 256
+#endif
+
+ for ( counter=INITVALUE; counter<= sizeof(struct vidc_state); counter++ ) {
+ if ( reg==tab[counter] ) {
+ WriteWord ( VIDC_BASE, reg | value );
+ current[counter] = value;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void
+vidc_setpalette(vidc)
+ struct vidc_state *vidc;
+{
+ int counter = 0;
+
+ vidc_write(VIDC_PALREG, 0x00000000);
+ for (counter = 0; counter < 255; counter++)
+ vidc_write(VIDC_PALETTE, vidc->palette[counter]);
+}
+
+void
+vidc_setstate(vidc)
+ struct vidc_state *vidc;
+{
+ vidc_write ( VIDC_PALREG, vidc->palreg );
+ vidc_write ( VIDC_BCOL, vidc->bcol );
+ vidc_write ( VIDC_CP1, vidc->cp1 );
+ vidc_write ( VIDC_CP2, vidc->cp2 );
+ vidc_write ( VIDC_CP3, vidc->cp3 );
+ vidc_write ( VIDC_HCR, vidc->hcr );
+ vidc_write ( VIDC_HSWR, vidc->hswr );
+ vidc_write ( VIDC_HBSR, vidc->hbsr );
+ vidc_write ( VIDC_HDSR, vidc->hdsr );
+ vidc_write ( VIDC_HDER, vidc->hder );
+ vidc_write ( VIDC_HBER, vidc->hber );
+ vidc_write ( VIDC_HCSR, vidc->hcsr );
+ vidc_write ( VIDC_HIR, vidc->hir );
+ vidc_write ( VIDC_VCR, vidc->vcr );
+ vidc_write ( VIDC_VSWR, vidc->vswr );
+ vidc_write ( VIDC_VBSR, vidc->vbsr );
+ vidc_write ( VIDC_VDSR, vidc->vdsr );
+ vidc_write ( VIDC_VDER, vidc->vder );
+ vidc_write ( VIDC_VBER, vidc->vber );
+ vidc_write ( VIDC_VCSR, vidc->vcsr );
+ vidc_write ( VIDC_VCER, vidc->vcer );
+/*
+ * Right, dunno what to set these to yet, but let's keep RiscOS's
+ * ones for now, until the time is right to finish this code
+ */
+
+/* vidc_write ( VIDC_EREG, vidc->ereg ); */
+/* vidc_write ( VIDC_FSYNREG, vidc->fsynreg ); */
+/* vidc_write ( VIDC_CONREG, vidc->conreg ); */
+/* vidc_write ( VIDC_DCTL, vidc->dctl ); */
+
+}
+
+
+void
+vidc_getstate(vidc)
+ struct vidc_state *vidc;
+{
+ *vidc = *vidc_current;
+}
+
+void
+vidc_stdpalette()
+{
+ WriteWord(VIDC_BASE, VIDC_PALREG | 0x00000000);
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL( 0, 0, 0));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 0, 0));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL( 0, 255, 0));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 0));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL( 0, 0, 255));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 0, 255));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL( 0, 255, 255));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 255));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 128, 128));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 128, 128));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 255, 128));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 128));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 128, 255));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 128, 255));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 255, 255));
+ WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 255));
+}
+
+#if 0
+int
+vidc_col(red, green, blue)
+ int red;
+ int green;
+ int blue;
+{
+ red = red & 0xFF;
+ green = green & 0xFF;
+ blue = blue & 0xFF;
+
+ return ( (blue<<16) + (green<<8) + red );
+}
+
+#endif
--- /dev/null
+/* $NetBSD: vidc_mc.S,v 1.3 1996/03/18 19:33:08 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * vidc_mc.S
+ *
+ * Console assembly functions
+ *
+ * Created : 17/09/94
+ */
+
+#include "assym.h"
+#include <machine/iomd.h>
+
+lr .req r14
+pc .req r15
+sp .req r13
+
+.text
+ .global _vidcconsole_loadtab
+_vidcconsole_loadtab:
+ mov r0, r0
+ ldmia r0!, { r2 }
+ ldmia r0!, { r2-r3 }
+ ldmia r0!, { r2-r4 }
+ ldmia r0!, { r2-r5 }
+ ldmia r0!, { r2-r6 }
+ ldmia r0!, { r2-r7 }
+ ldmia r0!, { r2-r8 }
+ ldmia r0!, { r2-r9 }
+ ldmia r0!, { r2-r10 }
+ ldmia r0!, { r2-r11 }
+ ldmia r0!, { r2-r12 }
+ ldmia r0!, { r2-r12, r14 }
+
+ .global _vidcconsole_storetab
+_vidcconsole_storetab:
+ mov r0, r0
+ stmia r0!, { r2 }
+ stmia r0!, { r2-r3 }
+ stmia r0!, { r2-r4 }
+ stmia r0!, { r2-r5 }
+ stmia r0!, { r2-r6 }
+ stmia r0!, { r2-r7 }
+ stmia r0!, { r2-r8 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r10 }
+ stmia r0!, { r2-r11 }
+ stmia r0!, { r2-r12 }
+ stmia r0!, { r2-r12, r14 }
+
+ .global _vidcconsole_pushtab
+_vidcconsole_pushtab:
+ mov r0, r0
+ stmfd r13!, { r0-r3 }
+ stmfd r13!, { r0-r7 }
+ stmfd r13!, { r0-r11 }
+ stmfd r13!, { r0-r14 }
+
+ .global _vidcconsole_poptab
+_vidcconsole_poptab:
+ mov r0, r0
+ ldmfd r13!, { r0-r3 }
+ ldmfd r13!, { r0-r7 }
+ ldmfd r13!, { r0-r11 }
+ ldmfd r13!, { r0-r14 }
+
+ .global _vidcconsole_enter
+_vidcconsole_enter:
+ stmfd r13!, { r15 }
+
+ .global _vidcconsole_exit
+_vidcconsole_exit:
+ stmfd r13!, { r15 }
+
+ .global _vidcconsolemc_render
+
+ /* On entry r0 = addr */
+ /* r1 = font */
+ /* r2 = col */
+ /* r3 = xres */
+
+ /* Optimise for 8x16 font */
+ /* At the moment */
+
+_vidcconsolemc_render:
+
+ stmfd r13!, {r0-r9, lr}
+
+ /* Generate colour mask */
+
+ mov r9, r2, lsr #16
+ mov r4, r2, lsr #8
+ and r9, r9, #0xff
+ and r4, r4, #0xff
+ and r2, r2, #0xff
+
+ /* For each row (8 pixels) */
+
+xloop:
+ ldrb r5, [r1], #1
+
+ mov r7, #0
+ mov r8, #0
+
+/* This loop will get *SOOOO* much faster with */
+/* the new algorithmn */
+ tst r5, #8
+ orrne r7, r2, r7, lsl #8
+ orreq r7, r4, r7, lsl #8
+ tst r5, #4
+ orrne r7, r2, r7, lsl #8
+ orreq r7, r4, r7, lsl #8
+ tst r5, #2
+ orrne r7, r2, r7, lsl #8
+ orreq r7, r4, r7, lsl #8
+ tst r5, #1
+ orrne r7, r2, r7, lsl #8
+ orreq r7, r4, r7, lsl #8
+ tst r5, #0x80
+ orrne r8, r2, r8, lsl #8
+ orreq r8, r4, r8, lsl #8
+ tst r5, #0x40
+ orrne r8, r2, r8, lsl #8
+ orreq r8, r4, r8, lsl #8
+ tst r5, #0x20
+ orrne r8, r2, r8, lsl #8
+ orreq r8, r4, r8, lsl #8
+ tst r5, #0x10
+ orrne r8, r2, r8, lsl #8
+ orreq r8, r4, r8, lsl #8
+
+ stmia r0, {r7, r8}
+ add r0, r0, r3
+
+ subs r9, r9, #1
+ bne xloop
+
+ ldmfd r13!, {r0-r9, pc}
+
+ .global _vidcconsolemc_cls
+
+ /* On entry r0 = start */
+ /* r1 = end */
+ /* r2 = col */
+
+
+_vidcconsolemc_cls:
+ stmfd r13!, {r0-r9, lr}
+
+ mov r3, r2
+ mov r4, r2
+ mov r5, r2
+ mov r6, r2
+ mov r7, r2
+ mov r8, r2
+ mov r9, r2
+
+loop:
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+ stmia r0!, { r2-r9 }
+
+ cmp r0, r1
+ ble loop
+
+ ldmfd r13!, {r0-r9, pc}
+
--- /dev/null
+/* $NetBSD: vidcconsole.c,v 1.7 1996/03/28 21:18:40 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Robert Black
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * vidcconsole.c
+ *
+ * Console assembly functions
+ *
+ * Created : 17/09/94
+ * Last updated : 07/02/96
+ */
+
+/* woo */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/conf.h>
+#include <sys/tty.h>
+#include <sys/device.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/syslog.h>
+#include <sys/resourcevar.h>
+#include <vm/vm.h>
+
+#include <machine/cpu.h>
+#include <machine/param.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/bootconfig.h>
+#include <machine/iomd.h>
+#include <machine/irqhandler.h>
+#include <machine/pmap.h>
+#include <machine/vidc.h>
+#include <machine/vconsole.h>
+
+#include <arm32/dev/console/fonts/font_normal.h>
+#include <arm32/dev/console/fonts/font_bold.h>
+#include <arm32/dev/console/fonts/font_italic.h>
+
+
+#define BCOPY bcopy
+
+#ifndef DEBUGTERM
+#define dprintf(x) ;
+#endif
+
+/* Options ************************************/
+#define ACTIVITY_WARNING
+#define SCREENBLANKER
+#undef INVERSE_CONSOLE
+/**********************************************/
+
+/* Internal defines only **********************/
+#define DEVLOPING
+#undef SELFTEST
+#undef SILLIES
+/**********************************************/
+
+#ifdef SILLIES
+#define PRETTYCURSOR
+#endif
+
+extern int physcon_major;
+extern struct vconsole *vconsole_default;
+
+extern videomemory_t videomemory;
+
+extern font_struct font_terminal_14normal;
+extern font_struct font_terminal_14bold;
+extern font_struct font_terminal_14italic;
+
+#define font_normal font_terminal_14normal
+#define font_bold font_terminal_14bold
+#define font_italic font_terminal_14italic
+
+#define VIDC_ENGINE_NAME "VIDC"
+#define R_DATA ((struct vidc_info *)vc->r_data)
+#define MODE (R_DATA->mode)
+
+static int cold_init = 0;
+
+extern struct vconsole *vconsole_master;
+extern struct vconsole *vconsole_current;
+static struct vidc_mode vidc_initialmode;
+static struct vidc_mode *vidc_currentmode;
+
+unsigned int dispstart;
+unsigned int dispsize;
+unsigned int dispbase;
+unsigned int dispend;
+unsigned int ptov;
+unsigned int transfersize;
+unsigned int vmem_base;
+unsigned int phys_base;
+int flash;
+int cursor_flash;
+char *cursor_normal;
+char *cursor_transparent;
+int p_cursor_normal;
+int p_cursor_transparent;
+
+/* Local function prototypes */
+static void vidcconsole_cls __P(( struct vconsole */*vc*/ ));
+static int vidc_cursor_init __P(( struct vconsole */*vc*/ ));
+static int vidcconsole_cursorintr __P(( struct vconsole */*vc*/ ));
+int vidcconsole_flashintr __P(( struct vconsole */*vc*/ ));
+static int vidcconsole_textpalette __P(( struct vconsole */*vc*/ ));
+static void vidcconsole_render __P(( struct vconsole */*vc*/, char /*c*/ ));
+static void vidcconsole_mode __P(( struct vconsole */*vc*/, struct vidc_mode */*mode*/ ));
+int vidcconsole_flash __P(( struct vconsole */*vc*/, int /*flash*/ ));
+int vidcconsole_cursorflash __P(( struct vconsole */*vc*/, int /*flash*/ ));
+int vidcconsole_flash_go __P(( struct vconsole */*vc*/ ));
+int vidcconsole_blank __P(( struct vconsole */*vc*/, int /*type*/ ));
+void vidcconsole_putchar __P(( dev_t dev, char c, struct vconsole *vc));
+extern int vidcconsolemc_cls __P(( unsigned char *, unsigned char *, int ));
+
+void (*line_cpfunc) __P(( char *, char * ));
+
+/*
+ * This will be called while still in the mode that we were left
+ * in after exiting from riscos
+ */
+
+static irqhandler_t cursor_ih;
+irqhandler_t flash_ih;
+
+
+#ifndef HARDCODEDMODES
+/* The table of modes is separately compiled */
+extern struct vidc_mode vidcmodes[];
+#else /* HARDCODEDMODES */
+#ifdef RC7500
+static struct vidc_mode vidcmodes[] = {
+ {31500,/**/48, 84, 30, 640, 30, 0,/**/3, 28, 0, 480, 0, 9,/**/0,/**/3},
+ {36000,/**/72, 84, 34, 800, 34, 0,/**/2, 22, 0, 600, 0, 1,/**/0,/**/3},
+};
+#else /* RC7500 */
+/* We have a hard compiled table of modes and a list of definable modes */
+static struct vidc_mode vidcmodes[] = {
+ {32500,/**/52, 64, 30, 640, 30, 14,/**/3, 28, 0, 480, 0, 9,/**/0,/**/3},
+ {65000,/**/128, 36, 60, 1024, 60 ,36,/**/6, 29, 0, 768, 0, 3,/**/0,/**/3},
+};
+#endif /* RC7500 */
+#endif /* HARDCODEDMODES */
+
+#ifdef RC7500
+struct vfreq {
+ u_int frqcon;
+ int freq;
+};
+
+static struct vfreq vfreq[] = {
+ { VIDFREQ_25_18, 25175},
+ { VIDFREQ_25_18, 25180},
+ { VIDFREQ_28_32, 28320},
+ { VIDFREQ_31_50, 31500},
+ { VIDFREQ_36_00, 36000},
+ { VIDFREQ_40_00, 40000},
+ { VIDFREQ_44_90, 44900},
+ { VIDFREQ_50_00, 50000},
+ { VIDFREQ_65_00, 65000},
+ { VIDFREQ_72_00, 72000},
+ { VIDFREQ_75_00, 75000},
+ { VIDFREQ_77_00, 77000},
+ { VIDFREQ_80_00, 80000},
+ { VIDFREQ_94_50, 94500},
+ { VIDFREQ_110_0, 110000},
+ { VIDFREQ_120_0, 120000},
+ { VIDFREQ_130_0, 130000}
+};
+
+#define NFREQ (sizeof (vfreq) / sizeof(struct vfreq))
+u_int vfreqcon = 0;
+#else /* RC7500 */
+
+struct fsyn {
+ int r, v, f;
+};
+
+static struct fsyn fsyn_pref[] = {
+ { 6, 2, 8000 },
+ { 4, 2, 12000 },
+ { 3, 2, 16000 },
+ { 2, 2, 24000 },
+ { 41, 43, 25171 },
+ { 50, 59, 28320 },
+ { 3, 4, 32000 },
+ { 2, 3, 36000 },
+ { 31, 58, 44903 },
+ { 12, 35, 70000 },
+ { 0, 0, 00000 }
+};
+#endif /* RC7500 */
+
+static inline int
+mod ( int n )
+{
+ if (n<0) return (-n);
+ else return n;
+}
+
+static int
+vidcconsole_coldinit(vc)
+ struct vconsole *vc;
+{
+ int found;
+ int loop;
+
+ line_cpfunc = NULL;
+
+ /* Do this first so it dont look messy */
+
+ vidc_write ( VIDC_CP1, 0x0 );
+ vidc_write ( VIDC_CP2, 0x0 );
+ vidc_write ( VIDC_CP3, 0x0 );
+
+ /* Try to determine the current mode */
+ vidc_initialmode.hder = bootconfig.width+1;
+ vidc_initialmode.vder = bootconfig.height+1;
+/*
+ vidc_initialmode.hder = 1024;
+ vidc_initialmode.vder = 768;
+*/
+ vidc_initialmode.bitsperpixel = 1 << bootconfig.bitsperpixel;
+
+/* Nut - should be using videomemory.vidm_vbase - mark */
+
+ dispbase = vmem_base = dispstart = bootconfig.display_start;
+ phys_base = videomemory.vidm_pbase;
+
+/* Nut - should be using videomemory.vidm_size - mark */
+
+#ifdef RC7500
+ dispsize = videomemory.vidm_size;
+ transfersize = 16;
+#else /* RC7500 */
+ dispsize = bootconfig.vram[0].pages * NBPG;
+ transfersize = dispsize >> 10;
+#endif /* RC7500 */
+
+ ptov = dispbase - phys_base;
+
+ dispend = dispstart+dispsize;
+
+ vidc_currentmode = &vidcmodes[0];
+ loop = 0;
+ found = 0;
+
+ while (vidcmodes[loop].pixel_rate != 0) {
+ if (vidcmodes[loop].hder == (bootconfig.width + 1)
+ && vidcmodes[loop].vder == (bootconfig.height + 1)
+ && vidcmodes[loop].frame_rate == bootconfig.framerate) {
+ vidc_currentmode = &vidcmodes[loop];
+ found = 1;
+ }
+ ++loop;
+ }
+
+ if (!found) {
+ vidc_currentmode = &vidcmodes[0];
+ loop = 0;
+ found = 0;
+
+ while (vidcmodes[loop].pixel_rate != 0) {
+ if (vidcmodes[loop].hder == (bootconfig.width + 1)
+ && vidcmodes[loop].vder == (bootconfig.height + 1)) {
+ vidc_currentmode = &vidcmodes[loop];
+ found = 1;
+ }
+ ++loop;
+ }
+ }
+
+ /* vidc_currentmode = &vidcmodes[0];*/
+ vidc_currentmode->bitsperpixel = 1 << bootconfig.bitsperpixel;
+
+ R_DATA->flash = R_DATA->cursor_flash = 0;
+
+ dispstart = dispbase;
+ dispend = dispstart+dispsize;
+
+ WriteWord ( IOMD_VIDINIT, dispstart-ptov );
+ WriteWord ( IOMD_VIDSTART, dispstart-ptov );
+ WriteWord ( IOMD_VIDEND, (dispend-transfersize)-ptov );
+ return 0;
+}
+
+struct vidc_mode newmode;
+
+static const int bpp_mask_table[] = {
+ 0, /* 1bpp */
+ 1, /* 2bpp */
+ 2, /* 4bpp */
+ 3, /* 8bpp */
+ 4, /* 16bpp */
+ 6 /* 32bpp */
+};
+
+void
+vidcconsole_mode(vc, mode)
+ struct vconsole *vc;
+ struct vidc_mode *mode;
+{
+ register int acc;
+ int bpp_mask;
+ int log_bpp;
+ int tmp_bpp;
+
+#ifndef RC7500
+ int best_r, best_v, best_match;
+#endif
+
+/*
+ * Find out what bit mask we need to or with the vidc20 control register
+ * in order to generate the desired number of bits per pixel.
+ * log_bpp is log base 2 of the number of bits per pixel.
+ */
+
+ tmp_bpp = mode->bitsperpixel;
+ if (tmp_bpp < 1 || tmp_bpp > 32)
+ tmp_bpp = 8; /* Set 8 bpp if we get asked for something silly */
+
+ for (log_bpp = 0; tmp_bpp != 1; tmp_bpp >>= 1)
+ log_bpp++;
+
+ bpp_mask = bpp_mask_table[log_bpp];
+
+/*
+ printf ( "res = (%d, %d) rate = %d\n", mode->hder, mode->vder, mode->pixel_rate );
+*/
+
+ newmode = *mode;
+ vidc_currentmode = &newmode;
+
+#ifdef RC7500
+ {
+ int i;
+ int old, new;
+ u_int nfreq;
+
+ old = vfreq[0].freq;
+ nfreq = vfreq[0].frqcon;
+ for (i = 0; i < (NFREQ - 1); i++) {
+ new = vfreq[i].freq - mode->pixel_rate;
+ if (new < 0)
+ new = -new;
+ if (new < old) {
+ nfreq = vfreq[i].frqcon;
+ old = new;
+ }
+ if (new == 0)
+ break;
+ }
+ nfreq |= (vfreqcon & 0xf0);
+ vfreqcon = nfreq;
+ }
+#else /* RC7500 */
+ /* Program the VCO Look up a preferred value before choosing one */
+ {
+ int least_error = mod (fsyn_pref[0].f - vidc_currentmode->pixel_rate);
+ int counter;
+ best_r = fsyn_pref[0].r;
+ best_match = fsyn_pref[0].f;
+ best_v = fsyn_pref[0].v;
+
+ /* Look up */
+
+ counter=0;
+
+ while ( fsyn_pref[counter].r != 0 ) {
+ if (least_error > mod (fsyn_pref[counter].f - vidc_currentmode->pixel_rate)) {
+ best_match = fsyn_pref[counter].f;
+ least_error = mod (fsyn_pref[counter].f - vidc_currentmode->pixel_rate);
+ best_r = fsyn_pref[counter].r;
+ best_v = fsyn_pref[counter].v;
+ }
+ counter++;
+ }
+
+ if ( least_error > 0) { /* Accuracy of 1000Hz */
+ int r, v, f;
+ for ( v=63; v>0; v-- )
+ for ( r=63; r>0; r-- ) {
+ f = (v * VIDC_FREF/1000) / r;
+ if (least_error >= mod (f - vidc_currentmode->pixel_rate)) {
+ best_match = f;
+ least_error = mod (f - vidc_currentmode->pixel_rate);
+ best_r = r;
+ best_v = v;
+ }
+ }
+ }
+
+ if ( best_r>63 ) best_r=63;
+ if ( best_v>63 ) best_v=63;
+ if ( best_r<1 ) best_r= 1;
+ if ( best_v<1 ) best_v= 1;
+
+ }
+/*
+ printf ( "best_v = %d best_r = %d best_f = %d\n", best_v, best_r, best_match );
+*/
+#endif /* RC7500 */
+
+ if (vc==vconsole_current) {
+#ifdef RC7500
+ outb(FREQCON, vfreqcon);
+ /*
+ * Need to program the control register first.
+ */
+ if ( dispsize>1024*1024 ) {
+ if ( vidc_currentmode->hder>=800 )
+ vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5);
+ else
+ vidc_write ( VIDC_CONREG, 6<<8 | bpp_mask<<5);
+ } else {
+ vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5);
+ }
+
+ /*
+ * We don't use VIDC_FSYNREG. Program it low.
+ */
+ vidc_write(VIDC_FSYNREG, 0x2020);
+#else /* RC7500 */
+ vidc_write ( VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0 );
+#endif /* RC7500 */
+ acc=0;
+ acc+=vidc_currentmode->hswr;vidc_write(VIDC_HSWR,(acc - 8 )& (~1) );
+ acc+=vidc_currentmode->hbsr;vidc_write(VIDC_HBSR,(acc - 12 )& (~1) );
+ acc+=vidc_currentmode->hdsr;vidc_write(VIDC_HDSR,(acc - 18 )& (~1) );
+ acc+=vidc_currentmode->hder;vidc_write(VIDC_HDER,(acc - 18 )& (~1) );
+ acc+=vidc_currentmode->hber;vidc_write(VIDC_HBER,(acc - 12 )& (~1) );
+ acc+=vidc_currentmode->hcr ;vidc_write(VIDC_HCR ,(acc - 8)&(~3));
+
+ acc=0;
+ acc+=vidc_currentmode->vswr; vidc_write(VIDC_VSWR,(acc - 1 ));
+ acc+=vidc_currentmode->vbsr; vidc_write(VIDC_VBSR,(acc - 1 ));
+ acc+=vidc_currentmode->vdsr; vidc_write(VIDC_VDSR,(acc - 1 ));
+ acc+=vidc_currentmode->vder; vidc_write(VIDC_VDER,(acc - 1 ));
+ acc+=vidc_currentmode->vber; vidc_write(VIDC_VBER,(acc - 1 ));
+ acc+=vidc_currentmode->vcr; vidc_write(VIDC_VCR ,(acc - 1 ));
+
+ WriteWord(IOMD_FSIZE, vidc_currentmode->vcr
+ + vidc_currentmode->vswr
+ + vidc_currentmode->vber
+ + vidc_currentmode->vbsr - 1 );
+
+ if ( dispsize==1024*1024 )
+ vidc_write ( VIDC_DCTL, vidc_currentmode->hder>>2 | 1<<16 | 1<<12);
+ else
+ vidc_write ( VIDC_DCTL, vidc_currentmode->hder>>2 | 3<<16 | 1<<12);
+
+ vidc_write ( VIDC_EREG, 1<<12 );
+ if ( dispsize>1024*1024) {
+ if ( vidc_currentmode->hder>=800 )
+ vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5);
+ else
+ vidc_write ( VIDC_CONREG, 6<<8 | bpp_mask<<5);
+ } else {
+ vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5);
+ }
+ }
+
+ R_DATA->mode = *vidc_currentmode;
+ R_DATA->screensize = R_DATA->XRES * R_DATA->YRES * R_DATA->BITSPERPIXEL/8;
+ R_DATA->pixelsperbyte = 8 / R_DATA->BITSPERPIXEL;
+ R_DATA->frontporch = MODE.hswr + MODE.hbsr + MODE.hdsr;
+ R_DATA->topporch = MODE.vswr + MODE.vbsr + MODE.vdsr;
+ R_DATA->bytes_per_line = R_DATA->XRES *
+ R_DATA->font->y_spacing/R_DATA->pixelsperbyte;
+ R_DATA->bytes_per_scroll = (vc->ycur % R_DATA->font->y_spacing)
+ * vc->xcur / R_DATA->pixelsperbyte;
+ R_DATA->text_width = R_DATA->XRES / R_DATA->font->x_spacing;
+ R_DATA->text_height = R_DATA->YRES / R_DATA->font->y_spacing;
+ vc->xchars = R_DATA->text_width;
+ vc->ychars = R_DATA->text_height;
+}
+
+void
+physcon_display_base(base)
+ u_int base;
+{
+ dispstart = dispstart-dispbase + base;
+ dispbase = vmem_base = base;
+ dispend = base + dispsize;
+ ptov = dispbase - phys_base;
+}
+
+static struct vidc_info masterinfo;
+static int cursor_init = 0;
+
+int
+vidcconsole_init(vc)
+ struct vconsole *vc;
+{
+ struct vidc_info *new;
+ int loop;
+
+ if ( cold_init==0 ) {
+ vidcconsole_coldinit ( vc );
+ } else {
+ if ( cursor_init == 0 )
+ vidcconsole_flash_go ( vc );
+ }
+
+ /*
+ * If vc->r_data is initialised then this means that the previous
+ * render engine on this vconsole was not freed properly. I should
+ * not try to clear it up, since I could panic the kernel. Instead
+ * I forget about its memory, which could cause a memory leak, but
+ * this would be easily detectable and fixable
+ */
+
+#ifdef SELFTEST
+ if ( vc->r_data != 0 ) {
+ printf( "*********************************************************\n" );
+ printf( "You have configured SELFTEST mode in the console driver\n" );
+ printf( "vc->rdata non zero. This could mean a new console\n" );
+ printf( "render engine has not freed up its data structure when\n" );
+ printf( "exiting.\n" );
+ printf( "DO NOT COMPILE NON DEVELOPMENT KERNELS WITH SELFTEST\n" );
+ printf( "*********************************************************" );
+ }
+#endif
+
+ if ( vc==vconsole_master ) {
+ vc->r_data = (char *)&masterinfo;
+ } else {
+ MALLOC ( (vc->r_data), char *, sizeof(struct vidc_info),
+ M_DEVBUF, M_NOWAIT );
+ }
+
+ if (vc->r_data==0)
+ panic ( "render engine initialisation failed. CLEAN THIS UP!" );
+
+ R_DATA->normalfont = &font_normal;
+ R_DATA->italicfont = &font_italic;
+ R_DATA->boldfont = &font_bold;
+ R_DATA->font = R_DATA->normalfont;
+
+ vidcconsole_mode ( vc, vidc_currentmode );
+ R_DATA->scrollback_end = dispstart;
+
+ new = (struct vidc_info *)vc->r_data;
+
+ R_DATA->text_colours = 1 << R_DATA->BITSPERPIXEL;
+ if ( R_DATA->text_colours > 8 ) R_DATA->text_colours = 8;
+
+#ifdef INVERSE_CONSOLE
+ R_DATA->n_backcolour = R_DATA->text_colours - 1;
+ R_DATA->n_forecolour = 0;
+#else
+ R_DATA->n_backcolour = 0;
+ R_DATA->n_forecolour = R_DATA->text_colours - 1;
+#endif
+
+ R_DATA->backcolour = R_DATA->n_backcolour;
+ R_DATA->forecolour = R_DATA->n_forecolour;
+
+ R_DATA->forefillcolour = 0;
+ R_DATA->backfillcolour = 0;
+
+ R_DATA->bold = 0;
+ R_DATA->reverse = 0;
+
+ for (loop = 0; loop < R_DATA->pixelsperbyte; ++loop) {
+ R_DATA->forefillcolour |= (R_DATA->forecolour <<
+ loop * R_DATA->BITSPERPIXEL);
+ R_DATA->backfillcolour |= (R_DATA->backcolour <<
+ loop * R_DATA->BITSPERPIXEL);
+ }
+
+ R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16);
+ R_DATA->blanked=0;
+ vc->BLANK ( vc, BLANK_NONE );
+
+ if ( vc == vconsole_current )
+ vidcconsole_textpalette ( vc );
+
+ vidc_cursor_init ( vc ) ;
+
+ if ( cold_init == 0 ) {
+ vidc_write ( VIDC_CP1, 0x0 );
+ vidc_write ( VIDC_CP2, 0x0 );
+ vidc_write ( VIDC_CP3, 0x0 );
+ }
+ cold_init=1;
+ return 0;
+}
+
+void
+vidcconsole_putchar(dev, c, vc)
+ dev_t dev;
+ char c;
+ struct vconsole *vc;
+{
+ vc->PUTSTRING ( &c, 1, vc );
+}
+
+int
+vidcconsole_spawn(vc)
+ struct vconsole *vc;
+{
+ vc->xchars = R_DATA->text_width;
+ vc->ychars = R_DATA->text_height;
+ vc->xcur = 0;
+ vc->ycur = 0;
+ vc->flags = 0;
+ return 0;
+}
+
+int
+vidcconsole_redraw(vc, x, y, a, b)
+ struct vconsole *vc;
+ int x, y;
+ int a, b;
+{
+ int xs, ys;
+ struct vidc_state vidc;
+ font_struct *p_font = R_DATA->font;
+ int p_forecol = R_DATA->forecolour;
+ int p_backcol = R_DATA->backcolour;
+ if (x<0) x=0;
+ if (y<0) y=0;
+ if (x>(vc->xchars-1)) x=vc->xchars-1;
+ if (y>(vc->ychars-1)) x=vc->ychars-1;
+
+ if (a>(vc->xchars-1)) a=vc->xchars-1;
+ if (b>(vc->ychars-1)) b=vc->ychars-1;
+
+ if (a<x) a=x;
+ if (b<y) b=y;
+
+
+ vidc = *vidc_current;
+ xs=vc->xcur;
+ ys=vc->ycur;
+
+ vc->xcur = 0;
+ vc->ycur = 0;
+ if ( (vc->flags&LOSSY) == 0 )
+ {
+ register int c;
+ /* This has *GOT* to be turboed */
+ for ( vc->ycur=y; vc->ycur<=b; vc->ycur++ )
+ {
+ for ( vc->xcur=x; vc->xcur<=a; vc->xcur++ )
+ {
+ c = (vc->charmap)[vc->xcur+vc->ycur*vc->xchars];
+ if ((c&BOLD)!=0)
+ R_DATA->font = R_DATA->boldfont;
+ else
+ R_DATA->font = R_DATA->normalfont;
+R_DATA->fast_render = ((c>>8)&0x7)|(((c>>11)&0x7)<<8)| (R_DATA->font->pixel_height<<16);
+if ( c & BLINKING )
+ c+=1<<8 | 1;
+ if ((c&BLINKING)!=0)
+ {
+ R_DATA->forecolour+=16;
+ R_DATA->backcolour+=16;
+ }
+ vidcconsole_render( vc, c&0xff );
+ }
+ }
+ }
+ vc->xcur = xs;
+ vc->ycur = ys;
+ R_DATA->forecolour = p_forecol;
+ R_DATA->backcolour = p_backcol;
+ R_DATA->font = p_font;
+ return 0;
+}
+
+
+int
+vidcconsole_swapin(vc)
+ struct vconsole *vc;
+{
+ register int counter;
+ int xs, ys;
+ struct vidc_state vidc;
+ font_struct *p_font = R_DATA->font;
+ int p_forecol = R_DATA->forecolour;
+ int p_backcol = R_DATA->backcolour;
+
+#ifdef ACTIVITY_WARNING
+ vconsole_pending = 0;
+#endif
+ vidc_write ( VIDC_CP1, 0x0 );
+
+ vidc = *vidc_current;
+ vidc_write ( VIDC_PALREG, 0x00000000 );
+ for ( counter=0; counter<255; counter++ )
+ vidc_write ( VIDC_PALETTE, 0x00000000 );
+ xs=vc->xcur;
+ ys=vc->ycur;
+/*TODO This needs to be vidc_restore (something) */
+ vidcconsole_mode ( vc, &MODE );
+
+ vc->xcur = 0;
+ vc->ycur = 0;
+ if ( (vc->flags&LOSSY) == 0 )
+ {
+ register int c;
+ /* This has *GOT* to be turboed */
+ for ( vc->ycur=0; vc->ycur<vc->ychars; vc->ycur++ )
+ {
+ for ( vc->xcur=0; vc->xcur<vc->xchars; vc->xcur++ )
+ {
+ c = (vc->charmap)[vc->xcur+vc->ycur*vc->xchars];
+ if ((c&BOLD)!=0)
+ R_DATA->font = R_DATA->boldfont;
+ else
+ R_DATA->font = R_DATA->normalfont;
+/*
+ R_DATA->forecolour = ((c>>8)&0x7);
+ R_DATA->backcolour = ((c>>11)&0x7);
+*/
+R_DATA->fast_render = ((c>>8)&0x7)|(((c>>11)&0x7)<<8)| (R_DATA->font->pixel_height<<16);
+if ( c & BLINKING )
+ c+=1<<8 | 1;
+ if ((c&BLINKING)!=0)
+ {
+ R_DATA->forecolour+=16;
+ R_DATA->backcolour+=16;
+ }
+ vidcconsole_render( vc, c&0xff );
+ }
+ }
+ }
+ else
+ {
+ vc->CLS ( vc );
+ }
+
+ if ( vc->vtty==1 )
+ {
+ vc->xcur = xs;
+ vc->ycur = ys;
+ vidcconsole_textpalette ( vc );
+ vidc_write ( VIDC_CP1, 0xffffff );
+ R_DATA->forecolour = p_forecol;
+ R_DATA->backcolour = p_backcol;
+ R_DATA->font = p_font;
+ }
+/* Make the cursor blank */
+ WriteWord(IOMD_CURSINIT,p_cursor_transparent);
+ return 0;
+
+}
+
+int
+vidcconsole_mmap(vc, offset, nprot)
+ struct vconsole *vc;
+ int offset;
+ int nprot;
+{
+ if (offset > videomemory.vidm_size)
+ return (-1);
+ return(arm_byte_to_page(((videomemory.vidm_pbase) + (offset))));
+}
+
+extern void vidcconsolemc_render __P(( unsigned char *addr, unsigned char *fontaddr,
+ int fast_render, int xres ));
+
+void
+vidcconsole_render(vc, c)
+ struct vconsole *vc;
+ char c;
+{
+ register unsigned char *fontaddr;
+ register unsigned char *addr;
+
+ /* Calculate the font's address */
+
+ fontaddr = R_DATA->font->data
+ + ((c-(0x20)) * R_DATA->font->height
+ * R_DATA->font->width);
+
+ addr = (unsigned char *)dispstart
+ + (vc->xcur * R_DATA->font->x_spacing)
+ + (vc->ycur * R_DATA->bytes_per_line);
+
+ vidcconsolemc_render ( addr, fontaddr, R_DATA->fast_render,
+ R_DATA->XRES );
+}
+
+/*
+ * Uugh. vidc graphics dont support scrolling regions so we have to emulate
+ * it here. This would normally require much software scrolling which is
+ * horriblly slow, so I'm going to try and do a composite scroll, which
+ * causes problems for scrollback but it's less speed critical
+ */
+
+void
+vidcconsole_scrollup(vc, low, high)
+ struct vconsole *vc;
+ int low;
+ int high;
+{
+ unsigned char *start, *end;
+
+ if ( ( low==0 ) && ( high==vc->ychars-1 ))
+ {
+ /* All hardware scroll */
+ dispstart+=R_DATA->bytes_per_line;
+ if ( dispstart >= dispend )
+ dispstart -= dispsize;
+
+ high=high+1; /* Big hack */
+
+ WriteWord(IOMD_VIDINIT, dispstart - ptov );
+ }
+ else
+ {
+ char *oldstart=(char *)dispstart;
+
+ /* Composite scroll */
+
+ if ( (high-low) > (vc->ychars>>1) )
+ {
+ /* Scroll region greater than half the screen */
+
+ dispstart+=R_DATA->bytes_per_line;
+ if ( dispstart >= dispend ) dispstart -= dispsize;
+
+ WriteWord(IOMD_VIDINIT, dispstart - ptov );
+
+ if ( low!=0 )
+ {
+ start = (unsigned char *)oldstart;
+ end=(unsigned char*)oldstart+((low+1) * R_DATA->bytes_per_line);
+ BCOPY ( start, start+R_DATA->bytes_per_line,
+ end-start-R_DATA->bytes_per_line);
+ }
+
+ if ( high!=(vc->ychars-1) )
+ {
+ start =(unsigned char *)dispstart+(high)*R_DATA->bytes_per_line;
+ end=(unsigned char*)dispstart+((vc->ychars)*R_DATA->bytes_per_line);
+ BCOPY ( start, start+R_DATA->bytes_per_line,
+ end-start-R_DATA->bytes_per_line);
+ }
+ high++;
+ }
+ else
+ {
+ /* Scroll region less than half the screen */
+
+ /* NO COMPOSITE SCROLL YET */
+
+ high++;
+ if (low<0) low=0;
+ if (high>(vc->ychars)) high=vc->ychars;
+ if (low>high) return; /* yuck */
+ start = (unsigned char *)dispstart + ((low)*R_DATA->bytes_per_line);
+ end = (unsigned char *)dispstart + ((high)*R_DATA->bytes_per_line);
+ BCOPY ( start+R_DATA->bytes_per_line, start,
+ (end-start)-R_DATA->bytes_per_line );
+ R_DATA->scrollback_end = dispstart;
+ }
+ }
+ memset ( (char *) dispstart + ((high-1)*R_DATA->bytes_per_line) ,
+ R_DATA->backfillcolour,
+ R_DATA->bytes_per_line );
+}
+
+void
+vidcconsole_scrolldown(vc, low, high)
+ struct vconsole *vc;
+ int low;
+ int high;
+{
+ unsigned char *start;
+ unsigned char *end;
+
+ if ( low<0 ) low = 0;
+ if ( high>(vc->ychars-1) ) high=vc->ychars-1;
+
+ if ( ( low==0 ) && ( high==vc->ychars-1 ))
+ {
+ dispstart-=R_DATA->bytes_per_line;
+
+ if ( dispstart < dispbase )
+ dispstart += dispsize;
+
+ WriteWord(IOMD_VIDINIT, dispstart - ptov );
+ }
+ else
+ {
+ if ( ((high-low) > (vc->ychars>>1)) )
+ {
+high--;
+ if (high!=(vc->ychars-1))
+ {
+ start =(unsigned char*)dispstart+((high+1)*R_DATA->bytes_per_line);
+ end=(unsigned char*)dispstart+((vc->ychars)*R_DATA->bytes_per_line);
+ BCOPY ( start+R_DATA->bytes_per_line, start,
+ (end-start)-R_DATA->bytes_per_line );
+ }
+
+ dispstart-=R_DATA->bytes_per_line;
+ if ( dispstart < dispbase )
+ dispstart += dispsize;
+ WriteWord(IOMD_VIDINIT, dispstart - ptov );
+ start = (unsigned char *)dispstart + (low * R_DATA->bytes_per_line);
+
+ if (low!=0)
+ {
+ end = (unsigned char *)dispstart + ((low+1)*R_DATA->bytes_per_line);
+ BCOPY ( (char*)(dispstart+R_DATA->bytes_per_line),
+ (char *)dispstart,
+ (int)((end-dispstart)-R_DATA->bytes_per_line ));
+ }
+ }
+ else
+ {
+ start = (unsigned char *)dispstart + (low * R_DATA->bytes_per_line);
+ end = (unsigned char *)dispstart + ((high+1) * R_DATA->bytes_per_line);
+ BCOPY ( start, start+R_DATA->bytes_per_line, end-start-R_DATA->bytes_per_line);
+ }
+
+ }
+ memset ((char*) dispstart + (low*R_DATA->bytes_per_line) ,
+ R_DATA->backfillcolour, R_DATA->bytes_per_line );
+}
+
+void
+vidcconsole_cls(vc)
+ struct vconsole *vc;
+{
+#ifdef RC7500
+ dispstart = dispbase;
+ dispend = dispstart+dispsize;
+
+ WriteWord ( IOMD_VIDINIT, dispstart-ptov );
+ WriteWord ( IOMD_VIDSTART, dispstart-ptov );
+ WriteWord ( IOMD_VIDEND, (dispend-transfersize)-ptov );
+#endif
+
+ vidcconsolemc_cls ( (char *)dispstart, (char *)dispstart+R_DATA->screensize, R_DATA->backfillcolour );
+ /*
+ memset((char *)dispstart,
+ R_DATA->backfillcolour, R_DATA->screensize);
+ */
+ vc->xcur = vc->ycur = 0;
+}
+
+void
+vidcconsole_update(vc)
+ struct vconsole *vc;
+{
+}
+
+static char vidcconsole_name[] = VIDC_ENGINE_NAME;
+
+static int scrollback_ptr = 0;
+
+int
+vidcconsole_scrollback(vc)
+ struct vconsole *vc;
+{
+ int temp;
+
+ if (scrollback_ptr==0)
+ scrollback_ptr=dispstart;
+
+ temp = scrollback_ptr;
+
+ scrollback_ptr-=R_DATA->bytes_per_line * (vc->ychars-2);
+
+ if ( scrollback_ptr < dispbase )
+ scrollback_ptr += dispsize;
+
+ if ( (scrollback_ptr>dispstart)&&
+ (scrollback_ptr<(dispstart+R_DATA->screensize) ) )
+ {
+ scrollback_ptr=temp;
+ return 0;
+ }
+
+ vc->r_scrolledback = 1;
+
+ WriteWord(IOMD_VIDINIT, scrollback_ptr - ptov );
+ return 0;
+}
+
+int
+vidcconsole_scrollforward(vc)
+ struct vconsole *vc;
+{
+ register int temp;
+
+ if (scrollback_ptr==0)
+ return 0;
+
+ temp = scrollback_ptr;
+
+ scrollback_ptr+=R_DATA->bytes_per_line * (vc->ychars - 2);
+
+ if ( scrollback_ptr >= dispend )
+ scrollback_ptr -= dispsize;
+
+ if ( scrollback_ptr == dispstart )
+ {
+ WriteWord(IOMD_VIDINIT, scrollback_ptr - ptov );
+ scrollback_ptr=0;
+ vc->r_scrolledback = 0;
+ return 0;
+ }
+
+ WriteWord(IOMD_VIDINIT, scrollback_ptr - ptov );
+ return 0;
+}
+
+int
+vidcconsole_scrollbackend(vc)
+ struct vconsole *vc;
+{
+ scrollback_ptr = 0;
+ WriteWord(IOMD_VIDINIT, dispstart - ptov );
+ vc->r_scrolledback = 0;
+ return 0;
+}
+
+int
+vidcconsole_clreos(vc, code)
+ struct vconsole *vc;
+ int code;
+{
+ char *addr;
+ char *endofscreen;
+
+ addr = (unsigned char *)dispstart
+ + (vc->xcur * R_DATA->font->x_spacing)
+ + (vc->ycur * R_DATA->bytes_per_line);
+
+ endofscreen = (unsigned char *)dispstart
+ + (vc->xchars * R_DATA->font->x_spacing)
+ + (vc->ychars * R_DATA->bytes_per_line);
+
+
+ switch (code)
+ {
+ case 0:
+ vidcconsolemc_cls ( addr,
+ (unsigned char *)dispend,
+ R_DATA->backfillcolour );
+ if ((unsigned char *)endofscreen > (unsigned char *)dispend) {
+ char string[80];
+ sprintf(string, "(addr=%08x eos=%08x dispend=%08x dispstart=%08x base=%08x)",
+ (u_int)addr, (u_int)endofscreen, dispend, dispstart, dispbase);
+ dprintf(string);
+ vidcconsolemc_cls((unsigned char *)dispbase, (unsigned char *)(dispbase + (endofscreen - dispend)), R_DATA->backfillcolour);
+ }
+ break;
+
+ case 1:
+ vidcconsolemc_cls ( (unsigned char *)dispstart+R_DATA->screensize,
+ addr,
+ R_DATA->backfillcolour );
+ break;
+
+ case 2:
+ default:
+ vidcconsole_cls ( vc );
+ break;
+ }
+ return 0;
+}
+
+#define VIDC R_DATA->vidc
+
+int
+vidcconsole_debugprint(vc)
+ struct vconsole *vc;
+{
+#ifdef DEVLOPING
+ printf ( "VIDCCONSOLE DEBUG INFORMATION\n\n" );
+ printf ( "res (%d, %d) charsize (%d, %d) cursor (%d, %d)\n"
+ , R_DATA->XRES, R_DATA->YRES
+ , vc->xchars, vc->ychars, vc->xcur, vc->ycur );
+ printf ( "bytes_per_line %d\n" , R_DATA->bytes_per_line );
+ printf ( "pixelsperbyte %d\n" , R_DATA->pixelsperbyte );
+ printf ( "dispstart %08x\n" , dispstart );
+ printf ( "dispend %08x\n" , dispend );
+ printf ( "screensize %08x\n" , R_DATA->screensize );
+
+ printf ( "fontwidth %08x\n" , R_DATA->font->pixel_width );
+ printf ( "fontheight %08x\n" , R_DATA->font->pixel_height );
+ printf ( "\n" );
+ printf ( "palreg = %08x bcol = %08x\n" , VIDC.palreg, VIDC.bcol );
+ printf ( "cp1 = %08x cp2 = %08x cp3 = %08x\n" , VIDC.cp1, VIDC.cp2, VIDC.cp3 );
+ printf ( "hcr = %08x hswr = %08x hbsr = %08x\n" , VIDC.hcr, VIDC.hswr, VIDC.hbsr );
+ printf ( "hder = %08x hber = %08x hcsr = %08x\n" , VIDC.hder, VIDC.hber, VIDC.hcsr );
+ printf ( "hir = %08x\n" , VIDC.hir );
+ printf ( "vcr = %08x vswr = %08x vbsr = %08x\n" , VIDC.vcr, VIDC.vswr, VIDC.vbsr );
+ printf ( "vder = %08x vber = %08x vcsr = %08x\n" , VIDC.vder, VIDC.vber, VIDC.vcsr );
+ printf ( "vcer = %08x\n" , VIDC.vcer );
+ printf ( "ereg = %08x fsynreg = %08x conreg = %08x\n" , VIDC.ereg, VIDC.fsynreg, VIDC.conreg );
+ printf ( "\n" );
+ printf ( "flash %08x, cursor_flash %08x", R_DATA->flash, R_DATA->cursor_flash );
+#else
+ printf ( "VIDCCONSOLE - NO DEBUG INFO\n" );
+#endif
+ return 0;
+}
+
+#ifdef NICE_UPDATE
+static int need_update = 0;
+
+void
+vidcconsole_updatecursor(arg)
+ void *arg;
+{
+ struct vconsole *vc = vconsole_current;
+
+ vidc_write(VIDC_HCSR, R_DATA->frontporch-17+ (vc->xcur)*R_DATA->font->pixel_width );
+ vidc_write(VIDC_VCSR, R_DATA->topporch-2+ (vc->ycur+1)*R_DATA->font->pixel_height-2 + 3
+ - R_DATA->font->pixel_height);
+ vidc_write(VIDC_VCER, R_DATA->topporch-2+ (vc->ycur+3)*R_DATA->font->pixel_height+2 + 3 );
+ return;
+}
+
+int
+vidcconsole_cursorupdate(vc)
+ struct vconsole *vc;
+{
+ timeout ( vidcconsole_updatecursor, NULL, 20 );
+ return 0;
+}
+
+#else
+
+static int
+vidcconsole_cursorupdate(vc)
+ struct vconsole *vc;
+{
+ vidc_write(VIDC_HCSR, R_DATA->frontporch-17+ (vc->xcur)*R_DATA->font->pixel_width );
+ vidc_write(VIDC_VCSR, R_DATA->topporch-2+ (vc->ycur+1)*R_DATA->font->pixel_height-2 + 3
+ - R_DATA->font->pixel_height);
+ vidc_write(VIDC_VCER, R_DATA->topporch-2+ (vc->ycur+3)*R_DATA->font->pixel_height+2 + 3 );
+ return (0);
+}
+
+#endif
+
+#define DEFAULT_CURSORSPEED (25)
+
+static int CURSORSPEED = DEFAULT_CURSORSPEED;
+
+static int
+vidcconsole_cursorflashrate(vc, rate)
+ struct vconsole *vc;
+ int rate;
+{
+ CURSORSPEED = 60/rate;
+}
+
+static int cursorcounter=DEFAULT_CURSORSPEED;
+static int flashcounter=DEFAULT_CURSORSPEED;
+#ifdef PRETTYCURSOR
+static int pretty=0xff;
+#endif
+
+static int cursor_col = 0x0;
+
+static int
+vidcconsole_cursorintr(vc)
+ struct vconsole *vc;
+{
+ if ( cursor_flash==0 )
+ return 0;
+
+ /*
+ * We don't need this.
+ */
+#ifndef RC7500
+ vconsole_blankcounter--;
+
+ if ( vconsole_blankcounter<0 ) {
+ vconsole_blankcounter=vconsole_blankinit;
+ vidcconsole_blank ( vc, BLANK_OFF );
+ }
+#endif
+
+ cursorcounter--;
+ if (cursorcounter<=0) {
+ cursorcounter=CURSORSPEED;
+ cursor_col = cursor_col ^ 0xffffff;
+#ifdef ACTIVITY_WARNING
+ if (vconsole_pending) {
+ if ( cursor_col==0 )
+ WriteWord(IOMD_CURSINIT,p_cursor_transparent);
+ else
+ WriteWord(IOMD_CURSINIT,p_cursor_normal);
+ vidc_write ( VIDC_CP1, cursor_col&0xff );
+ } else
+#endif
+ {
+ if ( cursor_col==0 )
+ WriteWord(IOMD_CURSINIT,p_cursor_transparent);
+ else
+ WriteWord(IOMD_CURSINIT,p_cursor_normal);
+ vidc_write ( VIDC_CP1, 0xffffff );
+ }
+ }
+ return(0);
+}
+
+int
+vidcconsole_flashintr(vc)
+ struct vconsole *vc;
+{
+ if ( flash==0 )
+ return 0;
+
+ flashcounter--;
+ if (flashcounter<=0) {
+ flashcounter=CURSORSPEED;
+ if ( cursor_col == 0 ) {
+
+ vidc_write(VIDC_PALREG, 0x00000010);
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL(255, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 255, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 255));
+ vidc_write(VIDC_PALETTE, VIDC_COL(255, 0, 255));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 255, 255));
+ vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
+ vidc_write(VIDC_PALETTE, VIDC_COL(128, 128, 128));
+ vidc_write(VIDC_PALETTE, VIDC_COL(255, 128, 128));
+ vidc_write(VIDC_PALETTE, VIDC_COL(128, 255, 128));
+ vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 128));
+ vidc_write(VIDC_PALETTE, VIDC_COL(128, 128, 255));
+ vidc_write(VIDC_PALETTE, VIDC_COL(255, 128, 255));
+ vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
+ } else {
+ vidc_write(VIDC_PALREG, 0x00000010);
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
+ }
+ }
+ return(0);
+}
+
+static int
+vidc_cursor_init(vc)
+ struct vconsole *vc;
+{
+ extern char *cursor_data;
+ int counter;
+ int line;
+
+ /* Blank the cursor while initialising it's sprite */
+
+ vidc_write ( VIDC_CP1, 0x0 );
+ vidc_write ( VIDC_CP2, 0x0 );
+ vidc_write ( VIDC_CP3, 0x0 );
+
+ cursor_normal = cursor_data;
+ cursor_transparent = cursor_data + (R_DATA->font->pixel_height *
+ R_DATA->font->pixel_width);
+
+ cursor_transparent += 32;
+ cursor_transparent = (char *)((int)cursor_transparent & (~31) );
+
+ for ( line = 0; line<R_DATA->font->pixel_height; ++ line )
+ {
+ for ( counter=0; counter<R_DATA->font->pixel_width/4;counter++ )
+ cursor_normal[line*R_DATA->font->pixel_width + counter]=0x55;
+ for ( ; counter<8; counter++ )
+ cursor_normal[line*R_DATA->font->pixel_width + counter]=0;
+ }
+
+ for ( line = 0; line<R_DATA->font->pixel_height; ++ line )
+ {
+ for ( counter=0; counter<R_DATA->font->pixel_width/4;counter++ )
+ cursor_transparent[line*R_DATA->font->pixel_width + counter]=0x00;
+ for ( ; counter<8; counter++ )
+ cursor_transparent[line*R_DATA->font->pixel_width + counter]=0;
+ }
+
+
+ p_cursor_normal = pmap_extract(kernel_pmap,(vm_offset_t)cursor_normal );
+ p_cursor_transparent = pmap_extract(kernel_pmap,(vm_offset_t)cursor_transparent);
+
+/*
+ memset ( cursor_normal, 0x55,
+ R_DATA->font->pixel_width*R_DATA->font->pixel_height );
+
+ memset ( cursor_transparent, 0x55,
+ R_DATA->font->pixel_width*R_DATA->font->pixel_height );
+*/
+
+ /* Ok, now see the cursor */
+
+ vidc_write ( VIDC_CP1, 0xffffff );
+ return 0;
+}
+
+int
+vidcconsole_setfgcol(vc, col)
+ struct vconsole *vc;
+ int col;
+{
+ register int loop;
+
+ if ( R_DATA->forecolour >= 16 )
+ R_DATA->forecolour=16;
+ else
+ R_DATA->forecolour=0;
+
+ R_DATA->forefillcolour = 0;
+
+ R_DATA->forecolour += col;
+
+/*TODO
+ if ( R_DATA->forecolour >> 1<<R_DATA->BITSPERPIXEL )
+ R_DATA->forecolour>>1;
+*/
+
+ for (loop = 0; loop < R_DATA->pixelsperbyte; ++loop) {
+ R_DATA->forefillcolour |= (R_DATA->forecolour <<
+ loop * R_DATA->BITSPERPIXEL);
+ }
+ R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16);
+ return 0;
+}
+
+int
+vidcconsole_setbgcol(vc, col)
+ struct vconsole *vc;
+ int col;
+{
+ register int loop;
+
+ if ( R_DATA->backcolour >= 16 )
+ R_DATA->backcolour=16;
+ else
+ R_DATA->backcolour=0;
+
+ R_DATA->backfillcolour = 0;
+ R_DATA->backcolour += col;
+ /*TODO
+ if ( R_DATA->backcolour >> 1<<R_DATA->BITSPERPIXEL )
+ R_DATA->backcolour>>1;
+*/
+
+ for (loop = 0; loop < R_DATA->pixelsperbyte; ++loop) {
+ R_DATA->backfillcolour |= (R_DATA->backcolour <<
+ loop * R_DATA->BITSPERPIXEL);
+ }
+ return 0;
+}
+
+int
+vidcconsole_textpalette(vc)
+ struct vconsole *vc;
+{
+ R_DATA->forecolour = COLOUR_WHITE_8;
+ R_DATA->backcolour = COLOUR_BLACK_8;
+
+ vidc_write( VIDC_PALREG , 0x00000000);
+ vidc_write( VIDC_PALETTE , VIDC_COL( 0, 0, 0));
+ vidc_write( VIDC_PALETTE , VIDC_COL(255, 0, 0));
+ vidc_write( VIDC_PALETTE , VIDC_COL( 0, 255, 0));
+ vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 0));
+ vidc_write( VIDC_PALETTE , VIDC_COL( 0, 0, 255));
+ vidc_write( VIDC_PALETTE , VIDC_COL(255, 0, 255));
+ vidc_write( VIDC_PALETTE , VIDC_COL( 0, 255, 255));
+ vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 255));
+ vidc_write( VIDC_PALETTE , VIDC_COL(128, 128, 128));
+ vidc_write( VIDC_PALETTE , VIDC_COL(255, 128, 128));
+ vidc_write( VIDC_PALETTE , VIDC_COL(128, 255, 128));
+ vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 128));
+ vidc_write( VIDC_PALETTE , VIDC_COL(128, 128, 255));
+ vidc_write( VIDC_PALETTE , VIDC_COL(255, 128, 255));
+ vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 255));
+
+R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16);
+ return 0;
+}
+
+int
+vidcconsole_sgr (vc, type)
+ struct vconsole *vc;
+ int type;
+{
+ switch ( type )
+ {
+ case 0: /* Normal */
+ if (R_DATA->BITSPERPIXEL == 8)
+ {
+ R_DATA->n_forecolour = COLOUR_WHITE_8;
+ R_DATA->n_backcolour = COLOUR_BLACK_8;
+ }
+
+ R_DATA->forecolour = R_DATA->n_forecolour;
+ R_DATA->backcolour = R_DATA->n_backcolour;
+ R_DATA->font = R_DATA->normalfont;
+ break;
+
+ case 1: /* bold */
+ R_DATA->font = R_DATA->boldfont;
+ break;
+
+ case 22: /* not bold */
+ R_DATA->font = R_DATA->normalfont;
+ break;
+
+ case 5: /* blinking */
+ if ( R_DATA->forecolour < 16 )
+ {
+ R_DATA->forecolour+=16;
+ R_DATA->backcolour+=16;
+ R_DATA->n_forecolour+=16;
+ R_DATA->n_backcolour+=16;
+ }
+ break;
+
+ case 25: /* not blinking */
+ if ( R_DATA->forecolour >= 16 )
+ {
+ R_DATA->forecolour-=16;
+ R_DATA->backcolour-=16;
+ R_DATA->n_forecolour-=16;
+ R_DATA->n_backcolour-=16;
+ }
+ break;
+
+ case 7: /* reverse */
+ R_DATA->forecolour = R_DATA->n_backcolour;
+ R_DATA->backcolour = R_DATA->n_forecolour;
+ break;
+
+ case 27: /* not reverse */
+ R_DATA->forecolour = R_DATA->n_forecolour;
+ R_DATA->backcolour = R_DATA->n_backcolour;
+ break;
+ }
+R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16);
+ return 0;
+}
+
+int
+vidcconsole_scrollregion(vc, low, high)
+ struct vconsole *vc;
+ int low;
+ int high;
+{
+ return 0;
+}
+
+int
+vidcconsole_blank(vc, type)
+ struct vconsole *vc;
+ int type;
+{
+ vc->blanked=type;
+ switch (type) {
+ case 0:
+#ifdef RC7500
+ vidc_write ( VIDC_EREG, 0x51<<12 );
+#else
+ vidc_write ( VIDC_EREG, 1<<12 );
+#endif
+ break;
+
+ case 1: /* not implemented yet */
+ case 2:
+ case 3:
+ vidc_write ( VIDC_EREG, 0 );
+ break;
+ }
+ return 0;
+}
+
+extern struct tty *find_tp __P((dev_t dev));
+
+int vidcconsole_ioctl ( struct vconsole *vc, dev_t dev, int cmd, caddr_t data,
+ int flag, struct proc *p )
+{
+ int error;
+ struct tty *tp;
+ struct winsize ws;
+ switch ( cmd )
+ {
+ case CONSOLE_MODE:
+ tp = find_tp(dev);
+ printf ( "mode ioctl called\n" );
+ vidcconsole_mode ( vc, (struct vidc_mode *)data );
+ vc->MODECHANGE ( vc );
+ ws.ws_row=vc->ychars;
+ ws.ws_col=vc->xchars;
+ error = (*linesw[tp->t_line].l_ioctl)(tp, TIOCSWINSZ, (char *)&ws, flag, p);
+ error = ttioctl(tp, TIOCSWINSZ, (char *)&ws, flag, p);
+ return 0;
+ break;
+
+ case CONSOLE_RESETSCREEN:
+ {
+ extern unsigned int dispbase;
+ extern unsigned int dispsize;
+ extern unsigned int ptov;
+ extern unsigned int transfersize;
+
+ WriteWord ( IOMD_VIDINIT, dispbase-ptov );
+ WriteWord ( IOMD_VIDSTART, dispbase-ptov );
+ WriteWord ( IOMD_VIDEND, (dispbase+dispsize-transfersize)-ptov );
+ return 0;
+ }
+ case CONSOLE_RESTORESCREEN:
+ {
+ extern unsigned int dispstart;
+ extern unsigned int dispsize;
+ extern unsigned int ptov;
+ extern unsigned int transfersize;
+
+ WriteWord ( IOMD_VIDINIT, dispstart-ptov );
+ WriteWord ( IOMD_VIDSTART, dispstart-ptov );
+ WriteWord ( IOMD_VIDEND, (dispstart+dispsize-transfersize)-ptov );
+ vidc_stdpalette();
+ return 0;
+ }
+ case CONSOLE_GETINFO:
+ {
+ extern videomemory_t videomemory;
+ register struct console_info *inf = (void *)data;
+
+
+ inf->videomemory = videomemory;
+ inf->width = R_DATA->mode.hder;
+ inf->height = R_DATA->mode.vder;
+ inf->bpp = R_DATA->mode.bitsperpixel;
+ return 0;
+ }
+ case CONSOLE_PALETTE:
+ {
+ register struct console_palette *pal = (void *)data;
+ vidc_write(VIDC_PALREG, pal->entry);
+ vidc_write(VIDC_PALETTE, VIDC_COL(pal->red, pal->green, pal->blue));
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int
+vidcconsole_attach(vc, parent, self, aux)
+ struct vconsole *vc;
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ vidc_cursor_init ( vc );
+ vidcconsole_flash_go ( vc );
+ return 0;
+}
+
+int
+vidcconsole_flash_go(vc)
+ struct vconsole *vc;
+{
+ static lock=0;
+ if (lock==1)
+ return -1;
+ lock=0;
+
+ cursor_ih.ih_func = vidcconsole_cursorintr;
+ cursor_ih.ih_arg = vc;
+ cursor_ih.ih_level = IPL_TTY;
+ cursor_ih.ih_name = "vsync";
+ irq_claim ( IRQ_FLYBACK, &cursor_ih );
+
+ cursor_init = 0;
+ return 0;
+}
+
+/* What does this function do ? */
+int
+vidcconsole_flash(vc, flash)
+ struct vconsole *vc;
+ int flash;
+{
+ flash = flash;
+}
+
+int
+vidcconsole_cursorflash(vc, flash)
+ struct vconsole *vc;
+ int flash;
+{
+ cursor_flash = flash;
+ return(0);
+}
+
+struct render_engine vidcconsole = {
+ vidcconsole_name,
+ vidcconsole_init,
+
+ vidcconsole_putchar,
+
+ vidcconsole_spawn,
+ vidcconsole_swapin,
+ vidcconsole_mmap,
+ vidcconsole_render,
+ vidcconsole_scrollup,
+ vidcconsole_scrolldown,
+ vidcconsole_cls,
+ vidcconsole_update,
+ vidcconsole_scrollback,
+ vidcconsole_scrollforward,
+ vidcconsole_scrollbackend,
+ vidcconsole_clreos,
+ vidcconsole_debugprint,
+ vidcconsole_cursorupdate,
+ vidcconsole_cursorflashrate,
+ vidcconsole_setfgcol,
+ vidcconsole_setbgcol,
+ vidcconsole_textpalette,
+ vidcconsole_sgr,
+ vidcconsole_blank,
+ vidcconsole_ioctl,
+ vidcconsole_redraw,
+ vidcconsole_attach,
+ vidcconsole_flash,
+ vidcconsole_cursorflash
+};
+
+
+
+
+
+
+
+struct vidcvideo_softc {
+ struct device device;
+ int sc_opened;
+};
+
+int
+vidcvideo_probe(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+/*
+ struct vidcvideo_softc *vidcvideosoftc = (void *)match;
+ struct mainbus_attach_args *mb = aux;
+*/
+
+ return 1;
+}
+
+void
+vidcvideo_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct vidcvideo_softc *vidcvideosoftc = (void *)self;
+ vidcvideosoftc->sc_opened=0;
+
+ printf ( ": vidc 20\n" );
+}
+
+struct cfattach vidcvideo_ca = {
+ sizeof (struct vidcvideo_softc), vidcvideo_probe, vidcvideo_attach
+};
+
+struct cfdriver vidcvideo_cd = {
+ NULL, "vidcvideo", DV_DULL
+};
+
+int
+vidcvideoopen(dev, flags, fmt, p)
+ dev_t dev;
+ int flags;
+ int fmt;
+ struct proc *p;
+{
+ struct vidcvideo_softc *sc;
+ struct vconsole vconsole_new;
+ int unit = minor(dev);
+ int s;
+
+ if ( unit >= vidcvideo_cd.cd_ndevs )
+ return ENXIO;
+ sc = vidcvideo_cd.cd_devs[unit];
+ if (!sc)
+ return ENXIO;
+
+ s = spltty();
+/* if (sc->sc_opened) {
+ (void)splx(s);
+ return(EBUSY);
+ }*/
+ ++sc->sc_opened;
+ (void)splx(s);
+
+ if (sc->sc_opened == 1) {
+ vconsole_new = *vconsole_default;
+ vconsole_new.render_engine = &vidcconsole;
+ vconsole_spawn_re (
+ makedev ( physcon_major, 64 + minor(dev) ),
+ &vconsole_new );
+ } else {
+ log(LOG_WARNING, "Multiple open of/dev/vidcvideo0 by proc %d\n", p->p_pid);
+ }
+
+ return 0;
+}
+
+int
+vidcvideoclose(dev, flags, fmt, p)
+ dev_t dev;
+ int flags;
+ int fmt;
+ struct proc *p;
+{
+ struct vidcvideo_softc *sc;
+ int unit = minor(dev);
+ int s;
+
+ if ( unit >= vidcvideo_cd.cd_ndevs )
+ return ENXIO;
+ sc = vidcvideo_cd.cd_devs[unit];
+ if (!sc)
+ return ENXIO;
+
+ s = spltty();
+ --sc->sc_opened;
+ (void)splx(s);
+
+ return 0;
+}
+
+extern int physconioctl __P(( dev_t, int, caddr_t, int, struct proc *));
+
+int
+vidcvideoioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ dev = makedev(physcon_major, 64 + minor(dev));
+ return ( physconioctl ( dev, cmd, data, flag, p ));
+}
+
+extern int physconmmap __P((dev_t, int, int));
+
+int
+vidcvideommap(dev, offset, prot)
+ dev_t dev;
+ int offset;
+ int prot;
+{
+ dev = makedev(physcon_major, 64 + minor(dev));
+ return(physconmmap(dev, offset, prot));
+}
+
--- /dev/null
+/* $NetBSD: vt220.c,v 1.3 1996/03/18 19:33:10 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * vt220.c
+ *
+ * VT220 emulation functions
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/syslog.h>
+#include <machine/param.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/bootconfig.h>
+#include <machine/iomd.h>
+#include <machine/vconsole.h>
+#include <machine/vidc.h>
+
+#include <arm32/dev/console/vt220.h>
+
+/* Temporary for debugging the vnode bug */
+
+int vnodeconsolebug = 0;
+u_int vnodeconsolebug1 = 0;
+u_int vnodeconsolebug2 = 0;
+
+static char vt220_name[] = "vt100";
+
+/* These defines are for the developer only !!!! */
+#define SELFTEST
+#define dprintf(x) ;
+
+/*************************************************/
+
+#define FGCOL 0x0700
+#define BGCOL 0x3800
+
+/* Options */
+#define HARD_RESET_AT_INIT
+#undef SIMPLE_CURSOR /* Define if any render engine is cursorless */
+
+/*************************************************/
+
+#define DA_VT220 "\033[?62;1;2;6;7;8;9c"
+
+char console_proc[41]; /* Is this debugging ? */
+
+#ifdef SIMPLE_CURSOR
+#define SIMPLE_CURSOR_CHAR ('_')
+#endif
+
+#define TERMTYPE_PUTSTRING vt220_putstring
+#define TERMTYPE_INIT vt220_init
+
+extern struct vconsole *vconsole_master;
+
+static int default_beepstate = 0;
+
+#define CDATA struct vt220_info *cdata = (struct vt220_info *)vc->data
+
+struct vt220_info master_termdata_store;
+struct vt220_info *master_termdata = &master_termdata_store;
+
+int do_render __P(( char /*c*/, struct vconsole */*vc*/ ));
+void do_render_noscroll __P(( char /*c*/, struct vconsole */*vc*/ ));
+void do_scrollcheck __P(( struct vconsole */*vc*/ ));
+void vt_ris __P((struct vconsole */*vc*/));
+
+void
+clr_params(cdata)
+ struct vt220_info *cdata;
+{
+ int i;
+ for (i=0; i<MAXPARMS; i++)
+ cdata->param[i] = 0;
+ cdata->parami = 0;
+}
+
+int
+TERMTYPE_INIT(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata;
+
+ if (vc->data==NULL) {
+ if ( vc==vconsole_master ) {
+ vc->data = (char *) master_termdata;
+ } else {
+ MALLOC ( vc->data, char *, sizeof(struct vt220_info),
+ M_DEVBUF, M_NOWAIT );
+ }
+ }
+
+ cdata = (struct vt220_info *)vc->data;
+
+ bzero ( (char *)cdata, sizeof (cdata) );
+
+#ifdef HARD_RESET_AT_INIT
+ vt_ris ( vc );
+#else
+ cdata->state = STATE_INIT;
+ cdata->disable_function = 1;
+ cdata->m_om = 0;
+ vc->xcur = vc->ycur = 0;
+ cdata->beepoff=default_beepstate;
+ cdata->simple_cursor_store = ' ';
+ cdata->scrr_beg = 0;
+ cdata->scrr_len = vc->ychars;
+ cdata->scrr_end = vc->ychars-1;
+ cdata->simple_cursor_on = 0;
+
+ for ( counter=0; counter<MAXTABSTOPS; counter++ ) {
+ if ( !(counter%8) )
+ cdata->tab_stops[counter] = 1;
+ else
+ cdata->tab_stops[counter] = 0;
+ }
+#endif
+ return 0;
+}
+
+int
+mapped_cls(vc)
+ struct vconsole *vc;
+{
+ int ptr;
+ if (vc->charmap == NULL)
+ return -1;
+ for ( ptr=0; ptr<(vc->xchars*vc->ychars); ptr++ )
+ vc->charmap[ptr]=0x20;
+ return 0;
+}
+
+void
+do_scrolldown(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+/*
+ if ( ( cdata->scrr_beg<0 ) || ( cdata->scrr_end>=vc->ychars) )
+ dprintf ( "INVALID SCROLLDOWN" );
+*/
+
+ /* Clean up */
+
+/*
+ if ( cdata->scrr_beg < 0 ) cdata->scrr_beg = 0;
+*/
+ if ( cdata->scrr_end >= vc->ychars ) cdata->scrr_end=vc->ychars-1;
+
+
+ if (vc==vconsole_current)
+ vc->SCROLLDOWN ( vc, cdata->scrr_beg, cdata->scrr_end );
+ else
+ vconsole_pending=vc->number;
+
+ if (vnodeconsolebug) {
+ if (ReadWord(0xf148a000) != vnodeconsolebug2) {
+ log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in do_scrolldown(1)\n",
+ vnodeconsolebug2, ReadWord(0xf148a000));
+ log(LOG_WARNING, "vc=%08x vcur=%08x charmap=%08x\n", vc, vconsole_current, vc->charmap);
+ }
+ }
+
+/*
+ * This version of the following code was responcible for the vnode bug
+ * It can trash part of the word that follows the allocated block
+ * e.g. charmap = 0xf1484000, size 0x6000
+ * vnode = 0xf148a000
+ * first word of vnode is trashed.
+ * bug is an adjustment of -1 for counting backwards was not made.
+
+ if ( ((vc->flags)&(LOSSY)) == 0 ) {
+ int counter;
+ for ( counter=((cdata->scrr_end+1)*(vc->xchars));
+ counter > (cdata->scrr_beg+1)*(vc->xchars) ; counter-- ) {
+ vc->charmap[counter] = vc->charmap[counter-vc->xchars];
+ }
+
+ for ( counter=(cdata->scrr_beg)*(vc->xchars);
+ counter < (cdata->scrr_beg+1)*(vc->xchars); counter++ ) {
+ vc->charmap[counter]=0x20;
+ }
+ }
+*/
+ if ( ((vc->flags)&(LOSSY)) == 0 ) {
+ int counter;
+ for ( counter=((cdata->scrr_end+1)*(vc->xchars)) - 1;
+ counter >= (cdata->scrr_beg+1)*(vc->xchars) ; counter-- ) {
+ vc->charmap[counter] = vc->charmap[counter-vc->xchars];
+ }
+
+ for ( counter=(cdata->scrr_beg)*(vc->xchars);
+ counter < (cdata->scrr_beg+1)*(vc->xchars); counter++ ) {
+ vc->charmap[counter]=0x20;
+ }
+ }
+ if (vnodeconsolebug) {
+ if (ReadWord(0xf148a000) != vnodeconsolebug2) {
+ log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in do_scrolldown(2)\n",
+ vnodeconsolebug2, ReadWord(0xf148a000));
+ log(LOG_WARNING, "vc=%08x vcur=%08x charmap=%08x\n", vc, vconsole_current, vc->charmap);
+ }
+ }
+}
+
+void
+do_scrollup(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ if (vc==vconsole_current)
+ vc->SCROLLUP ( vc, cdata->scrr_beg, cdata->scrr_end );
+ else
+ vconsole_pending = vc->number;
+
+ if ( cdata->scrr_end == 0 )
+ vc->ycur=vc->ychars-1;
+ else
+ vc->ycur=cdata->scrr_end;
+
+/* Do a cyclic buffer for this !!!!!!!!!!!!!! */
+ if ( ((vc->flags)&(LOSSY)) == 0 ) {
+/* bcopy was weird, do this for now */
+ int counter;
+ for ( counter=(cdata->scrr_beg+1)*vc->xchars;
+ counter < ((cdata->scrr_end+1)*(vc->xchars)); counter++ ) {
+ vc->charmap[counter-vc->xchars] = vc->charmap[counter];
+ }
+ for ( counter=vc->xchars*(cdata->scrr_end);
+ counter < (vc->xchars*(cdata->scrr_end+1)); counter++ ) {
+ vc->charmap[counter]=0x20;
+ }
+ }
+}
+
+void
+respond(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ while (*cdata->report_chars && cdata->report_count > 0) {
+ (*linesw[vc->tp->t_line].l_rint)
+ (*cdata->report_chars++ & 0xff, vc->tp);
+ cdata->report_count--;
+ }
+}
+
+void
+vt_curadr(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+#ifdef SELFTEST
+strcpy ( console_proc, "vt_curadr" );
+#endif
+
+ if ( cdata->m_om ) /* relative to scrolling region */
+ {
+ cdata->param[0]+=cdata->scrr_beg;
+ if ( (cdata->param[0]==0) && (cdata->param[1]==0) )
+ {
+ vc->xcur = 0;
+ vc->ycur = 0;
+ return;
+ }
+ /* Limit checking */
+ cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+ cdata->param[0] = (cdata->param[0] > vc->ychars) ? vc->ychars : cdata->param[0];
+ cdata->param[1] = (cdata->param[1] <= 0) ? 1 : cdata->param[1];
+ cdata->param[1] = (cdata->param[1] >= vc->xchars) ? (vc->xchars-1) : cdata->param[1];
+ (cdata->param[0])--;
+ (cdata->param[1])--;
+ vc->ycur = cdata->param[0];
+ vc->xcur = cdata->param[1];
+ }
+ else
+ {
+ if ( (cdata->param[0]==0) && (cdata->param[1]==0) )
+ {
+ vc->xcur = 0;
+ vc->ycur = 0;
+ return;
+ }
+ /* Limit checking */
+
+ (cdata->param[0])--;
+ (cdata->param[1])--;
+
+ vc->ycur = cdata->param[0];
+ vc->xcur = cdata->param[1];
+
+{
+ char buf[80];
+ sprintf ( buf, "vc->xcur %d vc->ycur %d", vc->xcur, vc->ycur );
+ dprintf ( buf );
+}
+ }
+}
+
+extern void beep_generate(void);
+
+void
+vt_reset_dec_priv_qm(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+#ifdef SELFTEST
+strcpy ( console_proc, "vt_reset_dec_priv_qm" );
+#endif
+ switch(cdata->param[0])
+ {
+ case 7: /* AWM - auto wrap mode */
+ beep_generate();
+ cdata->flags &= ~F_AWM;
+ break;
+ case 0: /* error, ignored */
+ case 1: /* CKM - cursor key mode */
+ case 2: /* ANM - ansi/vt52 mode */
+ case 3: /* COLM - column mode */
+ case 4: /* SCLM - scrolling mode */
+ case 5: /* SCNM - screen mode */
+ case 8: /* ARM - auto repeat mode */
+ case 9: /* INLM - interlace mode */
+ case 10: /* EDM - edit mode */
+ case 11: /* LTM - line transmit mode */
+ case 12: /* */
+ case 13: /* SCFDM - space compression / field delimiting */
+ case 14: /* TEM - transmit execution mode */
+ case 15: /* */
+ case 16: /* EKEM - edit key execution mode */
+ case 25: /* TCEM - text cursor enable mode */
+ case 42: /* NRCM - 7bit NRC characters */
+ break;
+
+ case 6: /* OM - origin mode */
+ cdata->m_om = 0;
+ break;
+ }
+}
+
+void
+vt_sc(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+#ifdef SELFTEST
+ strcpy ( console_proc, "vt_sc" );
+#endif
+
+ cdata->sc_G0 = cdata->G0;
+ cdata->sc_G1 = cdata->G1;
+ cdata->sc_G2 = cdata->G2;
+ cdata->sc_G3 = cdata->G3;
+ cdata->sc_GL = cdata->GL;
+ cdata->sc_GR = cdata->GR;
+ cdata->sc_xcur = vc->xcur;
+ cdata->sc_ycur = vc->ycur;
+ cdata->sc_om = cdata->m_om;
+ cdata->sflags = cdata->flags;
+/*
+ cdata->sc_attr = cdata->c_attr;
+ cdata->sc_awm = cdata->m_awm;
+ cdata->sc_sel = cdata->selchar;
+ cdata->sc_vtsgr = cdata->vtsgr;
+ cdata->sc_flag = 1;
+*/
+}
+
+void
+vt_rc(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ cdata->G0 = cdata->sc_G0;
+ cdata->G1 = cdata->sc_G1;
+ cdata->G2 = cdata->sc_G2;
+ cdata->G3 = cdata->sc_G3;
+ cdata->GL = cdata->sc_GL;
+ cdata->GR = cdata->sc_GR;
+ vc->xcur = cdata->sc_xcur;
+ vc->ycur = cdata->sc_ycur;
+ cdata->m_om = cdata->sc_om;
+ cdata->flags = cdata->sflags;
+
+/*
+ cdata->c_attr = cdata->sc_attr;
+ cdata->awm = cdata->sc_awm;
+ cdata->sel = cdata->sc_selchar;
+ cdata->vtsgr = cdata->sc_vtsgr;
+ cdata->flag = 0;
+*/
+}
+
+void
+vt_clreol(vc)
+ struct vconsole *vc;
+{
+/*
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+*/
+ int counter;
+ int x = vc->xcur;
+ int y = vc->ycur;
+
+#ifdef SELFTEST
+ strcpy ( console_proc, "vt_clreol" );
+#endif
+
+ for ( counter=vc->xcur; counter<vc->xchars; counter++ )
+ do_render_noscroll ( ' ', vc );
+
+ vc->xcur = x;
+ vc->ycur = y;
+}
+
+/* index, move cursor down */
+
+void
+vt_ind(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+#ifdef SELFTEST
+ strcpy ( console_proc, "vt_ind" );
+#endif
+
+ vc->ycur++;
+
+ {
+ char buf[80];
+ sprintf ( buf, "{vt_ind [%d,%d] [%d,%d] }",
+ vc->xcur, vc->ycur, cdata->scrr_beg, cdata->scrr_end);
+ dprintf ( buf );
+ }
+
+ do_scrollcheck ( vc );
+}
+
+void
+vt_nel(vc)
+ struct vconsole *vc;
+{
+ vc->ycur++;
+ do_scrollcheck ( vc );
+ vc->xcur=0;
+}
+
+void
+vt_ri(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ if (vnodeconsolebug & 1)
+ vnodeconsolebug2 = ReadWord(0xf148a000);
+
+ vc->ycur--;
+
+ if (vc->ycur<=cdata->scrr_beg)
+ vc->ycur = cdata->scrr_beg;
+
+
+ if (vc->ycur <= cdata->scrr_beg) {
+ if (vnodeconsolebug & 4) {
+ if (ReadWord(0xf148a000) != vnodeconsolebug2) {
+ log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in vt_ri(1)\n",
+ vnodeconsolebug2, ReadWord(0xf148a000));
+ log(LOG_WARNING, "vc=%08x ycur=%d scrr_beg=%d\n", vc, vc->ycur, cdata->scrr_beg);
+ vnodeconsolebug2 = ReadWord(0xf148a000);
+ }
+ }
+ do_scrolldown ( vc );
+ if (vnodeconsolebug & 4) {
+ if (ReadWord(0xf148a000) != vnodeconsolebug2) {
+ log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in vt_ri(2)\n",
+ vnodeconsolebug2, ReadWord(0xf148a000));
+ log(LOG_WARNING, "vc=%08x ycur=%d scrr_beg=%d charmap=%08x\n", vc, vc->ycur, cdata->scrr_beg, vc->charmap);
+ vnodeconsolebug2 = ReadWord(0xf148a000);
+ }
+ }
+ vc->ycur = cdata->scrr_beg;
+ }
+}
+
+/* selective in line erase */
+
+int
+vt_sel(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ register int counter;
+ register int x = vc->xcur;
+ register int y = vc->ycur;
+
+ switch ( cdata->param[0] )
+ {
+ case 0: /* Delete to the end of the line */
+ for ( counter=x; counter<vc->xchars; counter++ )
+ do_render_noscroll ( ' ', vc );
+ break;
+
+ case 1: /* Delete to the beginning of the line */
+ vc->xcur = 0;
+ for ( counter=0; counter<x; counter++ )
+ do_render_noscroll ( ' ', vc );
+ break;
+
+ case 2: /* Delete the whole line */
+ default:
+ vc->xcur = 0;
+ for ( counter=0; counter<vc->xchars; counter++ )
+ do_render_noscroll ( ' ', vc );
+ break;
+ }
+
+ vc->xcur = x;
+ vc->ycur = y;
+ return 0;
+}
+
+void
+vt_cuu(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+ vc->ycur -= cdata->param[0];
+ vc->ycur = vc->ycur < 0 ? 0 : vc->ycur;
+}
+
+void
+vt_cub(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+
+ vc->xcur -= cdata->param[0];
+ cdata->param[0] = (cdata->param[0] < 0 ) ? 0 : cdata->param[0];
+}
+
+void
+vt_da(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ static u_char *response = (u_char *)DA_VT220;
+
+ cdata->report_chars = response;
+ cdata->report_count = 18;
+ respond(vc);
+}
+
+void
+vt_str(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ int counter;
+
+ if (cdata == NULL) {
+ return;
+ }
+
+ clr_params ( cdata );
+
+ cdata->state = STATE_INIT;
+ cdata->disable_function = 1;
+ cdata->m_om = 0; /* origin mode */
+ vc->xcur = vc->ycur = 0;
+ cdata->beepoff=default_beepstate;
+ cdata->simple_cursor_store = ' ';
+ cdata->scrr_beg = 0;
+ cdata->scrr_len = vc->ychars;
+ cdata->scrr_end = vc->ychars-1;
+ cdata->simple_cursor_on = 0;
+ cdata->nfgcol = 7;
+ cdata->nbgcol = 0;
+ cdata->fgcol = cdata->nfgcol;
+ cdata->bgcol = cdata->nbgcol;
+ cdata->attribs=cdata->fgcol<<8 | cdata->bgcol<<11;
+ cdata->sc_flag = 0; /* save cursor position */
+ cdata->flags = F_AWM;
+ cdata->irm = 0;
+
+ for ( counter=0; counter<MAXTABSTOPS; counter++ )
+ {
+ if ( !(counter%8) )
+ cdata->tab_stops[counter] = 1;
+ else
+ cdata->tab_stops[counter] = 0;
+ }
+}
+
+void
+vt_ris(vc)
+ struct vconsole *vc;
+{
+ vc->xcur = vc->ycur = 0;
+ vt_str(vc); /* and soft terminal reset */
+}
+
+void
+vt_cud(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+
+ cdata->param[0] = (cdata->param[0] > (cdata->scrr_end-vc->ycur))
+ ? (cdata->scrr_end-vc->ycur) : cdata->param[0];
+
+ vc->ycur += cdata->param[0];
+
+ do_scrollcheck ( vc );
+}
+
+void
+vt_tst(vc)
+ struct vconsole *vc;
+{
+ int counter, times;
+
+ for ( times=0; times<100; times++ );
+ for ( counter=32; counter<127; counter++ )
+ do_render ( counter, vc );
+}
+
+void
+vt_il(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ register int beg, end;
+
+ if ( vc->ycur >= (vc->ychars-2) )
+ return;
+
+ cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0];
+
+ beg = cdata->scrr_beg;
+ end = cdata->scrr_end;
+
+ cdata->scrr_beg = vc->ycur;
+ cdata->scrr_end = vc->ychars-1;
+
+ for ( ; cdata->param[0]>0; cdata->param[0]-- )
+ do_scrolldown( vc );
+
+ cdata->scrr_beg = beg;
+ cdata->scrr_end = end;
+}
+
+void
+vt_ic(vc)
+ struct vconsole *vc;
+{
+ int counter;
+ int ox, oy;
+ int *ptr = vc->charmap + (vc->xcur + vc->ycur*vc->xchars);
+ for ( counter=vc->xchars-vc->xcur; counter>=0; counter-- )
+ ptr[counter+1] = ptr[counter];
+ ptr[0] = ' ';
+ ox = vc->xcur; oy = vc->ycur;
+
+ for ( ; vc->xcur < vc->xchars; )
+ do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc );
+ vc->xcur = ox; vc->ycur = oy;
+}
+
+void
+vt_dch(vc)
+ struct vconsole *vc;
+{
+ int counter;
+ int ox, oy;
+ int *ptr = vc->charmap + (vc->ycur*vc->xchars);
+
+ for ( counter=vc->xcur; counter<(vc->xchars-1); counter++ )
+ ptr[counter] = ptr[counter+1];
+
+ ptr[vc->xchars] = ' ';
+
+ ox = vc->xcur; oy = vc->ycur;
+
+ for ( ; vc->xcur < vc->xchars; )
+ do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc );
+
+ vc->xcur = ox; vc->ycur = oy;
+}
+
+void
+vt_dl(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ register int beg, end;
+
+ cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0];
+ cdata->param[0] = cdata->param[0]>vc->xchars ? vc->xchars : cdata->param[0];
+
+/*
+ vc->xcur=0;
+*/
+
+ beg = cdata->scrr_beg;
+ end = cdata->scrr_end;
+
+ cdata->scrr_beg = vc->ycur;
+ cdata->scrr_end = vc->ychars-1;
+
+ for ( ; cdata->param[0]>0; cdata->param[0]-- )
+ do_scrollup( vc );
+
+ cdata->scrr_beg = beg;
+ cdata->scrr_end = end;
+}
+
+/* Set scrolling region */
+
+void
+vt_stbm(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ if((cdata->param[0] == 0) && (cdata->param[1] == 0))
+ {
+ cdata->xcur = 0;
+ cdata->ycur = 0;
+ cdata->scrr_beg = 0;
+ cdata->scrr_len = vc->ychars;
+ cdata->scrr_end = cdata->scrr_len - 1;
+ return;
+ }
+ if(cdata->param[1] <= cdata->param[0])
+ return;
+
+ /* range parm 1 */
+
+ cdata->scrr_beg = cdata->param[0]-1;
+ cdata->scrr_len = cdata->param[1] - cdata->param[0] + 1;
+ cdata->scrr_end = cdata->param[1]-1;
+
+/*
+ if (cdata->scrr_beg<0)
+ cdata->scrr_beg = 0;
+*/
+
+ if (cdata->scrr_end>(vc->ychars-1))
+ cdata->scrr_end = vc->ychars-1;
+
+ cdata->scrr_len = cdata->scrr_end - cdata->scrr_beg - 1;
+{
+ char buf[80];
+ sprintf ( buf, "scrr_beg %d, scrr_end %d", cdata->scrr_beg,
+ cdata->scrr_end );
+ dprintf ( buf );
+}
+
+ cdata->flags &= ~F_LASTCHAR;
+}
+
+void
+vt_dsr(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ static u_char *answr = (u_char *)"\033[0n";
+ static u_char *panswr = (u_char *)"\033[?13n"; /* Printer Unattached */
+ static u_char *udkanswr = (u_char *)"\033[?21n"; /* UDK Locked */
+ static u_char *langanswr = (u_char *)"\033[?27;1n"; /* North American*/
+ static u_char buffer[16];
+ int i = 0;
+
+ switch(cdata->param[0])
+ {
+ case 5: /* return status */
+ cdata->report_chars = answr;
+ cdata->report_count = 4;
+ respond(vc);
+ break;
+
+ case 6: /* return cursor position */
+ buffer[i++] = 0x1b;
+ buffer[i++] = '[';
+ if((vc->ycur+1) > 10)
+ buffer[i++] = ((vc->ycur+1) / 10) + '0';
+ buffer[i++] = ((vc->ycur+1) % 10) + '0';
+ buffer[i++] = ';';
+ if((vc->xcur+1) > 10)
+ buffer[i++] = ((cdata->xcur+1) / 10) + '0';
+ buffer[i++] = ((vc->xcur+1) % 10) + '0';
+ buffer[i++] = 'R';
+ buffer[i++] = '\0';
+
+ cdata->report_chars = buffer;
+ cdata->report_count = i;
+ respond(vc);
+ break;
+
+ case 15: /* return printer status */
+ cdata->report_chars = panswr;
+ cdata->report_count = 6;
+ respond(vc);
+ break;
+
+ case 25: /* return udk status */
+ cdata->report_chars = udkanswr;
+ cdata->report_count = 6;
+ respond(vc);
+ break;
+
+ case 26: /* return language status */
+ cdata->report_chars = langanswr;
+ cdata->report_count = 8;
+ respond(vc);
+ break;
+
+ default: /* nothing else valid */
+ break;
+ }
+}
+
+void
+vt_su(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0];
+ cdata->param[0] = cdata->param[0]>(vc->xchars-1) ? vc->xchars-1 : cdata->param[0];
+
+ do_scrollup ( vc );
+}
+
+void
+vt_set_dec_priv_qm(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ switch(cdata->param[0])
+ {
+ case 7: /* AWM - auto wrap mode */
+ cdata->flags |= F_AWM;
+ break;
+
+ /* Implement these */
+ case 1: /* CKM - cursor key mode */
+ case 3: /* COLM - column mode */
+ case 6: /* OM - origin mode */
+ case 8: /* ARM - auto repeat mode */
+ case 25: /* TCEM - text cursor enable mode */
+ break;
+
+ case 0: /* error, ignored */
+ case 2: /* ANM - ansi/vt52 mode */
+ case 4: /* SCLM - scrolling mode */
+ case 5: /* SCNM - screen mode */
+ case 9: /* INLM - interlace mode */
+ case 10: /* EDM - edit mode */
+ case 11: /* LTM - line transmit mode */
+ case 12: /* */
+ case 13: /* SCFDM - space compression / field delimiting */
+ case 14: /* TEM - transmit execution mode */
+ case 15: /* */
+ case 16: /* EKEM - edit key execution mode */
+ case 42: /* NRCM - 7bit NRC characters */
+ break;
+ }
+}
+
+void
+vt_keyappl(vc)
+ struct vconsole *vc;
+{
+ dprintf ( "VT_KEYAPPL" );
+}
+
+void
+vt_clrtab(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ int i;
+
+ if(cdata->param[0] == 0)
+ cdata->tab_stops[vc->xcur] = 0;
+ else if(cdata->param[0] == 3)
+ {
+ for(i=0; i<MAXTABSTOPS; i++)
+ cdata->tab_stops[i] = 0;
+ }
+}
+
+/*
+void
+vt_cuf(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0];
+
+ vc->xcur += cdata->param[0];
+
+ cdata->param[0] = (cdata->param[0] > vc->xchars ) ? vc->xchars : cdata->param[0];
+}
+*/
+
+void
+vt_cuf(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ register int p = cdata->param[0];
+
+ if(vc->xcur == ((vc->xchars)-1)) /* already at right margin */
+ return;
+ if(p <= 0) /* parameter min = 1 */
+ p = 1;
+ else if(p > ((vc->xchars)-1)) /* parameter max = 79 */
+ p = ((vc->xchars)-1);
+ if((vc->xcur + p) > ((vc->xchars)-1)) /* not more than */
+ p = ((vc->xchars)-1) - vc->xcur;
+ vc->xcur += p;
+}
+
+void
+vt_sgr(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ register int i=0;
+
+ do
+ {
+ vc->SGR ( vc, cdata->param[i] );
+ switch ( cdata->param[i++] )
+ {
+ case 0: /* reset to normal attributes */
+ cdata->fgcol = cdata->nfgcol;
+ cdata->bgcol = cdata->nbgcol;
+ cdata->attribs=cdata->fgcol<<8 | cdata->bgcol<<11;
+ break;
+ case 1: /* bold */
+ cdata->attribs |= BOLD;
+ break;
+ case 4: /* underline */
+ cdata->attribs |= UNDERLINE;
+ break;
+ case 5: /* blinking */
+ cdata->attribs |= BLINKING;
+ break;
+ case 7: /* reverse */
+ cdata->fgcol = cdata->nbgcol;
+ cdata->bgcol = cdata->nfgcol;
+ cdata->attribs |= REVERSE;
+ cdata->attribs&=~0x3F00;
+ cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11;
+ break;
+ case 22: /* not bold */
+ cdata->attribs &= ~BOLD;
+ break;
+ case 24: /* not underlined */
+ cdata->attribs &= ~UNDERLINE;
+ break;
+ case 25: /* not blinking */
+ cdata->attribs &= ~BLINKING;
+ break;
+ case 27: /* not reverse */
+ cdata->attribs &= ~REVERSE;
+ cdata->fgcol = cdata->nfgcol;
+ cdata->bgcol = cdata->nbgcol;
+ cdata->attribs&=~0x3F00;
+ cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11;
+ break;
+
+ default:
+ if ( ( cdata->param[i-1] > 29 )&&( cdata->param[i-1] < 38 ) )
+ {
+ vc->SETFGCOL ( vc, cdata->param[i-1] - 30 );
+ cdata->fgcol = cdata->param[i-1] - 30;
+ cdata->attribs&=~0x3F00;
+ cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11;
+
+ }
+ if ( ( cdata->param[i-1] > 39 )&&( cdata->param[i-1] < 48 ) )
+ {
+ vc->SETBGCOL ( vc, cdata->param[i-1] - 40 );
+ cdata->bgcol = cdata->param[i-1] - 40;
+ cdata->attribs&=~0x3F00;
+ cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11;
+ }
+ }
+ } while ( i<=cdata->parami );
+}
+
+void
+vt_clreos(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ int ptr;
+ if ( vc == vconsole_current )
+ vc->R_CLREOS ( vc, cdata->param[0] );
+ else
+ vconsole_pending = vc->number;
+
+ switch ( cdata->param[0] )
+ {
+ case 0: /* Erase from cursor to end of screen */
+ for ( ptr=vc->xcur + vc->ycur * vc->xchars
+ ; ptr<(vc->xchars*vc->ychars); ptr++ )
+ vc->charmap[ptr]=0x20;
+ break;
+
+ case 1: /* Erase from start to cursor */
+ for ( ptr=0;
+ ptr<vc->ycur*vc->xchars + vc->xcur;
+ ptr++ )
+ vc->charmap[ptr]=0x20;
+ break;
+
+ case 2: /* Blitz the whole bloody thing */
+ if ((vc->flags&LOSSY)==0)
+ mapped_cls(vc);
+ if (vc==vconsole_current)
+ vc->CLS(vc);
+ else
+ vconsole_pending = vc->number;
+ break;
+ }
+}
+
+void
+vt_set_ansi(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ switch(cdata->param[0])
+ {
+ case 0: /* error, ignored */
+ case 1: /* GATM - guarded area transfer mode */
+ case 2: /* KAM - keyboard action mode */
+ case 3: /* CRM - Control Representation mode */
+ case 20: /* LNM - line feed / newline mode */
+ break;
+
+ case 4: /* IRM - insert replacement mode */
+ cdata->irm = 1;
+ break;
+
+ case 5: /* SRTM - status report transfer mode */
+ case 6: /* ERM - erasue mode */
+ case 7: /* VEM - vertical editing mode */
+ case 10: /* HEM - horizontal editing mode */
+ case 11: /* PUM - position unit mode */
+ case 12: /* SRM - send-receive mode */
+ case 13: /* FEAM - format effector action mode */
+ case 14: /* FETM - format effector transfer mode */
+ case 15: /* MATM - multiple area transfer mode */
+ case 16: /* TTM - transfer termination */
+ case 17: /* SATM - selected area transfer mode */
+ case 18: /* TSM - tabulation stop mode */
+ case 19: /* EBM - editing boundary mode */
+ break;
+ }
+}
+
+void
+vt_reset_ansi(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ switch(cdata->param[0])
+ {
+ /* Implement these */
+ case 0: /* error, ignored */
+ case 1: /* GATM - guarded area transfer mode */
+ case 2: /* KAM - keyboard action mode */
+ case 3: /* CRM - Control Representation mode */
+ case 20: /* LNM - line feed / newline mode */
+ break;
+
+ case 4: /* IRM - insert replacement mode */
+ cdata->irm = 0;
+ break;
+
+ case 5: /* SRTM - status report transfer mode */
+ case 6: /* ERM - erasue mode */
+ case 7: /* VEM - vertical editing mode */
+ case 10: /* HEM - horizontal editing mode */
+ case 11: /* PUM - position unit mode */
+ case 12: /* SRM - send-receive mode */
+ case 13: /* FEAM - format effector action mode */
+ case 14: /* FETM - format effector transfer mode */
+ case 15: /* MATM - multiple area transfer mode */
+ case 16: /* TTM - transfer termination */
+ case 17: /* SATM - selected area transfer mode */
+ case 18: /* TSM - tabulation stop mode */
+ case 19: /* EBM - editing boundary mode */
+ break;
+ }
+}
+
+/* DRN */
+
+void
+do_render_noscroll(c, vc)
+ char c;
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ /* THE RENDER STAGE **********************************/
+
+ if ((c>=0x20)&&(c<=0x7f))
+ {
+ if (((vc->flags)&(LOSSY))==0)
+ {
+ if ( vc->charmap[vc->xcur+vc->ycur*vc->xchars] != c|cdata->attribs )
+ {
+ if ( vc==vconsole_current )
+ vc->RENDER ( vc, c );
+ else
+ vconsole_pending = vc->number;
+ }
+ vc->charmap[ vc->xcur + vc->ycur*vc->xchars ] = c|cdata->attribs;
+ }
+ else
+ {
+ if ( vc==vconsole_current )
+ vc->RENDER ( vc, c );
+ else
+ vconsole_pending = vc->number;
+ }
+ }
+
+ vc->xcur++;
+
+ /*do_scrollcheck ( vc );*/
+}
+
+#ifdef SIMPLE_CURSOR
+void
+simple_cursor_on(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ if (cdata->simple_cursor_on)
+ return 0;
+ if (vc!=vconsole_current)
+ return 0;
+ if (((vc->flags)&(LOSSY))==0)
+ {
+ cdata->simple_cursor_store = vc->charmap[ vc->xcur + vc->ycur*vc->xchars ];
+ vc->RENDER ( vc, SIMPLE_CURSOR_CHAR );
+ }
+ cdata->simple_cursor_on = 1;
+}
+
+void
+simple_cursor_off(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ if (!cdata->simple_cursor_on)
+ return 0;
+ if (vc!=vconsole_current)
+ return 0;
+ if (((vc->flags)&(LOSSY))==0)
+ {
+ vc->RENDER ( vc, cdata->simple_cursor_store );
+ }
+ cdata->simple_cursor_on = 0;
+}
+#endif
+
+/* DSC */
+void
+do_scrollcheck(vc)
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+
+ /* BOUNDARY CHECK ************************************/
+ if ((vc->xcur >= (vc->xchars))&&((cdata->flags&F_AWM)!=0))
+ {
+ cdata->flags|=F_LASTCHAR;
+ cdata->lastpos = vc->ycur*vc->xchars+vc->xcur;
+ }
+
+ /* SCROLL CHECK *************************************/
+ if ( vc->ycur >= cdata->scrr_end+1 )
+ {
+ do_scrollup ( vc );
+ }
+}
+
+/* DR */
+
+int
+do_render(c, vc)
+ char c;
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata = (struct vt220_info *)vc->data;
+ /* THE RENDER STAGE **********************************/
+
+ if (((cdata->flags&F_AWM)==0)&&(vc->xcur >= 20))
+ return 0;
+
+ if ( cdata->flags & F_LASTCHAR )
+ {
+ if ( cdata->lastpos==vc->ycur*vc->xchars+vc->xchars)
+ {
+ vc->ycur++;
+ vc->xcur = 0;
+ cdata->flags &= ~F_LASTCHAR;
+ do_scrollcheck(vc);
+ }
+ else
+ {
+ cdata->flags &= ~F_LASTCHAR;
+ }
+ }
+
+ if ((c>=0x20)&&(c<=0x7f))
+ {
+ if (((vc->flags)&(LOSSY))==0)
+ {
+ if ( cdata->irm == 0 )
+ {
+ if(vc->charmap[vc->xcur+vc->ycur*vc->xchars]!=c|cdata->attribs )
+ {
+ if ( vc==vconsole_current )
+ vc->RENDER ( vc, c );
+ else
+ vconsole_pending = vc->number;
+ }
+ vc->charmap[vc->xcur+vc->ycur*vc->xchars ] = c|cdata->attribs;
+ }
+ else
+ {
+ int counter;
+ int ox, oy;
+ int *ptr = vc->charmap + (vc->xcur + vc->ycur*vc->xchars);
+ for ( counter=vc->xchars-vc->xcur; counter>=0; counter-- )
+ ptr[counter+1] = ptr[counter];
+ ptr[0] = c;
+ ox = vc->xcur; oy = vc->ycur;
+
+ for ( ; vc->xcur < vc->xchars; )
+ do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc );
+ vc->xcur = ox; vc->ycur = oy;
+
+ }
+ }
+ else
+ {
+ if ( vc==vconsole_current )
+ vc->RENDER ( vc, c );
+ else
+ vconsole_pending = vc->number;
+ }
+ }
+
+ vc->xcur++;
+
+ do_scrollcheck ( vc );
+
+ if ( cdata->flags & F_LASTCHAR )
+ vc->xcur--;
+ return 0;
+}
+
+int
+TERMTYPE_PUTSTRING(string, length, vc)
+ char *string;
+ int length;
+ struct vconsole *vc;
+{
+ struct vt220_info *cdata;
+ register char c;
+ char dc[] = "x\0";
+ cdata = (struct vt220_info *)vc->data;
+
+ /* A piece of saftey code */
+ if ( vconsole_current->vtty == 0 )
+ return 0;
+
+#ifdef SIMPLE_CURSOR
+ if ( vc==vconsole_current )
+ if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_off ( vc );
+#else
+ if ( vc==vconsole_current )
+ vc->CURSORUPDATE (vc);
+#endif
+
+ while ( ((c=*(string++))!=0) && ((length--)>0) )
+ {
+
+ if ( cdata->state != STATE_INIT )
+ cdata->flags &= ~F_LASTCHAR;
+
+ if ( ( c == 0x0a ) || ( c== 0x0d ) )
+ cdata->flags &= ~F_LASTCHAR;
+
+/* Middle mouse button freezes the display while active */
+
+ while ((ReadByte(IO_MOUSE_BUTTONS) & MOUSE_BUTTON_MIDDLE) == 0);
+
+/* Left mouse button slows down the display speed */
+
+ if ((ReadByte(IO_MOUSE_BUTTONS) & MOUSE_BUTTON_LEFT) == 0)
+ delay(5000);
+
+/* Always process characters in the range of 0x00 to 0x1f */
+
+
+#ifdef DEBUGTERM
+*dc = c;
+switch (c)
+{
+ case 0x0a: dprintf ( "[0a]" ); break;
+ case 0x0d: dprintf ( "[0d]" ); break;
+ case 0x0c: dprintf ( "[0c]" ); break;
+ case 0x1b: dprintf ( "[1b]" ); break;
+}
+#endif
+ if ( c <= 0x1f )
+ {
+ if ( cdata->disable_function )
+ {
+ if ( cdata->flags & F_LASTCHAR )
+ {
+ if ( cdata->lastpos==vc->ycur*vc->xchars+vc->xchars)
+ {
+ vc->ycur++;
+ vc->xcur = 0;
+ cdata->flags &= ~F_LASTCHAR;
+ do_scrollcheck(vc);
+ }
+ else
+ {
+ cdata->flags &= ~F_LASTCHAR;
+ }
+ }
+
+ switch (c)
+ {
+ case 0x00: /* NUL */
+ case 0x01: /* SOH */
+ case 0x02: /* STX */
+ case 0x03: /* ETX */
+ case 0x04: /* EOT */
+ case 0x05: /* ENQ */
+ case 0x06: /* ACK */
+ break;
+
+ case 0x07: /* BEL */
+ beep_generate();
+ if ( !cdata->beepoff )
+ c = 'G';
+ break;
+
+ case 0x08: /* BS */
+ cdata->flags &= ~F_LASTCHAR;
+ if ( vc->xcur>0 )
+ vc->xcur--;
+ break;
+
+ case 0x09: /* TAB */
+ while ( vc->xcur < vc->xchars-1 )
+ {
+ vc->xcur++;
+ if (cdata->tab_stops[vc->xcur])
+ break;
+ }
+ break;
+
+ case 0x0a:
+ cdata->flags &= ~F_LASTCHAR;
+ vc->ycur++;
+ do_scrollcheck ( vc );
+ break;
+
+ case 0x0c:
+ cdata->flags &= ~F_LASTCHAR;
+ if ((vc->flags&LOSSY)==0)
+ mapped_cls(vc);
+ if (vc==vconsole_current)
+ vc->CLS(vc);
+ vc->xcur=0;
+ vc->ycur=0;
+
+ break;
+ case 0x0d:
+ cdata->flags &= ~F_LASTCHAR;
+ vc->xcur=0;
+ break;
+
+ case 0x10: /* DLE */
+ case 0x11: /* DC1/XON */
+ case 0x12: /* DC2 */
+ case 0x13: /* DC3/XOFF */
+ case 0x14: /* DC4 */
+ case 0x15: /* NAK */
+ case 0x16: /* SYN */
+ case 0x17: /* ETB */
+ break;
+
+ case 0x18: /* CAN */
+ cdata->state = STATE_INIT;
+ clr_params(cdata);
+ break;
+
+ case 0x19: /* EM */
+ break;
+
+ case 0x1a: /* SUB */
+ cdata->state = STATE_INIT;
+ clr_params(cdata);
+ break;
+
+ case 0x1b: /* ESC */
+ cdata->state = STATE_ESC;
+ clr_params(cdata);
+ break;
+
+ case 0x1c: /* FS */
+ case 0x1d: /* GS */
+ case 0x1e: /* RS */
+ case 0x1f: /* US */
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* 0x20 to 0xff depends on current state */
+ switch ( cdata->state )
+ {
+ case STATE_INIT:
+ do_render ( c, vc );
+ break;
+
+ case STATE_ESC:
+#ifdef DEBUGTERM
+{
+ char buf[]="x";
+ buf[0] = c;
+ dprintf ( buf );
+}
+#endif
+ switch (c)
+ {
+ case '7': /* SAVE CUSOR */
+ vt_sc ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case '8': /* RESTORE CUSOR */
+ vt_rc ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case '=':
+ vt_keyappl ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case '>': /* Keypad numeric mode */
+#ifdef DEBUGTERM
+dprintf ( "\r\nKEYPAD NUMERIC MODE\r\n ");
+#endif
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'D':
+ vt_ind ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'E':
+ vt_nel ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'H':
+ cdata->tab_stops[vc->xcur] = 1;
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'M':
+ vt_ri ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'N':
+ cdata->Gs = cdata->G2;
+ cdata->ss = 1;
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'O':
+ cdata->Gs = cdata->G3;
+ cdata->ss = 1;
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'P':
+ cdata->dcs_state = DCS_INIT;
+ cdata->state = STATE_DCS;
+ break;
+
+ case 'Z':
+ vt_da ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case '~':
+ cdata->GR = cdata->G1;
+ cdata->state = STATE_INIT;
+ break;
+
+ case '[':
+ clr_params ( cdata );
+ cdata->state = STATE_CSI;
+ break;
+
+ case '\\':
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'c':
+ vt_ris ( vc );
+ cdata->state = STATE_CSI;
+ break;
+
+ case 'n':
+ cdata->GL = cdata->G2;
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'o':
+ cdata->GL = cdata->G3;
+ cdata->state = STATE_INIT;
+ break;
+
+ case '}':
+ cdata->GR = cdata->G2;
+ cdata->state = STATE_INIT;
+ break;
+
+ case '|':
+ cdata->GR = cdata->G3;
+ cdata->state = STATE_INIT;
+ break;
+
+ default:
+ do_render ( c, vc );
+ cdata->state = STATE_INIT;
+ break;
+ }
+ break;
+
+ case STATE_CSIQM:
+#ifdef DEBUGTERM
+{
+ char buf[]="x";
+ buf[0] = c;
+ dprintf ( buf );
+}
+#endif
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': /* parameters */
+ cdata->param[cdata->parami] *= 10;
+ cdata->param[cdata->parami] += (c-'0');
+ break;
+
+ case ';': /* next parameter */
+ cdata->parami =
+ (cdata->parami+1 < MAXPARMS) ?
+ cdata->parami+1 : cdata->parami;
+ break;
+
+ case 'h':
+ vt_set_dec_priv_qm ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'l':
+ vt_reset_dec_priv_qm ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'n':
+ vt_dsr ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'K':
+ vt_sel ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ default:
+ do_render ( '[', vc );
+ do_render ( c, vc );
+ cdata->state = STATE_INIT;
+ {
+ register int counter;
+ for ( counter=0; counter<=cdata->parami; counter++ )
+ {
+ do_render ( '@', vc );
+ }
+ }
+ do_render ( c, vc );
+ break;
+ }
+
+ case STATE_CSI:
+#ifdef DEBUGTERM
+{
+ char buf[]="x";
+ buf[0] = c;
+ dprintf ( buf );
+}
+#endif
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': /* parameters */
+ cdata->param[cdata->parami] *= 10;
+ cdata->param[cdata->parami] += (c-'0');
+ break;
+
+ case ';': /* next parameter */
+ cdata->parami =
+ (cdata->parami+1 < MAXPARMS) ?
+ cdata->parami+1 : cdata->parami;
+ break;
+
+ case '?': /* ESC [ ? family */
+ cdata->state = STATE_CSIQM;
+ break;
+
+ case '@': /* insert char */
+ vt_ic ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ /*
+ case '!':
+ cdata->state = STATE_STR;
+ break;
+ */
+
+ case 'A': /* cursor up */
+ vt_cuu ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'B': /* cursor down */
+ vt_cud ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'C':
+ vt_cuf ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'D': /* cursor back */
+ vt_cub ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'H': /* direct cursor addressing */
+ vt_curadr ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'J': /* erase screen */
+ vt_clreos ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'K': /* erase line */
+ vt_clreol ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'L': /* insert line */
+ vt_il ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'M': /* delete line */
+ vt_dl ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'P': /* Delete chars */
+ vt_dch ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'S': /* scroll up */
+ vt_su ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'c':
+ vt_da ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'f':
+ vt_curadr ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'h':
+ vt_set_ansi ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'l':
+ vt_reset_ansi ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'm': /* select graphic rendition */
+ vt_sgr( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'n':
+ vt_dsr ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'r': /* set scrolling region */
+ vt_stbm ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ case 'y':
+ vt_tst ( vc );
+ cdata->state = STATE_INIT;
+ break;
+
+ default:
+ do_render ( '[', vc );
+ do_render ( c, vc );
+ cdata->state = STATE_INIT;
+ {
+ register int counter;
+ for ( counter=0; counter<=cdata->parami; counter++ )
+ {
+ do_render ( '@', vc );
+ }
+ }
+ do_render ( c, vc );
+ cdata->state = STATE_INIT;
+ break;
+ }
+ break;
+
+ default:
+ cdata->state = STATE_INIT;
+ break;
+ }
+ }
+ }
+#ifdef SIMPLE_CURSOR
+ if ( vc==vconsole_current )
+ if ( vc->CURSORUPDATE(vc)==-1 )
+ simple_cursor_on ( vc );
+#else
+ if ( vc==vconsole_current )
+ vc->CURSORUPDATE (vc);
+#endif
+ return 0;
+}
+
+void
+console_debug()
+{
+}
+
+int
+vt220_swapin(vc)
+ struct vconsole *vc;
+{
+#ifdef SIMPLE_CURSOR
+ if ( vc==vconsole_current )
+ if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_on ( vc );
+#else
+ if ( vc==vconsole_current )
+ vc->CURSORUPDATE (vc);
+#endif
+ return 0;
+}
+
+int
+vt220_swapout(vc)
+ struct vconsole *vc;
+{
+ return 0;
+}
+
+
+int
+vt220_sleep(vc)
+ struct vconsole *vc;
+{
+#ifdef SIMPLE_CURSOR
+ if ( vc==vconsole_current )
+ if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_off ( vc );
+#else
+ if ( vc==vconsole_current )
+ vc->CURSORUPDATE (vc);
+#endif
+ vc->FLASH ( vc, 0 );
+ vc->CURSOR_FLASH ( vc, 0 );
+ return 0;
+}
+
+int
+vt220_wake(vc)
+ struct vconsole *vc;
+{
+ vc->FLASH ( vc, 1 );
+ vc->CURSOR_FLASH ( vc, 1 );
+
+#ifdef SIMPLE_CURSOR
+ if ( vc==vconsole_current )
+ if ( vc->CURSORUPDATE(vc)==-1 )
+ simple_cursor_on ( vc );
+#else
+ if ( vc==vconsole_current )
+ vc->CURSORUPDATE (vc);
+#endif
+ return 0;
+}
+
+int
+vt220_scrollback(vc)
+ struct vconsole *vc;
+{
+ return -1;
+}
+
+int
+vt220_scrollforward(vc)
+ struct vconsole *vc;
+{
+ return -1;
+}
+
+int
+vt220_scrollbackend(vc)
+ struct vconsole *vc;
+{
+ return -1;
+}
+
+int
+vt220_debugprint(vc)
+ struct vconsole *vc;
+{
+ printf ( "VT220 TERMINAL EMULATOR\n\n" );
+ printf ( "no information\n" );
+ printf ( "\n" );
+ return 0;
+}
+
+int
+vt220_modechange(vc)
+ struct vconsole *vc;
+{
+ if (vc->number >= 64)
+ return(0);
+
+ if (vc == NULL) {
+ return(EINVAL);
+ }
+ vt_str ( vc );
+ if (vc->charmap)
+ {
+ free ( vc->charmap, M_DEVBUF );
+
+ MALLOC (vc->charmap, int *, sizeof(int)*((vc->xchars)*(vc->ychars)), M_DEVBUF, M_NOWAIT );
+ if ((vc->flags&LOSSY)==0)
+ mapped_cls(vc);
+ if (vc==vconsole_current)
+ vc->CLS(vc);
+ vc->xcur=0;
+ vc->ycur=0;
+ }
+
+ return 0;
+}
+
+int
+vt220_attach(vc, a, b, aux)
+ struct vconsole *vc;
+ struct device *a;
+ struct device *b;
+ void *aux;
+{
+ return 0;
+}
+
+struct terminal_emulator vt220 = {
+ vt220_name,
+ vt220_init,
+ vt220_putstring,
+ vt220_swapin,
+ vt220_swapout,
+ vt220_sleep,
+ vt220_wake,
+ vt220_scrollback,
+ vt220_scrollforward,
+ vt220_scrollbackend,
+ vt220_debugprint,
+ vt220_modechange,
+ vt220_attach
+};
--- /dev/null
+/* $NetBSD: vt220.h,v 1.2 1996/03/18 19:33:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1995 Melvyn Tang-Richardson
+ * Copyright (c) 1994-1995 RiscBSD kernel team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * vt220.h
+ *
+ * VT220 emulation header file
+ *
+ * Created : 17/09/94
+ */
+
+#define MAXTABSTOPS 132
+
+#define STATE_INIT 0
+#define STATE_HASH 1
+#define STATE_BROPN 2
+#define STATE_BRCLO 3
+#define STATE_STAR 4
+#define STATE_PLUS 5
+#define STATE_MINUS 6
+#define STATE_DOT 7
+#define STATE_SLASH 8
+#define STATE_AMPSND 9
+#define SHP_INIT 10
+#define STATE_ESC 11
+#define STATE_CSIQM 14
+#define STATE_CSI 15
+#define STATE_DCS 16
+#define STATE_SCA 17
+#define STATE_STR 18
+
+/* sub-states for Device Control String processing */
+
+#define DCS_INIT 0 /* got ESC P ... */
+#define DCS_AND_UDK 1 /* got ESC P ... | */
+#define DCS_UDK_DEF 2 /* got ESC P ... | fnckey / */
+#define DCS_UDK_ESC 3 /* got ESC P ... | fnckey / ... ESC */
+#define DCS_DLD_DSCS 4 /* got ESC P ... { */
+#define DCS_DLD_DEF 5 /* got ESC P ... { dscs */
+#define DCS_DLD_ESC 6 /* got ESC P ... { dscs ... / ... ESC */
+
+#define F_AWM (1)
+#define F_LASTCHAR (2)
+#define F_IRM (3)
+
+#define MAXPARMS 10
+
+struct vt220_info {
+ int tab_stops[MAXTABSTOPS];
+ int state;
+ int hp_state;
+ int disable_function;
+ int lastchar;
+ int beepoff;
+ int param[MAXPARMS];
+ int parami;
+ u_char m_om, sc_om; /* flag, vt100 mode, origin mode */
+ u_char scrr_beg;
+ u_char scrr_len;
+ u_char scrr_end;
+ int simple_cursor_store;
+ int simple_cursor_on;
+
+ int dcs_state;
+
+ int G0, G1, G2, G3, GL, GR, sc_G0, sc_G1, sc_G2, sc_G3, sc_GL, sc_GR;
+ int Gs, ss;
+ int xcur, ycur, sc_xcur, sc_ycur;
+ int sc_flag;
+
+ char *report_chars;
+ int report_count;
+ int cursor_on;
+
+ int fgcol, bgcol;
+ int nfgcol, nbgcol;
+
+ int attribs;
+ int flags;
+ int sflags;
+
+ int lastpos;
+ int irm;
+};
+
--- /dev/null
+/* $NetBSD: rd_hooks.c,v 1.5 1996/03/28 21:14:13 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Gordon W. Ross
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+
+#include <vm/vm.h>
+#include <vm/vm_map.h>
+#include <vm/vm_kern.h>
+
+#include <dev/ramdisk.h>
+
+#ifndef RAMDISK_SIZE
+#define RAMDISK_SIZE 0
+#endif
+
+/*extern int boothowto;*/
+extern u_int ramdisc_size;
+struct rd_conf *bootrd = NULL;
+
+int load_ramdisc_from_floppy __P((struct rd_conf *rd, dev_t dev));
+
+/*
+ * This is called during autoconfig.
+ */
+int
+rd_match_hook(parent, self, aux)
+ struct device *parent;
+ void *self;
+ void *aux;
+{
+ return (1);
+}
+
+void
+rd_attach_hook(unit, rd)
+ int unit;
+ struct rd_conf *rd;
+{
+ if (unit == 0) {
+ if (ramdisc_size == 0 && RAMDISK_SIZE)
+ ramdisc_size = (RAMDISK_SIZE * 1024);
+
+ if (ramdisc_size != 0) {
+ rd->rd_size = round_page(ramdisc_size);
+ rd->rd_addr = (caddr_t)kmem_alloc(kernel_map, ramdisc_size);
+ rd->rd_type = RD_KMEM_FIXED;
+ bootrd = rd;
+ }
+ }
+ printf("rd%d: allocated %dK (%d blocks)\n", unit, rd->rd_size / 1024, rd->rd_size / DEV_BSIZE);
+}
+
+
+/*
+ * This is called during open (i.e. mountroot)
+ */
+
+void
+rd_open_hook(unit, rd)
+ int unit;
+ struct rd_conf *rd;
+{
+/* I use the ramdisc for other testing ... */
+#if 0
+ if (unit == 0) {
+ /* The root ramdisk only works single-user. */
+ boothowto |= RB_SINGLE;
+ }
+#endif
+}
--- /dev/null
+Currently the bootloader can only be built under RiscOS as this
+is the platform which it runs on. A spark file version of the
+bootloader source code is also available
+
+[ From boot/README ]
+Ok, this is the bootloader source that can be used to boot NetBSD/arm32
+from RISCOS. This code was written for use with Norcroft C and
+objasm under RISCOS. It has been modified to compile under NetBSD/arm32
+but is as yet untested.
+
+It is provided here for the moment as example code for a boot loader
+and will be updated shortly to compile under NetBSD/arm32
--- /dev/null
+3135 - fixed mode selection on boot
+ - page up/down, insert and delete now generate the correct codes in
+ the console
+ - the configured modesare now compiled in a separate file rather
+ than in vidcconsole.c
+ - The eb timeout reduced to 30 secs
+
+ - clreos problems fixed
+ - / on the keypad generated the correct code
+ - the block cursor hove down 2 scan lines to align with characters
+ - extended irq renamed netslot
+ - extra double mapping of kstack removed
+ - kstack located at efbfe000
+ - implementation of cpu_swapin() to remap the kstack
+ - patch to vm_glue to use kmem_alloc for the kstack
+ - extra pmap debugging code added with DEBUG669
+ - the pventry tables can not be dumped from the kshell
+ or from a running system.
+
+ - merged console code v133 into kernel
+ - the disklabel code no longer prints a warning if a HD is found
+ without a adfs partition
+ - the kbd driver now is capable of setting the keyboard leds.
+ - added ioctl to set the keyboard leds.
+ - added a routine to read the keyboard state.
+ - added a routine to set the keyboard state.
+ - added some prototypes to kbd.h
+ - implmented irq_setmasks() as an assembly function.
+ - added an extra disable irq mask
+ - the irq bits from IOMD reg A are cleared as soon as req A is read
+ - Debugged the plip driver. The ip packet is now word aligned when
+ passed to the upper network levels
+
+20/09/95
+ - the cpu_switch routine checks the amount of stack space used when
+ swapping in a task and prints a warning when 6K has been used
+ - removed the remnants of the old kstack double mapping
+ - a separate message is printed for umounts during a halt.
+ - added extra validation in copyin() copyout() copyinstr() and
+ copyoutstr()
+ - podule irq handler no longer panics
+ - Lark A16 podule now recognised
+ - section permission faults now cause bus errors
+ - the syscall handler now correctly uses bcopy to copy the register
+ passed parameters
+ - the copyin() function now validates the uaddrs argumant
+ - the kstack is filled with a know pattern on a fork()
+ - the postmortem code will check the size of the kstack fill pattern
+ - the assembly bcopyinout() now returns EFAULT on error
+ - the copyin() copyout() copyinstr() copyoutstr() now return EFAULT
+ if the validation checks fail.
+23/09/95
+ - the fault handler will report faults from (fu/su)iwintr()
+ - added new pmap function to return the address of the next physical
+ page (pmap_next_phys_page).
+ - added code to machdep.c to compare the page number against
+ pmap_next_phys_page() to try and locate source to kernel size
+ limit
+ - added option to syscall_special (32) to return the address of the
+ next physical page.
+ - fixed the primary bootstrap to map more memory for the secondary
+ bootstrap to use.
+ - The 936K kernel size limit has been removed.
+ - Added support for KTRACE in syscall.c
+ - Seondary bootstrap now zeros down its memory
+ - cpu_switch now zeros curpcb while there is no valid process
+ -
+1/10/95
+ - cpuswitch now detects trahsed stacks.
+ - new compile option for generation of enhanced postmortem debugging
+ - merged console code 183b
+ - implemented a memcpy routine
+ - removed remnants of the kstackpte's
+ - cleaned old commented debugging code out of cpu_switch
+ - Added new comments in exception.S
+ - userret() check for a non-zero proc pointer
+ - extended postmortem debug for cpu_switch bug
+ - updated prototype declarations in machdep.c
+ - fixed passing of proc0 pointer into cpu_switch from switch_exit
+ - podulebus now recognised Lingenuity podules
+ - Lingenuity 16bit SCSI card recognised
+
+3/10/95
+ - new compile option ROTTEN_INARDS to dump full debugging info on
+ postmortem
+ - Rewritten postmortem debug information printout
+ - Postmortem will now examine the IRQ stack for traceback info
+ - Fix cpu_exit() bug thus could result in the idle being entered at
+ splhigh()
+ - Added function prototypes for functions called in vm_machdep.c
+ - boot0() now makes sure IRQ's and FIQ's have been disabled
+ - The ARM700 FPA is now correctly turned off during boot
+ - A major has been allocated for the vidcaudio device (36)
+ - vidcaudio.c added to mainbus/ and associated support added in
+ conf/ and conf.c
+ - Patch to the console code to report the version number
+ - Latest version of dev/isa/com.c merged into mainbus/com.c
+ - Latest version of dev/isa/lpt.c merged into mainbus/lpt.c
+ - Latest version of dev/isa/wd.c merged into mainbus/wd.c
+ - new assembly version of copystr added
+ - buffer address for beep0 removed from attach message
+ - unrecognised undefined instructions are now logged as errors to
+ syslog
+ - fpe now attaches a coproc2 handler to stap coproc2 FP instructions
+ and report an error
+ - New compile option FPE_INLINE added to fpe.c to inline some of the
+ conversion functions
+ - Added new compile option FPE_PROF to fpe.c to compile in FP profiling
+ code
+ -
+
+14/10/95
+ - added podule id for laser direct card
+ - added podule id for morley SCSI card
+ - added podule id for AXRE SCSI card
+ - added podule id for CC midi max card
+ - modified primary/secondary bootstraps to reserve special boot
+ - memory for hydra board
+ - added hydra device
+ - Added cpu identification for all hydra processors
+ - Private stacks are allocated to all slave processors
+ - All hydra processors are halted on reboot
+ - podule code checks for chunk directories but does not try to read
+ them yet.
+ - polling, immediate execution asc driver written for Acorn SCSI
+ card
+ - new special syscalls added to aid development of hydra software
+
+01/11/95
+ - kernel built with new netbsd-current source tree
+ - arm32 source updated to conform to latest netbsd-current source
+ tree
+
+03/11/95
+ - ALT-Cursor Left/Right now work the correct way round
+ - ALT-F6 now gernerates the correct code
+ - alpha version of the cumana SCSI II driver added
+ - alpha version of the ether1 driver added
+ - console code upgraded to V191
+ - driver directory structure changed.
+ - ./src/patch directory updated
+ - alpha version of ATAPI CDROM driver added
+ - mainbus and podulebus directories split in to public and private
+ directories.
+ - warnings from validate_trapframe() are prefixed with "VTF"
+ - old rpc console stuff removed from files.arm32 and source moved to
+ arch/arm32/old/
+ - the arch/arm32/pmap_stuff dir has been moved to arch/arm32/old/
+ - the _mcount.S and belgium.S files have been moved to old and
+ removed from files.arm32
+ - the device name to major code in autoconf.c now recognised /dev/cd
+ and /dev/wcd
+ - the mountroot code in stubs.c will call cd9660_mountroot() instead
+ of ffs_mountroot() is the root dev is a CDROM major.
+ - major 36 allocated to audio device
+ - major 37 allocated to vidcvideo device
+ - major 38 allocated to hydra device
+
+
+07/11/95
+ - cpu_fork() now maps in a page table for each process covering the
+ 0M-4M block of memory.
+ - VM_MIN_ADDRESS lowered to 0x1000
+ - cpu_swapout() unmaps the system page at 0x00000000 from its page
+ table
+ - cpu_swapin() wires down the pagetable covering 0x00000000 and
+ maps in the system page at 0x00000000
+ - cpu_swapin() and cpu_swapout() moved to vm_machdep.c
+ - pmap_enter_pv() no longer panics on duplicate mapping, it just
+ prints an warning.
+ - alpha version of the powertec SCSI driver
+
+15/11/95
+ - switch_exit now unmaps the system page.
+ - added newline to printf in disksubr.c
+ - the console code has been moved to the dev directory
+ - cumana SCSI II driver upgraded to support interrupts
+ - powertec SCSI II driver upgraded to support interrupts
+ - the mount root code in stubs.c will attempt to mount
+ a hd partition as cd9660 if the ffs_mountroot() fails.
+ - added missing copyright notices
+ - updated some declarations in header files
+ - removed DEBUG669 code from pmap.c
+ - new syncing routine written for boot()
+ - syncing no longer requires kshell support
+ - Added extra comments to the boot() function
+ - Implemented cpu_sysctl() function (just returns not supported
+ error)
+ - The nosync kernel interrupt now correctly uses RB_NOSYNC
+ -
+
+20/11/95
+ - restructure of directories contains device files
+ - fixed bug in pmap_pte() that could result in non-word
+ aligned pointers being returned in a off page boundry virtual
+ address was specified.
+ -
+
+24/11/95
+ - merged in new netbsd-current source tree
+ - removed all the validate_trapframe() calls
+ - the ioctl CONSOLE_BLANKTIME now reloads the blank timer
+ - the ioctl CONSOLE_BLANKTIME uses the default blank time if a
+ negative time is specified.
+ - the machine id is now passed in the bootconfig structure
+ - the eb0 driver will set the MAC address from the machine id
+ if the address has not already been set.
+
+26/11/95
+ - Fixed the definition of va_dcl in arm32/include/varargs.h
+ -
+
+02/12/95
+ - Fixed the WriteShort() macro
+ - Removed some redundant code from machdep.c
+ - cpu_sysctl is now declared to return an int
+ - stubs.c now has prototypes for the floppy driver functions it
+ calls when loading the ramdisc.
+ - further debugging work on the ether3 driver
+
+10/12/95
+ - Added uk device for unknown scsi devices to configuration files
+ and conf.c
+ - Alpha version of the ether3 ea device driver
+
+14/12/95
+ - Merged in beta version of the ether1 (ie) device driver
+ - added ifdefs to stubs.c so the cd9660_mountroot() is only called
+ when the kernel is compiled with CD9660
+ - created new text file to track all major and minor numbers
+
+16/12/95
+ - define __FORK_BRAINDAMAGE for compilation with the latest NetBSD
+ sources
+ - boot() now calls doshutdownhooks()
+ - merged in frank's new debugger code (process_machdep.c, ptrace.h,
+ regs.h)
+ - patches stub.c to take account of frank's new code
+ - patch cpu.h to give more detail on the PSR bits
+ - fixed the setting of p->p_mdregs to point to the trapframe in
+ the kernel mapping of kstack rather than the current mapping.
+ - removed some redundant code from mem.c
+ - commented out all the trace_debug code
+ - cpu_coredump moved from stubs.c to vm_machdep.c
+ - implemented ptrace.S in libc
+ - boot() no longer sets the curproc to proc0 if it was zero.
+ - spl's added to the console locking code
+ -
+
+19/12/95
+ - merged in new console code (V203) from Nut
+ - dosoftints() now calls pppintr()
+
+21/12/95
+ - sys_sysarch() no longer panics but returns EINVAL instead.
+ - added 3 new debugging syscalls for tracing the vnode bug
+ - identified what goes wrong with vnodes resulting in a lockup
+ - fixed a number of source file headers
+ - Added new comments to a number of routines.
+ - readdisklabel() now sets the B_AGE flag on its buffer
+ - ether3 drive now reports the controller chip type
+ - removed all stand and glue code from kshell
+ - added a new debugging syscall to all wakeup() to be called
+
+24/12/95
+ - removed redundant physconinit() call in initarm().
+ - updated comments in machdep.c
+ - added support for mulitple swap devices to be specified at boot
+ time
+ - changed debugging output in userret()
+ - added extra debugging
+ - added new debugging syscalls for tracubg the vnode bug
+ - added new debugging commands to the kshell
+ - added a new insw16() function for faster block transfers
+ - created a patch to fix p_nice
+ - the wd driver now supports multisector transfers
+ - added a new outsw16() function for faster block transfers but is
+ currently untested
+ - the existing arm32/fpe directory has been renamed to
+ arm32/fpe-sp
+ - started work on integrating the ARM FPE
+ - a new fpe directory arm32/fpe-arm has been created for the new FPE
+ - file arm32/cpu.S renamed to arm32/cpuswitch.S
+ - created new mainbus device 'cpu' (mainbus/cpu.c)
+ - created new header file include/cpus.h to hold macros and
+ structure definitions for cpus.
+ - all identify functions for the processor and FPA have been moved
+ to mainbus/cpu.c
+ - FPE is now attached during the cpu attachment during
+ autoconfiguration
+ - Identification of CPU and FPU split into separate functions in
+ mainbus/cpu.c
+ - Added new function initialise_fpe() to fpe-sp/fpe.c This is the
+ new initialisation point for the FPE. All vector claiming is done
+ in this routine. Routine is also responcible for IDing the FPE.
+ - ramdisc memory allocation now only ever done in the ramdisc driver
+ - cpu_model now declared in mainbus/cpu.c
+ - rpc_configure() renamed to configure()
+ - added function need_proftick() to clock.c
+ - further development work ARM FPE driver
+ - glue code for ARM FPE written and tested.
+ - ARM FPE now gets first chance as being installed with
+ the existing FPE installed as a fallback if the ARM FPE
+ installation failed.
+ - Hooks for the ARM FPE added in cpu_fork() cpu_exit() and
+ cpu_switch()
+ - Recoding of ether3 driver started.
+ - More debugging code added to trace vnode bug
+ - macro added to syscall.c to handle exit from the syscall handler
+ for special development syscalls.
+ - Vnode bug idenitfied as a corruption of the first word (v_flag)
+ of certain vnodes.
+ - Ether3 driver rewritten and debugged. Now a beta stage driver
+ - Vnode corruption traced to console code.
+ - Ether3 drive now has interface buffer memory tests
+ - vnode corruption traced to do_scrolldown() routine in the
+ console driver.
+ - vnode corruption bug located and fixed. Incorrect loop start and
+ end points when scrolling the character map down (writing beyond
+ allocated memory).
+ - Started work on rewriting the etherB driver
+ - cleaned up various header files
+ - removed stub.c as it was no longer needed
+ - updated strstr.c
+ - hydra code hooks now only compiled in if hydra device is
+ configured
+ - EtherB driver rewritten to match recoding of ether3 driver
+ - EtherB driver now a beta stage driver
+ - Work started on generic driver code for SEEQ EDLC's
+ - vidcvideo device now supports multiple openings
+ - EtherB driver now puts the controller to sleep when not active
+ - strstr() replaced with version borrowed from libc/string/strstr.c
+
+05/01/96
+ - Further development of ARM FPE
+ - generic fas216 code no longer experimental/NDA
+ - powertec scsi driver no longer experimental/NDA
+ - entry to undefined instruction handlers is now indirected in
+ exception.s
+ - entry to the undefined instruction handlers is made a trapframe
+ on the stack and r0-r12 preserved from exception.
+ - bounce code added so the existing undefined instuction handler
+ can be called with r0 pointing to the trapframe.
+ - new function arm_fpe_copycontext created
+ - fixed the use of FP instructions in sfas.c
+ - fixed errors in the softint code
+ - netns support can be be compiled in the kernel
+ - fixed warnings in fpe-sp/fpe.c and mainbus/cpu.c
+
+10/01/96
+ - exception.S updated pending new undefined instruction handling
+ code
+ - merged in new wd driver from NetBSD-current
+ - merged in new com driver from NetBSD-current
+ - merged in new fd driver from NetBSD-current
+ - created new file sys_machdep.c for machine dependant syscall stuff
+ - moved sys_sysctl from machdep.c to sys_machdep.c
+ - fixed nested comments in iic.S
+ - removed old bug tracing code from cpuswitch.S
+ - debugged new fd driver
+
+13/01/96
+ - undefined mode r13 added to the pcb structure
+ - new version of the ARM fpe built
+ - ARM FPE now has core deactivate routine accessable
+ - Call back from ARM FPE added on instruction completion
+ - cpu_switch() now switches UND32 mode r13
+ - cpu_fork() now sets up UND32 mode r13 in pcb
+ - undefined vector now calls stub routine that indirects
+ via address held in data area.
+ - data abort handler address now held in data area rather
+ than text area.
+ - prefetch abort handler address now held in data area rather
+ than text area.
+ - disabled warnings about soft errors from the fd driver
+
+17/01/96
+ - implemented pmap_resident_count()
+ - fixed the kernel avail_start and avail_end variable. This
+ fixes the divide by zero bug in /bin/ps
+ - ps now reports the correct resident size
+
+19/01/96
+ - kernel now supports permission faults in UND32 mode.
+ - kernel shell now has kshell> prompt instead of #
+ - ramdisc loading code has been moved from stubs.c to fd.c
+ - ramdisc loading code now uses a rd_conf structure to
+ describe the ramdisc.
+ - rd_hooks.c file added to the arm32/dev directory in
+ order to support the generic ramdisk.
+ - patch to generic ramdisc driver to allow a device match hook
+ - mainbus/ramdisc.c removed.
+ - generic ramdisc has now replaces to mainbus/ramdisc.
+ - fault.c reformatted
+ - new compile symbols introduced to comile in debug code for
+ fault correction.
+ - all remnants of the trace_debug code removed.
+ - armfpe code moved from arm32/fpe-arm/arm32 to arm32/fpe-arm/
+ - fu*() su*() functions moved from libkern into arm32/fusu.c
+ - added code to locore.S to traceback frames on the user process
+ stack
+ - added variable to enable / disable tracing back of user process
+ stacks
+ - added syscall to control user stack trackbacks.
+ - optimised ARM FPE exception delivery code
+ - implemented ARM FPE post processing callback glue
+ - ARM FPE post processor now calls user
+ - ARM FPE post processor optimised to recover some of the
+ performance lost by calling userret()
+ - integrated alpha version of the etherH driver
+ - updated ramdisc hooks to removed the need for a rd_match_hook()
+ function
+ - added Oak to the list of podule manufacturers
+ - kernel now reconised Oak SCSI I cards.
+ - Added generic NCR5380 SCSI driver code
+ - integrating in alpha version of the oak SCSI driver
+
+26/01/96
+ - merged in latest updates from the NetBSD-current source tree
+
+29/01/96
+ - code updated for merging into NetBSD source tree
+
+02/02/96
+ - assembly symbol file now names assym.h instead of assym.s
+ - The symbol LOCORE has been replaced with _LOCORE
+ - ramdisc loading code in now compiled in conditionally on
+ RAMDISK_HOOKS
+ - Further development of hydrabus device.
+ - cpus can noe be attached to both the mainbus and the hydrabus
+ - hooks for hydrabus device updated in pmap.c syscall.c and
+ machdep.c
+ - Extra comments added in exception.S
+ - sizeof(struct trapframe) now defined in assym.h
+ - register fixup for data transfer instruction aborts now handles
+ LDC/STC instructions i.e. hardware executed LDF/STF
+ - configuration files updated for latest devices
+ - fixed use of mkdepend in makefile
+ - fixed the bug that caused panics when issuing the mode change
+ ioctl to the vidcvideo device
+ - console code version number updated
+ - Updated armfpe_post_proc() to take a trapframe pointer as the
+ second argument
+ - updated the armfpe_post_proc_glue() code to fake a trapframe
+ structure from the FPE frame before calling the post proc handler
+ so that sendsig has a valid trapframe in p->p_md.md_regs
+ - updated the armfpe_post_proc_glue() code to patch the FPE frame
+ with data from the trapframe on return from the post proc handler.
+ - signal delivery is now working during FP instructions.
+ - mondef code resurrected and renamed to setdisplay and moved to the
+ stand directory.
--- /dev/null
+/* $NetBSD: majors+minors,v 1.3 1996/04/19 20:04:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * majors
+ *
+ * list of all allocated major numbers
+ *
+ * Created : 17/09/94
+ * Last updated : 30/12/95
+ *
+ * $Id: majors+minors,v 1.1.1.1 1996/04/24 11:08:39 deraadt Exp $
+ */
+
+List of allocated and reserved major and minor numbers
+
+The block and character major numbers are ALWAYS allocated together to the
+same device driver even if the driver does not require both.
+
+ 0 B - reserved
+ 0 C - memory device
+ minor = 0 - /dev/mem
+ minor = 1 - /dev/kmem
+ minor = 2 - /dev/null
+ minor = 3 - /dev/zero
+ 1 B - swap device
+ 1 C - psuedo swap device
+ minor = 0 - /dev/drum
+ 2 B - reserved
+ 2 C - console device
+ minor = 0 - /dev/console
+ 3 B - reserved
+ 3 C - controlling terminal
+ minor = 0 - /dev/tty
+ 4 B - reserved
+ 4 C - virtual console
+ /dev/ttyv{unit}
+ unit = minor
+ 5 B - reserved
+ 5 C - kernel log device
+ minor = 0 - /dev/klog
+ 6 B - reserved
+ 6 C - psuedo tty master
+ /dev/pty{class}{unit}
+ unit = minor % 16
+ minor / 16 = 0 - class = p
+ minor / 16 = 1 - class = q
+ minor / 16 = 2 - class = r
+ minor / 16 = 3 - class = s
+ minor / 16 = 4 - class = t
+ 7 B - reserved
+ 7 C - psuedo tty slave
+ /dev/tty{class}{unit}
+ unit = minor % 16
+ minor / 16 = 0 - class = p
+ minor / 16 = 1 - class = q
+ minor / 16 = 2 - class = r
+ minor / 16 = 3 - class = s
+ minor / 16 = 4 - class = t
+ 8 B - reserved
+ 8 C - parallel printer
+ /dev/lp{class}{unit}
+ unit = minor & 0x1f
+ minor & 0x80 = 0x00 - class = t - interrupt driver
+ minor & 0x80 = 0x80 - class = a - polling driver
+ e.g.
+ 0 - /dev/lpt0
+ 128 - /dev/lpa0
+ 9 B - reserved
+ 9 C - quadrature mouse
+ minor = 0 - /dev/quadmouse
+10 B - reserved
+10 C - beep device
+ minor = 0 - /dev/beep
+11 B - reserved
+11 C - keyboard device
+ minor = 0 - /dev/kbd
+12 B - reserved
+12 C - serial port
+ /dev/tty0{unit}
+ unit = minor
+13 B - reserver
+13 C - reserved
+14 B - reserved
+14 C - reserved
+15 B - reserved
+15 C - reserved
+16 B - ST506/ESDI/IDE disk
+ /dev/wd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+16 C - ST506/ESDI/IDE disk
+ /dev/rwd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+17 B - floppy disk
+ /dev/fd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+17 C - floppy disk
+ /dev/rfd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+18 B - ram disk
+ /dev/rd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+18 C - ram disk
+ /dev/rrd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+19 B - vnode disk driver
+ /dev/vnd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+19 C - vnode disk driver
+ /dev/rvnd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+20 B - reserved (ATAPI CDROM)
+ /dev/wcd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+20 C - reserved (ATAPI CDROM)
+ /dev/rwcd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+21 B - concatenated disk driver
+ /dev/ccd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+21 C - concatenated disk driver
+ /dev/rccd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+22 B - reserved
+22 C - reserved
+23 B - reserved
+23 C - reserved
+24 B - SCSI disk
+ /dev/sd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+24 C - SCSI disk
+ /dev/rsd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+25 B - SCSI tape
+25 C - SCSI tape
+26 B - SCSI cdrom
+ /dev/cd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+26 C - SCSI cdrom
+ /dev/rcd{unit}{partition}
+ partition = minor % 8
+ unit = minor / 8
+27 B - reserved
+27 C - SCSI autochanger
+ /dev/ch{unit}
+ unit = minor
+28 B - reserved
+28 C - SCSI unknown device
+ /dev/uk{unit}
+ unit = minor
+29 B - reserved
+29 C - SCSI scanner device
+ /dev/ss{unit}
+ unit = minor
+30 B - reserved
+30 C - reserved
+31 B - reserved
+31 C - reserved
+32 B - reserved
+32 C - Berkeley packet filter
+ /dev/bpf{unit}
+ unit = minor
+ minor = 0 - /dev/bpf0
+ minor = 1 - /dev/bpf1
+ minor = 2 - /dev/bpf2
+ minor = 3 - /dev/bpf3
+33 B - reserved
+33 C - network tunnel
+ /dev/tun{unit}
+ unit = minor
+ minor = 0 - /dev/tun0
+ minor = 1 - /dev/tun1
+ minor = 2 - /dev/tun2
+34 B - reserved
+34 C - file descriptor pseudo-device
+ minor = 0 - /dev/stdin
+ minor = 1 - /dev/stdout
+ minor = 2 - /dev/stderr
+35 B - reserved
+35 C - loadable module driver
+ minor = 0 - /dev/lkm
+36 B - reserved
+36 C - generic audio device
+37 B - reserved
+37 C - vidcvideo device
+ minor = 0 - /dev/vidcvideo
+38 B - reserved
+38 C - cpu/hydra
+ minor = 0 - /dev/cpu0
+39 B - reserved
+39 C - reserved
+40 B - reserved
+40 C - PS2 mouse
+ minor = 0 - /dev/pms
+41 B - reserved
+41 C - reserved
+42 B - reserved
+42 C - IIC device
+43 B - reserved
+43 C - RTC device
--- /dev/null
+Ok there are a number of things that need to be done that I do not
+have time to do and am unlikely to have time to do them in the near
+future.
+These are currently being left in the hope that users will do them
+instead.
+
+1. replace netinet/in_cksum.c with an assembly version
+2. replace netns/ns_chsum.c with an assembly version
+3. drivers for currently unsupported podules
+4. replacing the C string functions in libc with assembly ones (work
+ started but not finished)
+5. porting libpthread to arm32 architecture
+
--- /dev/null
+/*
+ * $NetBSD: armfpe.h,v 1.3 1996/03/18 19:54:53 mark Exp $
+ *
+ * Copyright (c) 1995 Neil A Carson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * armfpe.h
+ *
+ * Details of functions and structures needed for ARM FP cor
+ * support in RiscBSD
+ *
+ * Created : 04/01/96
+ */
+
+#ifndef __ARM32_ARM_FPE_H
+#define __ARM32_ARM_FPE_H
+
+/************************************ Types ***********************************/
+
+/*
+ * An extended precision floating point number
+ */
+
+typedef struct {
+ u_int32_t exponent;
+ u_int32_t mantissa_hi;
+ u_int32_t mantissa_lo;
+} fp_extended_precision_t;
+
+/*
+ * Type for a saved FP context, if we want to translate the context to a
+ * user-readable form
+ */
+
+typedef struct fp_context_frame {
+ u_int32_t fpsr;
+ fp_extended_precision_t regs[8];
+} fp_context_frame_t;
+
+/************************************* Module *********************************/
+
+typedef struct {
+ /*
+ * Addresses of procedures/functions
+ */
+
+ u_int32_t core_abort_addr;
+ u_int32_t core_initws_addr;
+ u_int32_t core_initcontext_addr;
+ u_int32_t core_changecontext_addr;
+ u_int32_t core_shutdown_addr;
+ u_int32_t core_activatecontext_addr;
+ u_int32_t core_deactivatecontext_addr;
+ u_int32_t core_savecontext_addr;
+ u_int32_t core_loadcontext_addr;
+ u_int32_t core_disable_addr;
+ u_int32_t core_enable_addr;
+
+ /*
+ * Addresses of things that need to be filled in by the kernel on startup
+ */
+
+ u_int32_t *main_ws_ptr_addr;
+ u_int32_t *local_handler_ptr_addr;
+ u_int32_t *old_handler_ptr_addr;
+ u_int32_t *exc_handler_ptr_addr;
+ u_int32_t *fp_post_proc_addr;
+
+ /*
+ * Numbers that the kernel needs - these are not pointers so do not need to
+ * be relocated!
+ */
+
+ u_int32_t WorkspaceLength;
+ u_int32_t ContextLength;
+} arm_fpe_mod_hdr_t;
+
+/**************************** Procedures in arm_fpe.c *************************/
+
+#ifdef _KERNEL
+
+/* macro to return the FP context for a process */
+
+#define FP_CONTEXT(p) ((u_int)(((u_char *)(p)->p_addr) + sizeof(struct user)))
+
+/* Prototypes */
+
+void arm_fpe_mod_reloc __P((void));
+int arm_fpe_boot __P((void));
+int initialise_arm_fpe __P((cpu_t *cpu));
+void arm_fpe_postproc __P((u_int fpframe, struct trapframe *frame));
+void arm_fpe_exception __P((int exception, u_int pc, u_int fpframe));
+
+void arm_fpe_core_disable __P((void));
+void arm_fpe_core_enable __P((void));
+u_int arm_fpe_core_initws __P((u_int workspace, int handler1, int handler2));
+u_int arm_fpe_core_abort __P((u_int context, int r12, int pc));
+void arm_fpe_core_initcontext __P((u_int context));
+u_int arm_fpe_core_changecontext __P((u_int context));
+void arm_fpe_core_shutdown __P((void));
+void arm_fpe_core_activatecontext __P((u_int context));
+u_int arm_fpe_core_deactivatecontext __P((void));
+u_int arm_fpe_core_savecontext __P((u_int context, int *savearea, int pc));
+void arm_fpe_core_loadcontext __P((u_int context, int *loadarea));
+void arm_fpe_copycontext __P((u_int c1, u_int c2));
+#endif
+
+#endif
--- /dev/null
+/* $NetBSD: armfpe.s,v 1.2 1996/03/18 19:54:55 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Neil A Carson.
+ * Copyright (c) 1996 Advanced Risc Machines Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * armfpe.s
+ *
+ * ARM FPE core
+ *
+ * Created : 05/01/96
+ */
+
+/* DO NOT MODIFY - THIS FILE IS AUTOMATICALLY GENERATED. */
+
+/* Generated from KernelFPE */
+
+.text
+.global _arm_fpe_mod
+_arm_fpe_mod:
+ .word 0x00006cc0
+ .word 0x00006e54
+ .word 0x00006ebc
+ .word 0x00006f5c
+ .word 0x0000706c
+ .word 0x00006fd8
+ .word 0x00006f64
+ .word 0x00007140
+ .word 0x0000722c
+ .word 0x0000707c
+ .word 0x000070d0
+ .word 0x000072e4
+ .word 0x000072fc
+ .word 0x00007314
+ .word 0x00007364
+ .word 0x000072e8
+ .word 0x0000000c
+ .word 0x00000088
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0xe24dd040
+ .word 0xe8cd7fff
+ .word 0xe58de03c
+ .word 0xe1a0c00d
+ .word 0xe10fa000
+ .word 0xe14f9000
+ .word 0xe92d0600
+ .word 0xe319000f
+ .word 0xe24e9004
+ .word 0x04b9b000
+ .word 0x1599b000
+ .word 0xe92d4000
+ .word 0xeb001c90
+ .word 0xe8bd0400
+ .word 0xe8bd4000
+ .word 0xe31b0302
+ .word 0x0a000849
+ .word 0xe20b9c0f
+ .word 0xe3590c01
+ .word 0x1a000015
+ .word 0xe59aa000
+ .word 0xee509110
+ .word 0xe2098c0f
+ .word 0xee307110
+ .word 0xe08ff328
+ .word 0x00000000
+ .word 0xea001ca9
+ .word 0xea001ca8
+ .word 0xea001ca7
+ .word 0xea001ca6
+ .word 0xea000103
+ .word 0xea0002b1
+ .word 0xea00002e
+ .word 0xea0002af
+ .word 0xea00018f
+ .word 0xea0002b8
+ .word 0xea00018d
+ .word 0xea0002b6
+ .word 0xea0000fb
+ .word 0xea0002ad
+ .word 0xea000026
+ .word 0xea0002ab
+ .word 0xe3590c02
+ .word 0x1a00082e
+ .word 0xe59aa000
+ .word 0xee509110
+ .word 0xe2098c0f
+ .word 0xee307110
+ .word 0xe08ff328
+ .word 0x00000000
+ .word 0xea001c91
+ .word 0xea001c90
+ .word 0xea001c8f
+ .word 0xea001c8e
+ .word 0xea0000e7
+ .word 0xea000299
+ .word 0xea000008
+ .word 0xea000297
+ .word 0xea00081b
+ .word 0xea0002a0
+ .word 0xea000819
+ .word 0xea00029e
+ .word 0xea0000df
+ .word 0xea000295
+ .word 0xea000000
+ .word 0xea000293
+ .word 0xe3190010
+ .word 0x13190601
+ .word 0x0a00000d
+ .word 0xe59c803c
+ .word 0xe2488004
+ .word 0xe58c803c
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe3190010
+ .word 0x13190601
+ .word 0x1a00011d
+ .word 0xe389b402
+ .word 0xe3170b01
+ .word 0x059c803c
+ .word 0x02488004
+ .word 0x058c803c
+ .word 0xe10f8000
+ .word 0xe3c88080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe31b0901
+ .word 0x0d2d020c
+ .word 0x1d2d420c
+ .word 0xe20b8a03
+ .word 0xe0888088
+ .word 0xe08d8528
+ .word 0xe8980007
+ .word 0xe28dd030
+ .word 0xe3c03103
+ .word 0xe2000103
+ .word 0xe20b8301
+ .word 0xe18335a8
+ .word 0xe3530903
+ .word 0x22433801
+ .word 0xe20b50e0
+ .word 0xe20b8702
+ .word 0xe18555a8
+ .word 0xe20b4201
+ .word 0xe31b0102
+ .word 0x02644000
+ .word 0xea00001e
+ .word 0x00003f81
+ .word 0x0000407e
+ .word 0x00003f81
+ .word 0x0000407e
+ .word 0x00003f81
+ .word 0x0000407e
+ .word 0x00003f81
+ .word 0x0000407e
+ .word 0x00003c01
+ .word 0x000043fe
+ .word 0x00003c01
+ .word 0x000043fe
+ .word 0x00003c01
+ .word 0x000043fe
+ .word 0x00003c01
+ .word 0x000043fe
+ .word 0x00000000
+ .word 0x00007ffe
+ .word 0x00000000
+ .word 0x00007ffe
+ .word 0x00000000
+ .word 0x00007ffe
+ .word 0x00000000
+ .word 0x00007ffe
+ .word 0xe3100101
+ .word 0x1a00000f
+ .word 0xe20b50e0
+ .word 0xe20b8702
+ .word 0xe18555a8
+ .word 0xe3a04000
+ .word 0xeb000bbe
+ .word 0xe24f8084
+ .word 0xe0888125
+ .word 0xe8980300
+ .word 0xe1530009
+ .word 0xd1580003
+ .word 0xca000015
+ .word 0xe1800003
+ .word 0xe3540000
+ .word 0x11b08aa7
+ .word 0x33877010
+ .word 0x8b000d35
+ .word 0xe92d0007
+ .word 0xe20b8a07
+ .word 0xe08f84a8
+ .word 0xe1a0e00f
+ .word 0xe288f044
+ .word 0xee207110
+ .word 0xe92d4000
+ .word 0xeb001c01
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe24fe05c
+ .word 0xe0588003
+ .word 0xca000c8f
+ .word 0xea000c18
+ .word 0xecbd8203
+ .word 0xe1a0f00e
+ .word 0xecbd9203
+ .word 0xe1a0f00e
+ .word 0xecbda203
+ .word 0xe1a0f00e
+ .word 0xecbdb203
+ .word 0xe1a0f00e
+ .word 0xecbdc203
+ .word 0xe1a0f00e
+ .word 0xecbdd203
+ .word 0xe1a0f00e
+ .word 0xecbde203
+ .word 0xe1a0f00e
+ .word 0xecbdf203
+ .word 0xe1a0f00e
+ .word 0xe20b3a0f
+ .word 0xe3530a0d
+ .word 0x2a000011
+ .word 0xe79c6523
+ .word 0xeb000f16
+ .word 0xe20b50e0
+ .word 0xe20b8702
+ .word 0xe18555a8
+ .word 0xe3a04000
+ .word 0xeb000b84
+ .word 0xe1800003
+ .word 0xe3540000
+ .word 0x11b08aa7
+ .word 0x33877010
+ .word 0x8b000d01
+ .word 0xe92d0007
+ .word 0xe20b8807
+ .word 0xe08f86a8
+ .word 0xe1a0e00f
+ .word 0xe248f08c
+ .word 0xeaffffca
+ .word 0xe3530a0f
+ .word 0x0a00000c
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x0affffe8
+ .word 0xe3888090
+ .word 0xe10f9000
+ .word 0xe3c9601f
+ .word 0xe1868008
+ .word 0xe129f008
+ .word 0xe3530a0d
+ .word 0x01a0600d
+ .word 0x11a0600e
+ .word 0xe129f009
+ .word 0xeaffffdf
+ .word 0xe59c603c
+ .word 0xe2866008
+ .word 0xeaffffdc
+ .word 0xe31b0702
+ .word 0x131b0080
+ .word 0x1a00076c
+ .word 0xe31b0010
+ .word 0x0a000042
+ .word 0xe20b860f
+ .word 0xe08ff928
+ .word 0x00000000
+ .word 0xeaffffcf
+ .word 0xea0000a0
+ .word 0xea000764
+ .word 0xea000763
+ .word 0xea000762
+ .word 0xea000761
+ .word 0xea000760
+ .word 0xea00075f
+ .word 0xea00075e
+ .word 0xea000081
+ .word 0xea00075c
+ .word 0xea00007f
+ .word 0xea00075a
+ .word 0xea00007d
+ .word 0xea000758
+ .word 0xea00007b
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00003fff
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004000
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004000
+ .word 0xc0000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004001
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004001
+ .word 0xa0000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00003ffe
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004002
+ .word 0xa0000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0xe3190010
+ .word 0x13190601
+ .word 0x0a000003
+ .word 0xeaffff21
+ .word 0xe3190010
+ .word 0x13190601
+ .word 0x1a00004a
+ .word 0xe389b402
+ .word 0xe3170b01
+ .word 0x059c803c
+ .word 0x02488004
+ .word 0x058c803c
+ .word 0xe10f8000
+ .word 0xe3c88080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe31b0902
+ .word 0x1a000020
+ .word 0xed2d420c
+ .word 0xed2d020c
+ .word 0xe20b8807
+ .word 0xe0888088
+ .word 0xe08d8728
+ .word 0xe8980007
+ .word 0xe1b09e8b
+ .word 0x208f8ca9
+ .word 0x224880ec
+ .word 0x308d8da9
+ .word 0x30888d29
+ .word 0xe8980038
+ .word 0xe28dd060
+ .word 0xe24fefb7
+ .word 0xe20b860f
+ .word 0xe08ff928
+ .word 0x00000000
+ .word 0xea0012b1
+ .word 0xea0012e9
+ .word 0xea0012af
+ .word 0xea0012ae
+ .word 0xea001327
+ .word 0xea001326
+ .word 0xea001616
+ .word 0xea001615
+ .word 0xea001120
+ .word 0xea0012e1
+ .word 0xea001321
+ .word 0xea001320
+ .word 0xea001912
+ .word 0xea000706
+ .word 0xea000705
+ .word 0xea000704
+ .word 0xe1b09e8b
+ .word 0x208f8ca9
+ .word 0x22488f56
+ .word 0x2a000004
+ .word 0x5d2d020c
+ .word 0x4d2d420c
+ .word 0xe3c99102
+ .word 0xe08d8da9
+ .word 0xe0888d29
+ .word 0xe8980007
+ .word 0x328dd030
+ .word 0xe24fefd6
+ .word 0xe20b860f
+ .word 0xe08ff928
+ .word 0x00000000
+ .word 0xea0013d3
+ .word 0xea0013d2
+ .word 0xea0013d1
+ .word 0xea0011f2
+ .word 0xea00112c
+ .word 0xea0014cf
+ .word 0xea0014ce
+ .word 0xea001582
+ .word 0xea001709
+ .word 0xea001708
+ .word 0xea001842
+ .word 0xea001799
+ .word 0xea001798
+ .word 0xea001916
+ .word 0xea0013f8
+ .word 0xea0013ea
+ .word 0xe02b8009
+ .word 0xe59f90f8
+ .word 0xe1180009
+ .word 0x1afffecf
+ .word 0xe10f8000
+ .word 0xe3c88080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe31b0502
+ .word 0x0a000016
+ .word 0xed2d420c
+ .word 0xed2d020c
+ .word 0xe20b8807
+ .word 0xe0888088
+ .word 0xe08d8728
+ .word 0xe8980007
+ .word 0xe1b09e8b
+ .word 0x208f8ca9
+ .word 0x22488f85
+ .word 0x308d8da9
+ .word 0x30888d29
+ .word 0xe8980038
+ .word 0xe28dd060
+ .word 0xeb0013fb
+ .word 0xe20b3a0f
+ .word 0xe3330a0f
+ .word 0x1a000012
+ .word 0xe51c8008
+ .word 0xe3c8820f
+ .word 0xe206620f
+ .word 0xe1888006
+ .word 0xe50c8008
+ .word 0xeaffff0d
+ .word 0xe1b09e8b
+ .word 0x208f8ca9
+ .word 0x22488f96
+ .word 0x2a000004
+ .word 0x5d2d020c
+ .word 0x4d2d420c
+ .word 0xe3c99102
+ .word 0xe08d8da9
+ .word 0xe0888d29
+ .word 0xe8980007
+ .word 0x328dd030
+ .word 0xeb00141e
+ .word 0xe20b3a0f
+ .word 0xe3530a0d
+ .word 0x2a000001
+ .word 0xe78c6523
+ .word 0xeafffefc
+ .word 0xe3330a0f
+ .word 0x0affffe6
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x0afffff8
+ .word 0xe3888090
+ .word 0xe10f9000
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe3530a0d
+ .word 0x01a0d006
+ .word 0x11a0e006
+ .word 0xe129f009
+ .word 0xeafffeed
+ .word 0x00ff00ff
+ .word 0xe10f8000
+ .word 0xe3c88080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe31b0402
+ .word 0x1affff2d
+ .word 0xe20b5501
+ .word 0xe1a05725
+ .word 0xe20b8902
+ .word 0xe1855428
+ .word 0xe3550d06
+ .word 0x0a00005f
+ .word 0xe31b0901
+ .word 0x0d2d020c
+ .word 0x1d2d420c
+ .word 0xe20b8a03
+ .word 0xe0888088
+ .word 0xe08d8528
+ .word 0xe8980007
+ .word 0xe28dd030
+ .word 0xeb00069b
+ .word 0xe20b380f
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x1a00001b
+ .word 0xe353080f
+ .word 0x2a00000d
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe3550080
+ .word 0xe4a40004
+ .word 0x24a41004
+ .word 0x84a42000
+ .word 0xeafffec3
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe3550080
+ .word 0xe4a40004
+ .word 0x24a41004
+ .word 0x84a42000
+ .word 0xeafffeb7
+ .word 0xe353080d
+ .word 0x2a00000d
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe3550080
+ .word 0x38840001
+ .word 0x08840003
+ .word 0x88840007
+ .word 0xeafffea7
+ .word 0xe353080f
+ .word 0x1a00000b
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe3550080
+ .word 0x38840001
+ .word 0x08840003
+ .word 0x88840007
+ .word 0xeafffe99
+ .word 0xe3888090
+ .word 0xe10f9000
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe129f009
+ .word 0xe3550080
+ .word 0x38840001
+ .word 0x08840003
+ .word 0x88840007
+ .word 0xeafffe80
+ .word 0xe31b0601
+ .word 0x1a00005e
+ .word 0xe31b0901
+ .word 0x0d2d020c
+ .word 0x1d2d420c
+ .word 0xe20b8a03
+ .word 0xe0888088
+ .word 0xe08d8528
+ .word 0xe8980007
+ .word 0xe28dd030
+ .word 0xeb000775
+ .word 0xe20b380f
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x1a00001d
+ .word 0xe353080f
+ .word 0x2a00000e
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe3170b02
+ .word 0xe4a40004
+ .word 0xe4a41004
+ .word 0xe4a42004
+ .word 0x14a46000
+ .word 0xeafffe60
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe3170b02
+ .word 0xe4a40004
+ .word 0xe4a41004
+ .word 0xe4a42004
+ .word 0x14a46000
+ .word 0xeafffe53
+ .word 0xe353080d
+ .word 0x2a00000c
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe3170b02
+ .word 0x08840007
+ .word 0x88840047
+ .word 0xeafffe44
+ .word 0xe353080f
+ .word 0x1a00000a
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe3170b02
+ .word 0x08840007
+ .word 0x88840047
+ .word 0xeafffe37
+ .word 0xe3888090
+ .word 0xe10f9000
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe129f009
+ .word 0xe3170b02
+ .word 0x08840007
+ .word 0x88840047
+ .word 0xeafffe1f
+ .word 0xe20b380f
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x1a00001f
+ .word 0xe353080f
+ .word 0x2a000015
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe3170b02
+ .word 0xe4b40004
+ .word 0xe4b41004
+ .word 0xe4b42004
+ .word 0x14b46000
+ .word 0xeb00085d
+ .word 0xe92d0007
+ .word 0xe20b8a07
+ .word 0xe08f84a8
+ .word 0xe288805c
+ .word 0xe1a0e00f
+ .word 0xe248fb02
+ .word 0xeafffe03
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeaffffea
+ .word 0xe353080d
+ .word 0x2a00000c
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe3170b02
+ .word 0x08940007
+ .word 0x88940047
+ .word 0xeaffffe0
+ .word 0xe353080f
+ .word 0x1a000007
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeafffff1
+ .word 0xe3888090
+ .word 0xe10f9000
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe129f009
+ .word 0xeaffffdc
+ .word 0xe59a9084
+ .word 0xe3190c02
+ .word 0x1afffd6c
+ .word 0xeafffe48
+ .word 0xee309110
+ .word 0xe58a9080
+ .word 0xed8a0200
+ .word 0xed8a420c
+ .word 0xe59a9084
+ .word 0xe3c99b02
+ .word 0xe58a9084
+ .word 0xe59c903c
+ .word 0xe2499004
+ .word 0xe58c903c
+ .word 0xea0019cf
+ .word 0xe24dd040
+ .word 0xe8cd7fff
+ .word 0xe58de03c
+ .word 0xe1a0c00d
+ .word 0xe10fa000
+ .word 0xe14f9000
+ .word 0xe92d0600
+ .word 0xe319000f
+ .word 0xe24e9004
+ .word 0x04b9b000
+ .word 0x1599b000
+ .word 0xe92d4000
+ .word 0xeb0019af
+ .word 0xe8bd0400
+ .word 0xe8bd4000
+ .word 0xe31b0302
+ .word 0x0a000568
+ .word 0xe20b9c0f
+ .word 0xe3590c01
+ .word 0x1a00048b
+ .word 0xe59aa000
+ .word 0xe59a8084
+ .word 0xe3380000
+ .word 0x1a000481
+ .word 0xe10f8000
+ .word 0xe3c88080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe59a7080
+ .word 0xe31b0402
+ .word 0x1a0003bf
+ .word 0xe1a0948b
+ .word 0xe209920a
+ .word 0xe31b0902
+ .word 0x13899101
+ .word 0xe20b380f
+ .word 0xe353080f
+ .word 0x23899201
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x13899302
+ .word 0xe2095103
+ .word 0xe08ffca9
+ .word 0x00000000
+ .word 0xea00001e
+ .word 0xea000039
+ .word 0xea000063
+ .word 0xea000070
+ .word 0xea0001ab
+ .word 0xea0001cc
+ .word 0xea000207
+ .word 0xea00020e
+ .word 0xea000079
+ .word 0xea000095
+ .word 0xea0000bf
+ .word 0xea0000cd
+ .word 0xea000212
+ .word 0xea000237
+ .word 0xea000275
+ .word 0xea00027c
+ .word 0xea0000d6
+ .word 0xea0000f3
+ .word 0xea00011d
+ .word 0xea00012c
+ .word 0xea000280
+ .word 0xea0002a3
+ .word 0xea0002de
+ .word 0xea0002e5
+ .word 0xea000135
+ .word 0xea000148
+ .word 0xea000175
+ .word 0xea000185
+ .word 0xea0002e9
+ .word 0xea0002fb
+ .word 0xea000323
+ .word 0xea00032a
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb000535
+ .word 0xe20b380f
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe4a40000
+ .word 0xe58a7080
+ .word 0xe92d4000
+ .word 0xeb001964
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb000519
+ .word 0xe20b380f
+ .word 0xe353080d
+ .word 0x2a00000a
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe8840001
+ .word 0xea00031b
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xe8840001
+ .word 0xea000303
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb0004ee
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe4a40000
+ .word 0xea0002f5
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb0004e0
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe8840001
+ .word 0xea0002e7
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb000527
+ .word 0xe20b380f
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe4a40004
+ .word 0xe4241004
+ .word 0xe58a7080
+ .word 0xe92d4000
+ .word 0xeb001900
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb00050a
+ .word 0xe20b380f
+ .word 0xe353080d
+ .word 0x2a00000a
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe8840003
+ .word 0xea0002b7
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xe8840003
+ .word 0xea00029f
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb0004df
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe4a40004
+ .word 0xe4241004
+ .word 0xea000290
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb0004d0
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe8840003
+ .word 0xea000282
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb00051d
+ .word 0xe20b380f
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe4a40004
+ .word 0xe4a41004
+ .word 0xe4242008
+ .word 0xe58a7080
+ .word 0xe92d4000
+ .word 0xeb00189a
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb0004ff
+ .word 0xe20b380f
+ .word 0xe353080d
+ .word 0x2a00000a
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe8840007
+ .word 0xea000251
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xe8840007
+ .word 0xea000239
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb0004d4
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe4a40004
+ .word 0xe4a41004
+ .word 0xe4242008
+ .word 0xea000229
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xe1a05ba5
+ .word 0xeb0004c4
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe8840007
+ .word 0xea00021b
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xeb00053f
+ .word 0xe20b380f
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe3170b02
+ .word 0xe4a40004
+ .word 0xe4a41004
+ .word 0xe4a42004
+ .word 0x14a46000
+ .word 0xea000207
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xeb00052b
+ .word 0xe20b380f
+ .word 0xe353080d
+ .word 0x2a00000c
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe3170b02
+ .word 0x08840007
+ .word 0x18840047
+ .word 0xea0001f3
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xe3170b02
+ .word 0x08840007
+ .word 0x18840047
+ .word 0xea0001d9
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xeb0004fd
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe3170b02
+ .word 0xe4a40004
+ .word 0xe4a41004
+ .word 0xe4a42004
+ .word 0x14a46000
+ .word 0xea0001c8
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8980007
+ .word 0xeb0004ec
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe3170b02
+ .word 0x08840007
+ .word 0x18840047
+ .word 0xea0001b9
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe4b40000
+ .word 0xe1b00080
+ .word 0xe1a01380
+ .word 0xe1a00ba0
+ .word 0x12800c7f
+ .word 0xe1a00060
+ .word 0x13811102
+ .word 0xe3a02000
+ .word 0xe1b08c80
+ .word 0x323884fe
+ .word 0x03800101
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8880007
+ .word 0xe92d4000
+ .word 0xeb0017cd
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe353080d
+ .word 0x2a000021
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe8940001
+ .word 0xe1b00080
+ .word 0xe1a01380
+ .word 0xe1a00ba0
+ .word 0x12800c7f
+ .word 0xe1a00060
+ .word 0x13811102
+ .word 0xe3a02000
+ .word 0xe1b08c80
+ .word 0x323884fe
+ .word 0x03800101
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8880007
+ .word 0xe92d4000
+ .word 0xeb0017a9
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xe8940001
+ .word 0xeaffffcf
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeaffffa2
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe8940001
+ .word 0xeaffffbe
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe4b40004
+ .word 0xe4342004
+ .word 0xe1b00080
+ .word 0x03320000
+ .word 0xe1a01500
+ .word 0xe1a00a20
+ .word 0xe1811aa2
+ .word 0xe1a02582
+ .word 0x12800b1e
+ .word 0xe1a00060
+ .word 0x13811102
+ .word 0xe1b08b00
+ .word 0x32288103
+ .word 0x323885ff
+ .word 0x03800101
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8880007
+ .word 0xe92d4000
+ .word 0xeb00175a
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe353080d
+ .word 0x2a000024
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe8940005
+ .word 0xe1b00080
+ .word 0x03320000
+ .word 0xe1a01500
+ .word 0xe1a00a20
+ .word 0xe1811aa2
+ .word 0xe1a02582
+ .word 0x12800b1e
+ .word 0xe1a00060
+ .word 0x13811102
+ .word 0xe1b08b00
+ .word 0x32288103
+ .word 0x323885ff
+ .word 0x03800101
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8880007
+ .word 0xe92d4000
+ .word 0xeb001733
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xe8940005
+ .word 0xeaffffcc
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeaffff9b
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe8940005
+ .word 0xeaffffbb
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe4b40004
+ .word 0xe4b41004
+ .word 0xe4342008
+ .word 0xe3c009fe
+ .word 0xe3c005ff
+ .word 0xe3110102
+ .word 0x11e08000
+ .word 0x11b08888
+ .word 0x03800101
+ .word 0x13c00101
+ .word 0xe1818002
+ .word 0xe1988880
+ .word 0x03c00101
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8880007
+ .word 0xe92d4000
+ .word 0xeb0016e6
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe353080d
+ .word 0x2a000021
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe8940007
+ .word 0xe3c009fe
+ .word 0xe3c005ff
+ .word 0xe3110102
+ .word 0x11e08000
+ .word 0x11b08888
+ .word 0x03800101
+ .word 0x13c00101
+ .word 0xe1818002
+ .word 0xe1988880
+ .word 0x03c00101
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8880007
+ .word 0xe92d4000
+ .word 0xeb0016c2
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xe8940007
+ .word 0xeaffffcf
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeaffffa0
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe8940007
+ .word 0xeaffffbe
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe3170b02
+ .word 0xe4b40004
+ .word 0xe4b41004
+ .word 0xe4b42004
+ .word 0x14b46000
+ .word 0xeb0004cf
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8880007
+ .word 0xea000050
+ .word 0xe353080d
+ .word 0x2a00000c
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe3170b02
+ .word 0x08940007
+ .word 0x18940047
+ .word 0xeaffffeb
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xe3170b02
+ .word 0x08940007
+ .word 0x18940047
+ .word 0xeaffffd1
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeaffffc4
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xe3170b02
+ .word 0x08940007
+ .word 0x18940047
+ .word 0xeaffffbe
+ .word 0xe3100101
+ .word 0x1a00000f
+ .word 0xe20b50e0
+ .word 0xe20b8702
+ .word 0xe18555a8
+ .word 0xe3a04000
+ .word 0xeb0005e4
+ .word 0xe28f8070
+ .word 0xe0888125
+ .word 0xe8980300
+ .word 0xe1530009
+ .word 0xd1580003
+ .word 0xca000013
+ .word 0xe1800003
+ .word 0xe3540000
+ .word 0x11b08aa7
+ .word 0x33877010
+ .word 0x8b00075b
+ .word 0xe20b8a07
+ .word 0xe08a8428
+ .word 0xe8880007
+ .word 0xe58a7080
+ .word 0xe92d4000
+ .word 0xeb001629
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe1a0d00c
+ .word 0xe8dc7fff
+ .word 0xe1a00000
+ .word 0xe28dd03c
+ .word 0xe8fd8000
+ .word 0xe24fe054
+ .word 0xe0588003
+ .word 0xca0006b7
+ .word 0xea000640
+ .word 0x00003f81
+ .word 0x0000407e
+ .word 0x00003f81
+ .word 0x0000407e
+ .word 0x00003f81
+ .word 0x0000407e
+ .word 0x00003f81
+ .word 0x0000407e
+ .word 0x00003c01
+ .word 0x000043fe
+ .word 0x00003c01
+ .word 0x000043fe
+ .word 0x00003c01
+ .word 0x000043fe
+ .word 0x00003c01
+ .word 0x000043fe
+ .word 0x00000000
+ .word 0x00007ffe
+ .word 0x00000000
+ .word 0x00007ffe
+ .word 0x00000000
+ .word 0x00007ffe
+ .word 0x00000000
+ .word 0x00007ffe
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00003fff
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004000
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004000
+ .word 0xc0000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004001
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004001
+ .word 0xa0000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00003ffe
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004002
+ .word 0xa0000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0xe31b0702
+ .word 0x131b0080
+ .word 0x1a000193
+ .word 0xe31b0010
+ .word 0x1a000036
+ .word 0xe31b0902
+ .word 0x1a00001b
+ .word 0xe20b8807
+ .word 0xe08a8628
+ .word 0xe8980007
+ .word 0xe1b09e8b
+ .word 0x208f8ca9
+ .word 0x224880b4
+ .word 0x308a8ca9
+ .word 0xe8980038
+ .word 0xe20b860f
+ .word 0xe24fef6f
+ .word 0xe08ff928
+ .word 0x00000000
+ .word 0xea00095b
+ .word 0xea0009bf
+ .word 0xea000959
+ .word 0xea000958
+ .word 0xea000a5c
+ .word 0xea000a5b
+ .word 0xea001085
+ .word 0xea001084
+ .word 0xea000b8f
+ .word 0xea0009b7
+ .word 0xea000a56
+ .word 0xea000a55
+ .word 0xea001381
+ .word 0xea000175
+ .word 0xea000174
+ .word 0xea000173
+ .word 0xe1b09e8b
+ .word 0x208f8ca9
+ .word 0x22488f46
+ .word 0x308a8ca9
+ .word 0xe8980007
+ .word 0xe20b860f
+ .word 0xe24fee22
+ .word 0xe08ff928
+ .word 0x00000000
+ .word 0xea000c2b
+ .word 0xea000c2a
+ .word 0xea000c29
+ .word 0xea000c67
+ .word 0xea000ba1
+ .word 0xea000f44
+ .word 0xea000f43
+ .word 0xea000ff7
+ .word 0xea00117e
+ .word 0xea00117d
+ .word 0xea0012b7
+ .word 0xea00120e
+ .word 0xea00120d
+ .word 0xea00138b
+ .word 0xea000c38
+ .word 0xea000c26
+ .word 0xe20b860f
+ .word 0xe08ff928
+ .word 0x00000000
+ .word 0xea000055
+ .word 0xea00000d
+ .word 0xea00003a
+ .word 0xea000024
+ .word 0xea000152
+ .word 0xea000151
+ .word 0xea000150
+ .word 0xea00014f
+ .word 0xea00014e
+ .word 0xea00000c
+ .word 0xea00014c
+ .word 0xea00000a
+ .word 0xea00014a
+ .word 0xea000008
+ .word 0xea000148
+ .word 0xea000006
+ .word 0xe1b09e8b
+ .word 0x208f8ca9
+ .word 0x22488f72
+ .word 0x308a8ca9
+ .word 0xe8980007
+ .word 0xe28fe04c
+ .word 0xea000cac
+ .word 0xe20b8807
+ .word 0xe08a8628
+ .word 0xe8980007
+ .word 0xe1b09e8b
+ .word 0x208f8ca9
+ .word 0x22488e1f
+ .word 0x308a8ca9
+ .word 0xe8980038
+ .word 0xeb000c8a
+ .word 0xe20b3a0f
+ .word 0xe3330a0f
+ .word 0x1a000007
+ .word 0xe51c8008
+ .word 0xe3c8820f
+ .word 0xe206620f
+ .word 0xe1888006
+ .word 0xe50c8008
+ .word 0xeaffff4f
+ .word 0xe1a06007
+ .word 0xe20b3a0f
+ .word 0xe3530a0d
+ .word 0x2a000001
+ .word 0xe78c6523
+ .word 0xeaffff49
+ .word 0xe3330a0f
+ .word 0x0afffff1
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x0afffff8
+ .word 0xe3888090
+ .word 0xe10f9000
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe3530a0d
+ .word 0x01a0d006
+ .word 0x11a0e006
+ .word 0xe129f009
+ .word 0xeaffff3a
+ .word 0xe20b3a0f
+ .word 0xe3530a0d
+ .word 0x2a000003
+ .word 0xe79c6523
+ .word 0xe3c664ff
+ .word 0xe3867401
+ .word 0xeaffff33
+ .word 0xe3530a0f
+ .word 0x0a00000c
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x0afffff6
+ .word 0xe3888090
+ .word 0xe10f9000
+ .word 0xe3c9601f
+ .word 0xe1868008
+ .word 0xe129f008
+ .word 0xe3530a0d
+ .word 0x01a0600d
+ .word 0x11a0600e
+ .word 0xe129f009
+ .word 0xeaffffed
+ .word 0xe59c603c
+ .word 0xe2866008
+ .word 0xeaffffea
+ .word 0xe20b3a0f
+ .word 0xe3530a0d
+ .word 0x2a00000f
+ .word 0xe79c6523
+ .word 0xeb000880
+ .word 0xe20b50e0
+ .word 0xe20b8702
+ .word 0xe18555a8
+ .word 0xe3a04000
+ .word 0xeb0004ee
+ .word 0xe1800003
+ .word 0xe3540000
+ .word 0x11b08aa7
+ .word 0x33877010
+ .word 0x8b00066b
+ .word 0xe20b8807
+ .word 0xe08a8628
+ .word 0xe8880007
+ .word 0xeaffff0e
+ .word 0xe3530a0f
+ .word 0x0a00000c
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x0affffea
+ .word 0xe3888090
+ .word 0xe10f9000
+ .word 0xe3c9601f
+ .word 0xe1868008
+ .word 0xe129f008
+ .word 0xe3530a0d
+ .word 0x01a0600d
+ .word 0x11a0600e
+ .word 0xe129f009
+ .word 0xeaffffe1
+ .word 0xe59c603c
+ .word 0xe2866008
+ .word 0xeaffffde
+ .word 0xe3a08000
+ .word 0xe58a8084
+ .word 0xe59c803c
+ .word 0xe2488004
+ .word 0xe58c803c
+ .word 0xea00152f
+ .word 0xe3590c02
+ .word 0x1a0000d7
+ .word 0xe59aa000
+ .word 0xe59a8084
+ .word 0xe3380000
+ .word 0x1afffff3
+ .word 0xe10f8000
+ .word 0xe3c88080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe31b0402
+ .word 0x1a0000c9
+ .word 0xe1a0958b
+ .word 0xe2099102
+ .word 0xe20b380f
+ .word 0xe353080f
+ .word 0x23899101
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0x13899202
+ .word 0xe1a0548b
+ .word 0xe2055102
+ .word 0xe31b0902
+ .word 0x13855101
+ .word 0xe08ffda9
+ .word 0x00000000
+ .word 0xea000006
+ .word 0xea00001a
+ .word 0xea000045
+ .word 0xea00004c
+ .word 0xea000053
+ .word 0xea000070
+ .word 0xea0000a4
+ .word 0xea0000ab
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe20b3a07
+ .word 0xe1a03883
+ .word 0xe28a9000
+ .word 0xe0898ca3
+ .word 0xe8980007
+ .word 0xe4a40004
+ .word 0xe4a41004
+ .word 0xe4a42004
+ .word 0xe2833202
+ .word 0xe2555101
+ .word 0x1afffff7
+ .word 0xeafffec0
+ .word 0xe353080d
+ .word 0x2a000012
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe20b3a07
+ .word 0xe1a03883
+ .word 0xe28a9000
+ .word 0xe0898ca3
+ .word 0xe8980007
+ .word 0xe8a40007
+ .word 0xe2833202
+ .word 0xe2555101
+ .word 0x1afffff9
+ .word 0xeafffeab
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xeaffffde
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeaffffbf
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeaffffce
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe20b3a07
+ .word 0xe1a03883
+ .word 0xe28a9000
+ .word 0xe4b40004
+ .word 0xe4b41004
+ .word 0xe4b42004
+ .word 0xe3c009fe
+ .word 0xe3c005ff
+ .word 0xe3110102
+ .word 0x11e08000
+ .word 0x11b08888
+ .word 0xe1818080
+ .word 0x03800101
+ .word 0xe1988002
+ .word 0x03c00101
+ .word 0xe0898ca3
+ .word 0xe8880007
+ .word 0xe2833202
+ .word 0xe2555101
+ .word 0x1affffee
+ .word 0xeafffe66
+ .word 0xe353080d
+ .word 0x2a00001b
+ .word 0xe79c4723
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x178c8723
+ .word 0xe20b3a07
+ .word 0xe1a03883
+ .word 0xe28a9000
+ .word 0xe8b40007
+ .word 0xe3c009fe
+ .word 0xe3c005ff
+ .word 0xe3110102
+ .word 0x11e08000
+ .word 0x11b08888
+ .word 0xe1818080
+ .word 0x03800101
+ .word 0xe1988002
+ .word 0x03c00101
+ .word 0xe0898ca3
+ .word 0xe8880007
+ .word 0xe2833202
+ .word 0xe2555101
+ .word 0x1afffff0
+ .word 0xeafffe48
+ .word 0xe51c8008
+ .word 0xe218800f
+ .word 0xe10f9000
+ .word 0xe3888090
+ .word 0xe3c9401f
+ .word 0xe1848008
+ .word 0xe129f008
+ .word 0xe353080d
+ .word 0x01a0400d
+ .word 0x11a0400e
+ .word 0xe20b80ff
+ .word 0xe31b0502
+ .word 0x10848108
+ .word 0x00448108
+ .word 0xe31b0401
+ .word 0x11a04008
+ .word 0xe31b0602
+ .word 0x0a000002
+ .word 0xe353080d
+ .word 0x01a0d008
+ .word 0x11a0e008
+ .word 0xe129f009
+ .word 0xeaffffd5
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeaffffad
+ .word 0xe59c403c
+ .word 0xe2844004
+ .word 0xe31b0401
+ .word 0x120b80ff
+ .word 0x10444108
+ .word 0x131b0502
+ .word 0x10844188
+ .word 0xeaffffc5
+ .word 0xe92d4000
+ .word 0xeb001444
+ .word 0xe8bd0400
+ .word 0xe8bd4000
+ .word 0xe91c0300
+ .word 0xe129f009
+ .word 0xe169f008
+ .word 0xe59ab004
+ .word 0xe59bb000
+ .word 0xe59ca03c
+ .word 0xe28c9040
+ .word 0xe9090e00
+ .word 0xe919ffff
+ .word 0xe3550080
+ .word 0x0a000093
+ .word 0x8a0000b1
+ .word 0xea000036
+ .word 0xe3a05000
+ .word 0xe3100101
+ .word 0x1a000035
+ .word 0xe3110102
+ .word 0x01a0f00e
+ .word 0xe3c03103
+ .word 0xe2000102
+ .word 0xe1924c01
+ .word 0x1a00000a
+ .word 0xe28f8fc9
+ .word 0xe8980300
+ .word 0xe1530009
+ .word 0xd1580003
+ .word 0xc92d4000
+ .word 0xca000023
+ .word 0xe1800421
+ .word 0xe3c00502
+ .word 0xe2438dfe
+ .word 0xe1800b88
+ .word 0xe1a0f00e
+ .word 0xe92d4000
+ .word 0xe3a04000
+ .word 0xe3a06000
+ .word 0xeb0003e2
+ .word 0xe28f8fba
+ .word 0xe8980300
+ .word 0xe1530009
+ .word 0xd1580003
+ .word 0xca000015
+ .word 0xe1800003
+ .word 0xe3540000
+ .word 0x11b08aa7
+ .word 0x33877010
+ .word 0x8b000540
+ .word 0xe8bd4000
+ .word 0xe1d18080
+ .word 0x5a000006
+ .word 0xe2300080
+ .word 0xe1a08081
+ .word 0xe1a084a8
+ .word 0xe1880b80
+ .word 0x53c00102
+ .word 0x43800102
+ .word 0xe1a0f00e
+ .word 0xe1b007c0
+ .word 0x33c10102
+ .word 0x23810102
+ .word 0xe1a00440
+ .word 0x53c00102
+ .word 0x43800102
+ .word 0xe1a0f00e
+ .word 0xe24fe05c
+ .word 0xe0588003
+ .word 0xca000502
+ .word 0xea000429
+ .word 0xe3100101
+ .word 0x0affffc9
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a00000e
+ .word 0xe1918002
+ .word 0x02000102
+ .word 0x01a0f00e
+ .word 0xe3c03103
+ .word 0xe3110102
+ .word 0x13530b0f
+ .word 0x1affffe6
+ .word 0xe2000102
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12833001
+ .word 0xe92d4000
+ .word 0xeb000731
+ .word 0xe8bd4000
+ .word 0xeaffffb9
+ .word 0xe1928081
+ .word 0x0affffdc
+ .word 0xe92d4000
+ .word 0xeb000559
+ .word 0xe3360000
+ .word 0x5b000595
+ .word 0xe8bd4000
+ .word 0xeaffffcd
+ .word 0xe3a05080
+ .word 0xe3100101
+ .word 0x1a00003b
+ .word 0xe3110102
+ .word 0x01a0f00e
+ .word 0xe3c03103
+ .word 0xe2000102
+ .word 0xe1b04a82
+ .word 0x1a00000c
+ .word 0xe28f8f76
+ .word 0xe8980300
+ .word 0xe1530009
+ .word 0xd1580003
+ .word 0xc92d4000
+ .word 0xca000029
+ .word 0xe18005a1
+ .word 0xe3c00601
+ .word 0xe2438b0f
+ .word 0xe1800a08
+ .word 0xe1a01a81
+ .word 0xe18115a2
+ .word 0xe1a0f00e
+ .word 0xe92d4000
+ .word 0xe3a04000
+ .word 0xe3a06000
+ .word 0xeb00039e
+ .word 0xe28f8f65
+ .word 0xe8980300
+ .word 0xe1530009
+ .word 0xd1580003
+ .word 0xca000019
+ .word 0xe1800003
+ .word 0xe3540000
+ .word 0x11b08aa7
+ .word 0x33877010
+ .word 0x8b0004eb
+ .word 0xe8bd4000
+ .word 0xe1d18080
+ .word 0x5a000008
+ .word 0xe2300b01
+ .word 0xe1a08081
+ .word 0xe1a08628
+ .word 0xe1880a00
+ .word 0x53c00102
+ .word 0x43800102
+ .word 0xe1a01a81
+ .word 0xe18115a2
+ .word 0xe1a0f00e
+ .word 0xe1b007c0
+ .word 0x33c10102
+ .word 0x23810102
+ .word 0xe1a005c0
+ .word 0x53c00102
+ .word 0x43800102
+ .word 0xe1a01a81
+ .word 0xe18115a2
+ .word 0xe1a0f00e
+ .word 0xe24fe06c
+ .word 0xe0588003
+ .word 0xca0004a7
+ .word 0xea0003ce
+ .word 0xe3100101
+ .word 0x0affffc3
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a00000e
+ .word 0xe1918002
+ .word 0x02000102
+ .word 0x01a0f00e
+ .word 0xe3c03103
+ .word 0xe3110102
+ .word 0x13530dfe
+ .word 0x1affffe4
+ .word 0xe2000102
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12833001
+ .word 0xe92d4000
+ .word 0xeb0006d6
+ .word 0xe8bd4000
+ .word 0xeaffffb3
+ .word 0xe1928081
+ .word 0x0affffda
+ .word 0xe92d4000
+ .word 0xeb0004fe
+ .word 0xe3360000
+ .word 0x5b00053a
+ .word 0xe8bd4000
+ .word 0xeaffffc9
+ .word 0xe3a05c01
+ .word 0xe3100101
+ .word 0x01a0f00e
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a00000b
+ .word 0xe1918002
+ .word 0x02000102
+ .word 0x01a0f00e
+ .word 0xe1a06880
+ .word 0xe2000102
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12866802
+ .word 0xe3360000
+ .word 0x1a00063d
+ .word 0xe2000102
+ .word 0xe1a0f00e
+ .word 0xe1928081
+ .word 0x0a000004
+ .word 0xe92d4000
+ .word 0xeb0004e2
+ .word 0xe3360000
+ .word 0x5b00051e
+ .word 0xe8bd4000
+ .word 0xe1110080
+ .word 0xe3c00101
+ .word 0x51a0f00e
+ .word 0xe1928081
+ .word 0x11a0f00e
+ .word 0xe38000ff
+ .word 0xe3800c7f
+ .word 0xe3c11102
+ .word 0xe1a0f00e
+ .word 0x00003f81
+ .word 0x0000407e
+ .word 0x00003c01
+ .word 0x000043fe
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a00000d
+ .word 0xe1916002
+ .word 0x02000102
+ .word 0x01a0f00e
+ .word 0xe3c03103
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12833001
+ .word 0xe92d4000
+ .word 0xeb000696
+ .word 0xe8bd4000
+ .word 0xe3c00101
+ .word 0xe3c04103
+ .word 0xe0444003
+ .word 0xea000053
+ .word 0xe1918002
+ .word 0x0a000003
+ .word 0xe3100101
+ .word 0x1a000001
+ .word 0xe3170801
+ .word 0x1a0005b6
+ .word 0xe1a085a2
+ .word 0xe1888a81
+ .word 0xe3c8820e
+ .word 0xe3c15103
+ .word 0xe1a05425
+ .word 0xe1a04982
+ .word 0xe3c44103
+ .word 0xe1855b08
+ .word 0xe1844528
+ .word 0xe2000102
+ .word 0xe38006ff
+ .word 0xe3800aff
+ .word 0xe1918002
+ .word 0x13800b02
+ .word 0xe3a06000
+ .word 0xe3a02000
+ .word 0xe3a01b02
+ .word 0xe1a09005
+ .word 0xe1a08125
+ .word 0xe1888f04
+ .word 0xe0555008
+ .word 0xe0c44124
+ .word 0xe1a08225
+ .word 0xe1888e04
+ .word 0xe0955008
+ .word 0xe0a44224
+ .word 0xe1a08425
+ .word 0xe1888c04
+ .word 0xe0955008
+ .word 0xe0a44424
+ .word 0xe1a08825
+ .word 0xe1888804
+ .word 0xe0955008
+ .word 0xe0a44824
+ .word 0xe0955004
+ .word 0xe2a44000
+ .word 0xe1a051a5
+ .word 0xe1855e84
+ .word 0xe1a041a4
+ .word 0xe0858105
+ .word 0xe0498088
+ .word 0xe358000a
+ .word 0x2248800a
+ .word 0xe2b55000
+ .word 0xe2a44000
+ .word 0xe1b06226
+ .word 0xe1866e02
+ .word 0xe1a02222
+ .word 0xe1822e01
+ .word 0xe1a01221
+ .word 0xe1811e08
+ .word 0x3affffdc
+ .word 0xe3170b02
+ .word 0x0a000008
+ .word 0xe1a06a26
+ .word 0xe1866602
+ .word 0xe1a02a22
+ .word 0xe1822601
+ .word 0xe1a01a21
+ .word 0xe1811a00
+ .word 0xe3800eff
+ .word 0xe380000f
+ .word 0xe1a0f00e
+ .word 0xe1800a21
+ .word 0xe1a01601
+ .word 0xe1811a22
+ .word 0xe1a02602
+ .word 0xe1822a26
+ .word 0xe1a0f00e
+ .word 0x00003ffe
+ .word 0x00013441
+ .word 0xe3100101
+ .word 0x1affff9d
+ .word 0xe3c03103
+ .word 0xe1916002
+ .word 0x02000102
+ .word 0x01a0f00e
+ .word 0xe3a04000
+ .word 0xe92d4000
+ .word 0xe24f8030
+ .word 0xe8980300
+ .word 0xe0536008
+ .word 0x82899001
+ .word 0xe0090996
+ .word 0xe1b06949
+ .word 0x51a08006
+ .word 0x0a000022
+ .word 0x42668000
+ .word 0xe24dd028
+ .word 0xe1a09407
+ .word 0xe3899003
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d901c
+ .word 0xed490206
+ .word 0xe8890007
+ .word 0xed998200
+ .word 0xe358001c
+ .word 0xaa0000a7
+ .word 0xe28f9fae
+ .word 0xe0899208
+ .word 0xedd91100
+ .word 0xe3360000
+ .word 0x5e480101
+ .word 0x4e180101
+ .word 0xee308110
+ .word 0xe2088010
+ .word 0xe28d901c
+ .word 0xed898200
+ .word 0xe8990007
+ .word 0xed590206
+ .word 0xe28dd028
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c03103
+ .word 0xe0433004
+ .word 0xe2000102
+ .word 0xe3170b02
+ .word 0x03a09011
+ .word 0x13a09015
+ .word 0xe2633002
+ .word 0xe2833901
+ .word 0xe263e020
+ .word 0xe1a04e12
+ .word 0xe1a02332
+ .word 0xe1822e11
+ .word 0xe1a01331
+ .word 0xe3a03000
+ .word 0xe311020f
+ .word 0x1a00000a
+ .word 0xe2466001
+ .word 0xe0944004
+ .word 0xe0b22002
+ .word 0xe0a11001
+ .word 0xe1a05f24
+ .word 0xe0944104
+ .word 0xe1a0ef22
+ .word 0xe1855102
+ .word 0xe0b22102
+ .word 0xe18ee101
+ .word 0xe0a1100e
+ .word 0xe1a03203
+ .word 0xe1833e21
+ .word 0xe3c1120f
+ .word 0xe2499001
+ .word 0xe3340000
+ .word 0x1affffef
+ .word 0xe3a05000
+ .word 0xe0922002
+ .word 0xe0a11001
+ .word 0xe1a0ef22
+ .word 0xe0922102
+ .word 0xe18ee101
+ .word 0xe0a1100e
+ .word 0xe1a04204
+ .word 0xe1844e25
+ .word 0xe1a05205
+ .word 0xe1855e23
+ .word 0xe1a03203
+ .word 0xe1833e21
+ .word 0xe3c1120f
+ .word 0xe2599001
+ .word 0x1afffff0
+ .word 0xe1889001
+ .word 0xe1899002
+ .word 0xe1921281
+ .word 0x3a000005
+ .word 0x02031001
+ .word 0x0a000003
+ .word 0xe2933001
+ .word 0xe203800f
+ .word 0xe338000a
+ .word 0x0a00003e
+ .word 0xe3360000
+ .word 0x43800101
+ .word 0x42666000
+ .word 0xe3a08000
+ .word 0xe3560efa
+ .word 0x22466efa
+ .word 0x23888901
+ .word 0xe3560e7d
+ .word 0x22466e7d
+ .word 0x23888a02
+ .word 0xe3560ffa
+ .word 0x22466ffa
+ .word 0x23888a01
+ .word 0xe3560e32
+ .word 0x22466e32
+ .word 0x23888b02
+ .word 0xe3560e19
+ .word 0x22466e19
+ .word 0x23888b01
+ .word 0xe35600c8
+ .word 0x224660c8
+ .word 0x23888c02
+ .word 0xe3560064
+ .word 0x22466064
+ .word 0x23888c01
+ .word 0xe3560050
+ .word 0x22466050
+ .word 0x23888080
+ .word 0xe3560028
+ .word 0x22466028
+ .word 0x23888040
+ .word 0xe3560014
+ .word 0x22466014
+ .word 0x23888020
+ .word 0xe356000a
+ .word 0x22866006
+ .word 0xe0888006
+ .word 0xe3170b02
+ .word 0x0a00000b
+ .word 0xe1800008
+ .word 0xe1a01604
+ .word 0xe1811a25
+ .word 0xe1a02605
+ .word 0xe1822a23
+ .word 0xe1a06603
+ .word 0xe3390000
+ .word 0x08bd8000
+ .word 0xe3170601
+ .word 0x03877010
+ .word 0x1b0003c6
+ .word 0xe8bd8000
+ .word 0xe1800608
+ .word 0xe1800404
+ .word 0xe1800c25
+ .word 0xe1a01405
+ .word 0xe1811c23
+ .word 0xe1a02403
+ .word 0xe3390000
+ .word 0x08bd8000
+ .word 0xe3170601
+ .word 0x03877010
+ .word 0x1b0003ad
+ .word 0xe8bd8000
+ .word 0xe3a01011
+ .word 0xe1811401
+ .word 0xe1811801
+ .word 0xe1812081
+ .word 0xe0828063
+ .word 0xe02880a3
+ .word 0xe0188181
+ .word 0xe08330a8
+ .word 0xe0833128
+ .word 0x5affffb6
+ .word 0xe2955001
+ .word 0xe0828065
+ .word 0xe02880a5
+ .word 0xe0188181
+ .word 0xe08550a8
+ .word 0xe0855128
+ .word 0x5affffaf
+ .word 0xe2944001
+ .word 0xe0828064
+ .word 0xe02880a4
+ .word 0xe0088181
+ .word 0xe08440a8
+ .word 0xe0844128
+ .word 0xe1b08627
+ .word 0x33140010
+ .word 0x23140601
+ .word 0x11a04224
+ .word 0x12866001
+ .word 0xeaffffa3
+ .word 0xe1a090a8
+ .word 0xeb000075
+ .word 0xe3360000
+ .word 0x5e480101
+ .word 0x4e180101
+ .word 0xe3180001
+ .word 0x1e19110f
+ .word 0xeaffff52
+ .word 0x00003fff
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004002
+ .word 0xa0000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004005
+ .word 0xc8000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004008
+ .word 0xfa000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x0000400c
+ .word 0x9c400000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x0000400f
+ .word 0xc3500000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004012
+ .word 0xf4240000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004016
+ .word 0x98968000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004019
+ .word 0xbebc2000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x0000401c
+ .word 0xee6b2800
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004020
+ .word 0x9502f900
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004023
+ .word 0xba43b740
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00004026
+ .word 0xe8d4a510
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x0000402a
+ .word 0x9184e72a
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x0000402d
+ .word 0xb5e620f4
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00004030
+ .word 0xe35fa931
+ .word 0xa0000000
+ .word 0x00000000
+ .word 0x00004034
+ .word 0x8e1bc9bf
+ .word 0x04000000
+ .word 0x00000000
+ .word 0x00004037
+ .word 0xb1a2bc2e
+ .word 0xc5000000
+ .word 0x00000000
+ .word 0x0000403a
+ .word 0xde0b6b3a
+ .word 0x76400000
+ .word 0x00000000
+ .word 0x0000403e
+ .word 0x8ac72304
+ .word 0x89e80000
+ .word 0x00000000
+ .word 0x00004041
+ .word 0xad78ebc5
+ .word 0xac620000
+ .word 0x00000000
+ .word 0x00004044
+ .word 0xd8d726b7
+ .word 0x177a8000
+ .word 0x00000000
+ .word 0x00004048
+ .word 0x87867832
+ .word 0x6eac9000
+ .word 0x00000000
+ .word 0x0000404b
+ .word 0xa968163f
+ .word 0x0a57b400
+ .word 0x00000000
+ .word 0x0000404e
+ .word 0xd3c21bce
+ .word 0xcceda100
+ .word 0x00000000
+ .word 0x00004052
+ .word 0x84595161
+ .word 0x401484a0
+ .word 0x00000000
+ .word 0x00004055
+ .word 0xa56fa5b9
+ .word 0x9019a5c8
+ .word 0x00000000
+ .word 0x00004058
+ .word 0xcecb8f27
+ .word 0xf4200f3a
+ .word 0x00000000
+ .word 0xe1a0000e
+ .word 0xe3a01000
+ .word 0xe1a02009
+ .word 0xe352001c
+ .word 0x21a020a2
+ .word 0x22811001
+ .word 0x2afffffb
+ .word 0xe24fef79
+ .word 0xe08e2202
+ .word 0xedd21100
+ .word 0xe3510001
+ .word 0x31a0f000
+ .word 0xee191101
+ .word 0xe1b02139
+ .word 0xe2411001
+ .word 0x2e19110f
+ .word 0xeafffff8
+ .word 0xe92d4000
+ .word 0xe1a08200
+ .word 0xe3170b02
+ .word 0x03a09004
+ .word 0x13a09007
+ .word 0xe3a05000
+ .word 0xeb000141
+ .word 0xe1b08627
+ .word 0x23a09008
+ .word 0x21b08001
+ .word 0x21a01002
+ .word 0x21a02006
+ .word 0x33a09003
+ .word 0x31b08a00
+ .word 0xe1a06085
+ .word 0x43866001
+ .word 0xe3a05000
+ .word 0xe3a04000
+ .word 0xe3a03000
+ .word 0xeb000134
+ .word 0xe1a08001
+ .word 0xe3a09008
+ .word 0xeb000131
+ .word 0xe1a08002
+ .word 0xe3a09008
+ .word 0xeb00012e
+ .word 0xe3170b02
+ .word 0x03a08c41
+ .word 0x13a088fe
+ .word 0xe15800a6
+ .word 0x9a000111
+ .word 0xe1a060a6
+ .word 0xe1838004
+ .word 0xe1988005
+ .word 0x02000102
+ .word 0x08bd8000
+ .word 0xe3100101
+ .word 0x12666000
+ .word 0xe3170b02
+ .word 0x02466012
+ .word 0x12466017
+ .word 0xe2000102
+ .word 0xe2800901
+ .word 0x0280003e
+ .word 0x03a08000
+ .word 0x1280004e
+ .word 0x11a08805
+ .word 0x11a05825
+ .word 0x11855804
+ .word 0x11a04824
+ .word 0x11844803
+ .word 0xe3340000
+ .word 0x4a000004
+ .word 0xe0988008
+ .word 0xe0b55005
+ .word 0xe0b44004
+ .word 0xe2400001
+ .word 0x5afffffa
+ .word 0xe3380102
+ .word 0x01f08f85
+ .word 0x4a000003
+ .word 0xe2955001
+ .word 0xe2b44000
+ .word 0x21a04064
+ .word 0x22800001
+ .word 0xe24dd034
+ .word 0xe1a09407
+ .word 0xe3899007
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d9028
+ .word 0xed498209
+ .word 0xe8890031
+ .word 0xed998200
+ .word 0xe3380000
+ .word 0x1e309110
+ .word 0x13899010
+ .word 0x1e209110
+ .word 0xe1b09006
+ .word 0x4a000009
+ .word 0x0a000011
+ .word 0xe3590a01
+ .word 0x8a000020
+ .word 0xe359001c
+ .word 0xb24f8fdd
+ .word 0xb0888209
+ .word 0xbdd81100
+ .word 0xabffff90
+ .word 0xee180101
+ .word 0xea000008
+ .word 0xe2699000
+ .word 0xe3590a01
+ .word 0x8a00006c
+ .word 0xe359001c
+ .word 0xb24f8fe7
+ .word 0xb0888209
+ .word 0xbdd81100
+ .word 0xabffff86
+ .word 0xee480101
+ .word 0xee308110
+ .word 0xe3180010
+ .word 0xe28d9028
+ .word 0xed898200
+ .word 0xe8990007
+ .word 0xed598209
+ .word 0xe28dd034
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0x08bd8000
+ .word 0xe3170601
+ .word 0x03877010
+ .word 0x13a04102
+ .word 0x1b000262
+ .word 0xe8bd8000
+ .word 0xe3590a02
+ .word 0x8a000028
+ .word 0xe1a06009
+ .word 0xe1a090a9
+ .word 0xebffff6f
+ .word 0xe28f9fa6
+ .word 0xed99a200
+ .word 0xee180102
+ .word 0xee180101
+ .word 0xe3160001
+ .word 0x1e19110f
+ .word 0xee181101
+ .word 0xe28f9fa2
+ .word 0xed998200
+ .word 0xee190100
+ .word 0xee309110
+ .word 0xe3190004
+ .word 0x0affffdc
+ .word 0xee190102
+ .word 0xee308110
+ .word 0xe3180010
+ .word 0xe28d9028
+ .word 0xed898200
+ .word 0xe8990007
+ .word 0xed598209
+ .word 0xe28dd034
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c03103
+ .word 0xe2833a06
+ .word 0xe2000102
+ .word 0x03a04000
+ .word 0x13a04102
+ .word 0xe3a05002
+ .word 0xeb000136
+ .word 0xe3340000
+ .word 0x08bd8000
+ .word 0xe3170601
+ .word 0x03877010
+ .word 0x1b000237
+ .word 0xe8bd8000
+ .word 0xe3590901
+ .word 0x2a000014
+ .word 0xe1a06009
+ .word 0xe1a09129
+ .word 0xebffff44
+ .word 0xe28f9f7b
+ .word 0xed99a200
+ .word 0xee180102
+ .word 0xee180101
+ .word 0xee180101
+ .word 0xee180102
+ .word 0xe3160002
+ .word 0x1e19110f
+ .word 0xee180101
+ .word 0xe3160001
+ .word 0x1e19110f
+ .word 0xee180101
+ .word 0xee309110
+ .word 0xe3190004
+ .word 0x0affffd3
+ .word 0xe28d9028
+ .word 0xed898200
+ .word 0xe8990007
+ .word 0xe28d9028
+ .word 0xed598209
+ .word 0xe28dd034
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe2000102
+ .word 0xe3a01102
+ .word 0xe3a02000
+ .word 0xe3a03401
+ .word 0xe3a04102
+ .word 0xe3a05002
+ .word 0xeb00010b
+ .word 0xe3340000
+ .word 0x08bd8000
+ .word 0xe3170601
+ .word 0x03877010
+ .word 0x1b00020c
+ .word 0xe8bd8000
+ .word 0xe3590a02
+ .word 0x8a000029
+ .word 0xe1a06009
+ .word 0xe1a090a9
+ .word 0xebffff19
+ .word 0xe28f9f53
+ .word 0xed99a200
+ .word 0xee180102
+ .word 0xee480101
+ .word 0xe3160001
+ .word 0x1e19110f
+ .word 0xee481101
+ .word 0xe28f9f49
+ .word 0xed998200
+ .word 0xee190100
+ .word 0xee309110
+ .word 0xe3190008
+ .word 0x0affff86
+ .word 0xee190102
+ .word 0xee308110
+ .word 0xe3180010
+ .word 0xe28d9028
+ .word 0xed898200
+ .word 0xe8990007
+ .word 0xed598209
+ .word 0xe28dd034
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c03103
+ .word 0xe2433a06
+ .word 0xe2000102
+ .word 0x03a04000
+ .word 0x13a04102
+ .word 0xe3a05002
+ .word 0xe2638000
+ .word 0xeb000155
+ .word 0xe3340000
+ .word 0x08bd8000
+ .word 0xe3170601
+ .word 0x03877010
+ .word 0x1b0001e0
+ .word 0xe8bd8000
+ .word 0xe3590901
+ .word 0x2a000014
+ .word 0xe1a06009
+ .word 0xe1a09129
+ .word 0xebfffeed
+ .word 0xe28f909c
+ .word 0xed99a200
+ .word 0xee180102
+ .word 0xee480101
+ .word 0xee480101
+ .word 0xee180102
+ .word 0xe3160002
+ .word 0x1e19110f
+ .word 0xee480101
+ .word 0xe3160001
+ .word 0x1e19110f
+ .word 0xee480101
+ .word 0xee309110
+ .word 0xe3190008
+ .word 0x0affffd2
+ .word 0xe28d9028
+ .word 0xed898200
+ .word 0xe8990007
+ .word 0xe28d9028
+ .word 0xed598209
+ .word 0xe28dd034
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe2000102
+ .word 0xe3a01102
+ .word 0xe3a02000
+ .word 0xe3a034ff
+ .word 0xe3a04102
+ .word 0xe3a05002
+ .word 0xeb00012a
+ .word 0xe3340000
+ .word 0x08bd8000
+ .word 0xe3170601
+ .word 0x03877010
+ .word 0x1b0001b5
+ .word 0xe8bd8000
+ .word 0x00000fff
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00006fff
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x6f05b59d
+ .word 0x3b200000
+ .word 0x16ef0a57
+ .word 0xb4000000
+ .word 0xe3160001
+ .word 0x0a000005
+ .word 0xe3170b02
+ .word 0x024f8024
+ .word 0x124f8020
+ .word 0xe8980006
+ .word 0xe0555002
+ .word 0xe0c44001
+ .word 0xe1a08b25
+ .word 0xe1888504
+ .word 0xe3c8820e
+ .word 0xe3c42103
+ .word 0xe1a029a2
+ .word 0xe1a01405
+ .word 0xe3c11103
+ .word 0xe1822588
+ .word 0xe1811aa8
+ .word 0xe2000102
+ .word 0xe3800101
+ .word 0xe3800c7f
+ .word 0xe38000ff
+ .word 0xe3160001
+ .word 0x13811101
+ .word 0xe1a0f00e
+ .word 0xe1a03183
+ .word 0xe1833ea4
+ .word 0xe1a04184
+ .word 0xe1844ea5
+ .word 0xe1a05185
+ .word 0xe0955125
+ .word 0x20855f04
+ .word 0x30955f04
+ .word 0xe0b44124
+ .word 0x20844f03
+ .word 0x30944f03
+ .word 0xe0a33123
+ .word 0xe0955e28
+ .word 0xe2b44000
+ .word 0xe2a33000
+ .word 0xe1a08208
+ .word 0xe2599001
+ .word 0x1affffed
+ .word 0xe1a0f00e
+ .word 0xe1b08425
+ .word 0x2a000024
+ .word 0x0a000010
+ .word 0xe1b08086
+ .word 0xe18082e5
+ .word 0x23888101
+ .word 0x13888202
+ .word 0xe3340000
+ .word 0x01b06f82
+ .word 0x43888201
+ .word 0xe28f6038
+ .word 0xe7d66e68
+ .word 0xe1b080a6
+ .word 0x22922001
+ .word 0x22911001
+ .word 0x23a01102
+ .word 0x22833001
+ .word 0xe3160002
+ .word 0x11a04c06
+ .word 0xe1a0f00e
+ .word 0xe1868002
+ .word 0xe1988c81
+ .word 0xe18082e5
+ .word 0x23888101
+ .word 0x13888202
+ .word 0xe3340000
+ .word 0x01b06b81
+ .word 0x43888201
+ .word 0xe3a02000
+ .word 0xe3c110ff
+ .word 0xe28f6068
+ .word 0xe7d66e68
+ .word 0xe1b080a6
+ .word 0x22911c01
+ .word 0x23a01102
+ .word 0x22833001
+ .word 0xe3160002
+ .word 0x11a04c06
+ .word 0xe1a0f00e
+ .word 0xe1968b02
+ .word 0xe18082e5
+ .word 0x23888101
+ .word 0x13888202
+ .word 0xe3340000
+ .word 0x01b06a02
+ .word 0x43888201
+ .word 0xe3c220ff
+ .word 0xe3c22c07
+ .word 0xe24f6020
+ .word 0xe7d66e68
+ .word 0xe1b080a6
+ .word 0x22922b02
+ .word 0x22911001
+ .word 0x23a01102
+ .word 0x22833001
+ .word 0xe3160002
+ .word 0x11a04c06
+ .word 0xe1a0f00e
+ .word 0xfefe0000
+ .word 0x030303fe
+ .word 0xfefe0000
+ .word 0x030303fe
+ .word 0x03030000
+ .word 0x03030303
+ .word 0xfefe0000
+ .word 0xfefefefe
+ .word 0xfefe0000
+ .word 0xfefefefe
+ .word 0x03030000
+ .word 0x03030303
+ .word 0xfefe0000
+ .word 0xfefefefe
+ .word 0xfefe0000
+ .word 0xfefefefe
+ .word 0x40007fff
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x0000407e
+ .word 0xffffff00
+ .word 0x00000000
+ .word 0x000043fe
+ .word 0xffffffff
+ .word 0xfffff800
+ .word 0x00007ffe
+ .word 0xffffffff
+ .word 0xffffffff
+ .word 0xc0007fff
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x8000407e
+ .word 0xffffff00
+ .word 0x00000000
+ .word 0x800043fe
+ .word 0xffffffff
+ .word 0xfffff800
+ .word 0x80007ffe
+ .word 0xffffffff
+ .word 0xffffffff
+ .word 0x00000030
+ .word 0x00000000
+ .word 0x0000003c
+ .word 0x00000000
+ .word 0x00000030
+ .word 0x0000000c
+ .word 0x0000003c
+ .word 0x0000000c
+ .word 0x00000030
+ .word 0x00000000
+ .word 0x00000048
+ .word 0x00000000
+ .word 0x00000030
+ .word 0x00000018
+ .word 0x00000048
+ .word 0x00000018
+ .word 0x00000030
+ .word 0x00000000
+ .word 0x00000054
+ .word 0x00000000
+ .word 0x00000030
+ .word 0x00000024
+ .word 0x00000054
+ .word 0x00000024
+ .word 0xe3170701
+ .word 0x1a00000c
+ .word 0xe3877004
+ .word 0xe24f1074
+ .word 0xe0811125
+ .word 0xe8910006
+ .word 0xe3100102
+ .word 0xe24f00e4
+ .word 0x10800001
+ .word 0x00800002
+ .word 0xe8900007
+ .word 0xe3100101
+ .word 0x13a04001
+ .word 0x03e04000
+ .word 0xe1a0f00e
+ .word 0xe92d4c28
+ .word 0xe3540102
+ .word 0x13540000
+ .word 0xc3a04001
+ .word 0xb3e04000
+ .word 0xee207110
+ .word 0xe24dd004
+ .word 0xe28f8e17
+ .word 0xe20b9010
+ .word 0xe7989129
+ .word 0xe31b0902
+ .word 0x11a09829
+ .word 0xe20b860f
+ .word 0xe1a08a28
+ .word 0xe1a09839
+ .word 0xe0099fa7
+ .word 0xe1c99527
+ .word 0xe0099cab
+ .word 0xe3150c01
+ .word 0x1a00002b
+ .word 0xe3150080
+ .word 0x1a000014
+ .word 0xe24330c0
+ .word 0xe59f8124
+ .word 0xe1530008
+ .word 0xd1800003
+ .word 0xc28f0f43
+ .word 0xc8900007
+ .word 0xe92d0007
+ .word 0xe1a03009
+ .word 0xeb000fc2
+ .word 0xe24dd010
+ .word 0xe1a08407
+ .word 0xe3888001
+ .word 0xe58d8000
+ .word 0xe10f8000
+ .word 0xe3888080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe28d8010
+ .word 0xed088203
+ .word 0xed980100
+ .word 0xea000028
+ .word 0xe2433c06
+ .word 0xe59f80d4
+ .word 0xe1530008
+ .word 0xd1800003
+ .word 0xc28f00b8
+ .word 0xc8900007
+ .word 0xe92d0007
+ .word 0xe1a03009
+ .word 0xeb000fad
+ .word 0xe24dd010
+ .word 0xe1a08407
+ .word 0xe3888001
+ .word 0xe58d8000
+ .word 0xe10f8000
+ .word 0xe3888080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe28d8010
+ .word 0xed088203
+ .word 0xed988100
+ .word 0xea000013
+ .word 0xe2433a06
+ .word 0xe59f8084
+ .word 0xe1530008
+ .word 0xd1800003
+ .word 0xc28f0064
+ .word 0xc8900007
+ .word 0xe92d0007
+ .word 0xe1a03009
+ .word 0xeb000f98
+ .word 0xe24dd010
+ .word 0xe1a08407
+ .word 0xe3888001
+ .word 0xe58d8000
+ .word 0xe10f8000
+ .word 0xe3888080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe28d8010
+ .word 0xed088203
+ .word 0xedd80100
+ .word 0xee307110
+ .word 0xe28d8010
+ .word 0xed888200
+ .word 0xe8980007
+ .word 0xed188203
+ .word 0xe28dd020
+ .word 0xe10f8000
+ .word 0xe3c88080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe8bd8c28
+ .word 0x40007fff
+ .word 0x40000200
+ .word 0x00000000
+ .word 0x0000407e
+ .word 0x000043fe
+ .word 0x00007ffe
+ .word 0xc0070e3f
+ .word 0x00010001
+ .word 0xe92d4000
+ .word 0xe3170702
+ .word 0x1a000025
+ .word 0xe0833008
+ .word 0xe1a092a8
+ .word 0xe1c88289
+ .word 0xe3590002
+ .word 0x33390000
+ .word 0xe2689020
+ .word 0xe1a06912
+ .word 0xe1a02832
+ .word 0xe1822911
+ .word 0xe1a01831
+ .word 0x0a000003
+ .word 0x11866106
+ .word 0x11826126
+ .word 0x11a02001
+ .word 0x13a01000
+ .word 0x3a000004
+ .word 0x21866002
+ .word 0x21866106
+ .word 0x21816126
+ .word 0x23a02000
+ .word 0x23a01000
+ .word 0xebfffef6
+ .word 0xe3170c01
+ .word 0x13310102
+ .word 0x11918002
+ .word 0x13a01000
+ .word 0x13a02000
+ .word 0x13e04000
+ .word 0x03360000
+ .word 0x13877008
+ .word 0xe1916002
+ .word 0x08bd8000
+ .word 0xe3330000
+ .word 0x1b000280
+ .word 0x03110102
+ .word 0x03800101
+ .word 0xe1800003
+ .word 0xe8bd8000
+ .word 0xe92d4c28
+ .word 0xe3540102
+ .word 0x13540000
+ .word 0xc3a04001
+ .word 0xb3e04000
+ .word 0xee207110
+ .word 0xe24dd004
+ .word 0xe24f80d0
+ .word 0xe20b9010
+ .word 0xe7989129
+ .word 0xe31b0902
+ .word 0x11a09829
+ .word 0xe20b860f
+ .word 0xe1a08a28
+ .word 0xe1a09839
+ .word 0xe0099fa7
+ .word 0xe1c99527
+ .word 0xe0099cab
+ .word 0xe3150c01
+ .word 0x1a000015
+ .word 0xe3150080
+ .word 0x1a000009
+ .word 0xe28330c0
+ .word 0xe59f8078
+ .word 0xe1530008
+ .word 0xa1800003
+ .word 0xb28f0060
+ .word 0xb8900007
+ .word 0xe92d0007
+ .word 0xe1a03009
+ .word 0xeb000f34
+ .word 0xeaffff6e
+ .word 0xe2833c06
+ .word 0xe59f8054
+ .word 0xe1530008
+ .word 0xa1800003
+ .word 0xb28f0038
+ .word 0xb8900007
+ .word 0xe92d0007
+ .word 0xe1a03009
+ .word 0xeb000f2a
+ .word 0xeaffff79
+ .word 0xe2833a06
+ .word 0xe3a08000
+ .word 0xe1530008
+ .word 0xa1800003
+ .word 0xb28f0010
+ .word 0xb8900007
+ .word 0xe92d0007
+ .word 0xe1a03009
+ .word 0xeb000f20
+ .word 0xeaffff84
+ .word 0x40007fff
+ .word 0x40000300
+ .word 0x00000000
+ .word 0x00003f81
+ .word 0x00003c01
+ .word 0xe92d4000
+ .word 0xe3170702
+ .word 0x1affffc3
+ .word 0xe0833008
+ .word 0xe1a092a8
+ .word 0xe1c88289
+ .word 0xe3590002
+ .word 0x33390000
+ .word 0xe2689020
+ .word 0xe1a06912
+ .word 0xe1a02832
+ .word 0xe1822911
+ .word 0xe1a01831
+ .word 0x0a000003
+ .word 0x11866106
+ .word 0x11826126
+ .word 0x11a02001
+ .word 0x13a01000
+ .word 0x3a000004
+ .word 0x21866002
+ .word 0x21866106
+ .word 0x21816126
+ .word 0x23a02000
+ .word 0x23a01000
+ .word 0xebfffe94
+ .word 0xe3170c01
+ .word 0x13310102
+ .word 0x11918002
+ .word 0x13a01000
+ .word 0x13a02000
+ .word 0x13e04000
+ .word 0x03360000
+ .word 0x13877008
+ .word 0xe1916002
+ .word 0x08bd8000
+ .word 0xe3310102
+ .word 0x13800101
+ .word 0x13330000
+ .word 0x12433001
+ .word 0x13811102
+ .word 0xe1800003
+ .word 0xe8bd8000
+ .word 0xe3a08000
+ .word 0xea000004
+ .word 0xe3a08001
+ .word 0xea000002
+ .word 0xe3a08002
+ .word 0xea000000
+ .word 0xe1a083a5
+ .word 0xe92d4c28
+ .word 0xe3540102
+ .word 0x13540000
+ .word 0xc3a04001
+ .word 0xb3e04000
+ .word 0xee207110
+ .word 0xe24dd004
+ .word 0xe92d0007
+ .word 0xe24f8f9f
+ .word 0xe20b3010
+ .word 0xe7983123
+ .word 0xe31b0902
+ .word 0x11a03823
+ .word 0xe20b860f
+ .word 0xe1a08a28
+ .word 0xe1a03833
+ .word 0xe0033fa7
+ .word 0xe1c33527
+ .word 0xe0033cab
+ .word 0xe3580001
+ .word 0x8a000004
+ .word 0x0a000001
+ .word 0xeb000ed4
+ .word 0xeaffff0c
+ .word 0xeb000ed2
+ .word 0xeaffff1f
+ .word 0xeb000ed0
+ .word 0xeaffff32
+ .word 0xe92d4c28
+ .word 0xe3540102
+ .word 0x13540000
+ .word 0xc3a04001
+ .word 0xb3e04000
+ .word 0xee207110
+ .word 0xe24dd010
+ .word 0xe3a03000
+ .word 0xeb000ec6
+ .word 0xee307110
+ .word 0xe49d6010
+ .word 0xe8bd8c28
+ .word 0xe92d4c28
+ .word 0xe3540102
+ .word 0x13540000
+ .word 0xc3a04001
+ .word 0xb3e04000
+ .word 0xee207110
+ .word 0xe24dd010
+ .word 0xe3a03000
+ .word 0xeb000eba
+ .word 0xee307110
+ .word 0xe89d0007
+ .word 0xe28dd010
+ .word 0xe8bd8c28
+ .word 0xe92d4c28
+ .word 0xe3540102
+ .word 0x13540000
+ .word 0xc3a04001
+ .word 0xb3e04000
+ .word 0xee207110
+ .word 0xe24dd010
+ .word 0xe3a03000
+ .word 0xeb000ead
+ .word 0xee307110
+ .word 0xe8bd0047
+ .word 0xe8bd8c28
+ .word 0xe3c08103
+ .word 0xe3a090ff
+ .word 0xe3899c43
+ .word 0xe1580009
+ .word 0x81a0648b
+ .word 0x91e0648b
+ .word 0x0006680b
+ .word 0x11c6680b
+ .word 0xe3360000
+ .word 0x52176c02
+ .word 0x11a0f00e
+ .word 0xe1b06b08
+ .word 0x31a06fa6
+ .word 0x22026001
+ .word 0xe31b0902
+ .word 0x12266001
+ .word 0xe31b0501
+ .word 0x13a06000
+ .word 0xe1a0f00e
+ .word 0xe3c08103
+ .word 0xe3a090ff
+ .word 0xe3899c43
+ .word 0xe1580009
+ .word 0x81a0660b
+ .word 0x91e0660b
+ .word 0x00066c0b
+ .word 0x11c66c0b
+ .word 0xe3360000
+ .word 0x52176c02
+ .word 0x11a0f00e
+ .word 0xe1b06b08
+ .word 0x31a06fa6
+ .word 0x22026001
+ .word 0xe31b0080
+ .word 0x12266001
+ .word 0xe31b0702
+ .word 0x13a06000
+ .word 0xe1a0f00e
+ .word 0xe1928081
+ .word 0x0a000005
+ .word 0xe3110101
+ .word 0x0a000019
+ .word 0xe1958084
+ .word 0x0a000017
+ .word 0xe3140101
+ .word 0x1a000015
+ .word 0xe2148101
+ .word 0x1a000003
+ .word 0xe3170801
+ .word 0x1a00009b
+ .word 0xe3877001
+ .word 0xe3844101
+ .word 0xe1a00003
+ .word 0xe1a01004
+ .word 0xe1a02005
+ .word 0xea000011
+ .word 0x0a000010
+ .word 0xe2118101
+ .word 0x1a00000e
+ .word 0xe3170801
+ .word 0x1a000053
+ .word 0xea000009
+ .word 0x0a00000a
+ .word 0xe2118101
+ .word 0x1a000008
+ .word 0xe3170801
+ .word 0x1a00002d
+ .word 0xea000003
+ .word 0xe2118101
+ .word 0x1a000003
+ .word 0xe3170801
+ .word 0x1a000085
+ .word 0xe3877001
+ .word 0xe3811101
+ .word 0xe31b0702
+ .word 0x1a000010
+ .word 0xe31b0080
+ .word 0x1a000006
+ .word 0xe2000103
+ .word 0xe380007f
+ .word 0xe3800901
+ .word 0xe3a02000
+ .word 0xe3c110ff
+ .word 0xe3811102
+ .word 0xe1a0f00e
+ .word 0xe2000103
+ .word 0xe38000ff
+ .word 0xe3800c43
+ .word 0xe1a025a2
+ .word 0xe1a02582
+ .word 0xe3811102
+ .word 0xe1300000
+ .word 0xe1a0f00e
+ .word 0xe31b0c02
+ .word 0x1a000005
+ .word 0xe3c08103
+ .word 0xe3a090ff
+ .word 0xe3899c43
+ .word 0xe1580009
+ .word 0x33c22001
+ .word 0x03822001
+ .word 0xe2000103
+ .word 0xe38000ff
+ .word 0xe3800c7f
+ .word 0xe1300000
+ .word 0xe1a0f00e
+ .word 0xe3170801
+ .word 0x1a000004
+ .word 0xe3877001
+ .word 0xe28f0d0a
+ .word 0xe8900007
+ .word 0xe1811408
+ .word 0xe1a0f00e
+ .word 0xe92d4c30
+ .word 0xee207110
+ .word 0xe24dd00c
+ .word 0xe92d0007
+ .word 0xe28f8f9b
+ .word 0xe20b3010
+ .word 0xe7983123
+ .word 0xe31b0902
+ .word 0x11a03823
+ .word 0xe20b860f
+ .word 0xe1a08a28
+ .word 0xe1a03833
+ .word 0xe0033fa7
+ .word 0xe1c33527
+ .word 0xe0033cab
+ .word 0xe31b0702
+ .word 0x1a00002e
+ .word 0xe31b0080
+ .word 0x1a00001f
+ .word 0xeb000e1d
+ .word 0xe24dd010
+ .word 0xe1a08407
+ .word 0xe3888001
+ .word 0xe58d8000
+ .word 0xe10f8000
+ .word 0xe3888080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe28d8010
+ .word 0xed088203
+ .word 0xed980100
+ .word 0xea00002b
+ .word 0xe92d4c30
+ .word 0xee207110
+ .word 0xe24dd00c
+ .word 0xe92d0007
+ .word 0xe28f8f7b
+ .word 0xe20b3010
+ .word 0xe7983123
+ .word 0xe31b0902
+ .word 0x11a03823
+ .word 0xe20b860f
+ .word 0xe1a08a28
+ .word 0xe1a03833
+ .word 0xe0033fa7
+ .word 0xe1c33527
+ .word 0xe0033cab
+ .word 0xe31b0501
+ .word 0x1a00000e
+ .word 0xe31b0902
+ .word 0x0affffdf
+ .word 0xeb000dfd
+ .word 0xe24dd010
+ .word 0xe1a08407
+ .word 0xe3888001
+ .word 0xe58d8000
+ .word 0xe10f8000
+ .word 0xe3888080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe28d8010
+ .word 0xed088203
+ .word 0xed988100
+ .word 0xea00000b
+ .word 0xeb000df0
+ .word 0xe24dd010
+ .word 0xe1a08407
+ .word 0xe3888001
+ .word 0xe58d8000
+ .word 0xe10f8000
+ .word 0xe3888080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe28d8010
+ .word 0xed088203
+ .word 0xedd80100
+ .word 0xee307110
+ .word 0xe28d8010
+ .word 0xed888200
+ .word 0xe8980007
+ .word 0xed188203
+ .word 0xe28dd028
+ .word 0xe10f8000
+ .word 0xe3c88080
+ .word 0xe129f008
+ .word 0xe1a00000
+ .word 0xe2106101
+ .word 0x03c03103
+ .word 0x02000102
+ .word 0xe3b08001
+ .word 0xe8bd8c30
+ .word 0xe3170801
+ .word 0x0affff9d
+ .word 0xe92d4c30
+ .word 0xee207110
+ .word 0xe92d003f
+ .word 0xe28f80fc
+ .word 0xe20b3010
+ .word 0xe7983123
+ .word 0xe31b0902
+ .word 0x11a03823
+ .word 0xe20b860f
+ .word 0xe1a08a28
+ .word 0xe1a03833
+ .word 0xe0033fa7
+ .word 0xe1c33527
+ .word 0xe0033cab
+ .word 0xe31b0702
+ .word 0x1a000005
+ .word 0xe31b0080
+ .word 0x1a000001
+ .word 0xeb000dc1
+ .word 0xeaffffa2
+ .word 0xeb000dbf
+ .word 0xeaffffc0
+ .word 0xeb000dbd
+ .word 0xeaffffcb
+ .word 0xe3170801
+ .word 0x03877001
+ .word 0x01a0f00e
+ .word 0xe92d4c00
+ .word 0xee207110
+ .word 0xe24dd004
+ .word 0xe92d0007
+ .word 0xe3a03000
+ .word 0xeb000db3
+ .word 0xee307110
+ .word 0xe49d6010
+ .word 0xe8bd8c00
+ .word 0xe3170801
+ .word 0x03877001
+ .word 0x01a0f00e
+ .word 0xe92d4c00
+ .word 0xee207110
+ .word 0xe92d003f
+ .word 0xe3a03000
+ .word 0xeb000da8
+ .word 0xee307110
+ .word 0xe49d6018
+ .word 0xe8bd8c00
+ .word 0xe92d4c00
+ .word 0xee207110
+ .word 0xe24dd004
+ .word 0xe92d0007
+ .word 0xe3a03000
+ .word 0xe3170b02
+ .word 0x1a000003
+ .word 0xeb000d9d
+ .word 0xe8bd0007
+ .word 0xe28dd004
+ .word 0xea000001
+ .word 0xeb000d99
+ .word 0xe8bd0047
+ .word 0xee307110
+ .word 0xe8bd8c00
+ .word 0x40007fff
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x40007fff
+ .word 0x40000000
+ .word 0x00000000
+ .word 0xc0070e3f
+ .word 0x00010001
+ .word 0xe3170802
+ .word 0x1a000004
+ .word 0xe3877002
+ .word 0xe24f0034
+ .word 0xe8900007
+ .word 0xe3800102
+ .word 0xe1a0f00e
+ .word 0xe92d4c30
+ .word 0xee207110
+ .word 0xe24dd00c
+ .word 0xe92d0007
+ .word 0xe24f803c
+ .word 0xe20b3010
+ .word 0xe7983123
+ .word 0xe31b0902
+ .word 0x11a03823
+ .word 0xe20b860f
+ .word 0xe1a08a28
+ .word 0xe1a03833
+ .word 0xe0033fa7
+ .word 0xe1c33527
+ .word 0xe0033cab
+ .word 0xe31b0702
+ .word 0x1a000005
+ .word 0xe31b0080
+ .word 0x1a000001
+ .word 0xeb000d75
+ .word 0xeaffff54
+ .word 0xeb000d73
+ .word 0xeaffff72
+ .word 0xeb000d71
+ .word 0xeaffff7d
+ .word 0xe3170802
+ .word 0x1a000006
+ .word 0xe3877002
+ .word 0xe0208003
+ .word 0xe2088102
+ .word 0xe24f00bc
+ .word 0xe8900007
+ .word 0xe1800008
+ .word 0xe1a0f00e
+ .word 0xe92d4c30
+ .word 0xee207110
+ .word 0xe92d003f
+ .word 0xe24f80c0
+ .word 0xe20b3010
+ .word 0xe7983123
+ .word 0xe31b0902
+ .word 0x11a03823
+ .word 0xe20b860f
+ .word 0xe1a08a28
+ .word 0xe1a03833
+ .word 0xe0033fa7
+ .word 0xe1c33527
+ .word 0xe0033cab
+ .word 0xe31b0702
+ .word 0x1a000005
+ .word 0xe31b0080
+ .word 0x1a000001
+ .word 0xeb000d54
+ .word 0xeaffff33
+ .word 0xeb000d52
+ .word 0xeaffff51
+ .word 0xeb000d50
+ .word 0xeaffff5c
+ .word 0xe2000102
+ .word 0xe3310000
+ .word 0x0a000017
+ .word 0xe3a08000
+ .word 0xe1b09821
+ .word 0x01a01801
+ .word 0x02888010
+ .word 0xe1b09c21
+ .word 0x01a01401
+ .word 0x02888008
+ .word 0xe1b09e21
+ .word 0x01a01201
+ .word 0x02888004
+ .word 0xe1b09f21
+ .word 0x01a01101
+ .word 0x02888002
+ .word 0xe1b09fa1
+ .word 0x01a01081
+ .word 0x02888001
+ .word 0xe05898a6
+ .word 0x81a01931
+ .word 0x81a088a6
+ .word 0xe2686020
+ .word 0xe1811632
+ .word 0xe1a02812
+ .word 0x30400009
+ .word 0xe1a0f00e
+ .word 0xe3560501
+ .word 0x3a000016
+ .word 0xe1b01002
+ .word 0x01a0f00e
+ .word 0xe3a02000
+ .word 0xe3a08020
+ .word 0xe1b09821
+ .word 0x01a01801
+ .word 0x02888010
+ .word 0xe1b09c21
+ .word 0x01a01401
+ .word 0x02888008
+ .word 0xe1b09e21
+ .word 0x01a01201
+ .word 0x02888004
+ .word 0xe1b09f21
+ .word 0x01a01101
+ .word 0x02888002
+ .word 0xe1b09fa1
+ .word 0x01a01081
+ .word 0x02888001
+ .word 0xe05898a6
+ .word 0x81a01931
+ .word 0x30400009
+ .word 0xe1a0f00e
+ .word 0xe1a088a6
+ .word 0xe2689020
+ .word 0xe1a01811
+ .word 0xe1811932
+ .word 0xe1a02812
+ .word 0xe1a0f00e
+ .word 0xe2033102
+ .word 0xe3340000
+ .word 0x0a000017
+ .word 0xe3a08000
+ .word 0xe1b09824
+ .word 0x01a04804
+ .word 0x02888010
+ .word 0xe1b09c24
+ .word 0x01a04404
+ .word 0x02888008
+ .word 0xe1b09e24
+ .word 0x01a04204
+ .word 0x02888004
+ .word 0xe1b09f24
+ .word 0x01a04104
+ .word 0x02888002
+ .word 0xe1b09fa4
+ .word 0x01a04084
+ .word 0x02888001
+ .word 0xe05898a6
+ .word 0x81a04934
+ .word 0x81a088a6
+ .word 0xe2686020
+ .word 0xe1844635
+ .word 0xe1a05815
+ .word 0x30433009
+ .word 0xe1a0f00e
+ .word 0xe3560501
+ .word 0x3a000016
+ .word 0xe1b04005
+ .word 0x01a0f00e
+ .word 0xe3a05000
+ .word 0xe3a08020
+ .word 0xe1b09824
+ .word 0x01a04804
+ .word 0x02888010
+ .word 0xe1b09c24
+ .word 0x01a04404
+ .word 0x02888008
+ .word 0xe1b09e24
+ .word 0x01a04204
+ .word 0x02888004
+ .word 0xe1b09f24
+ .word 0x01a04104
+ .word 0x02888002
+ .word 0xe1b09fa4
+ .word 0x01a04084
+ .word 0x02888001
+ .word 0xe05898a6
+ .word 0x81a04934
+ .word 0x30433009
+ .word 0xe1a0f00e
+ .word 0xe1a088a6
+ .word 0xe2689020
+ .word 0xe1a04814
+ .word 0xe1844935
+ .word 0xe1a05815
+ .word 0xe1a0f00e
+ .word 0xe3a02000
+ .word 0xe2160102
+ .word 0x12661000
+ .word 0x01b01006
+ .word 0x03a03000
+ .word 0x01a0f00e
+ .word 0xe3a03901
+ .word 0xe383301e
+ .word 0xe3a06000
+ .word 0xe3310000
+ .word 0x01a01002
+ .word 0x03a02000
+ .word 0x02433020
+ .word 0xe3a08000
+ .word 0xe1b09821
+ .word 0x01a01801
+ .word 0x02888010
+ .word 0xe1b09c21
+ .word 0x01a01401
+ .word 0x02888008
+ .word 0xe1b09e21
+ .word 0x01a01201
+ .word 0x02888004
+ .word 0xe1b09f21
+ .word 0x01a01101
+ .word 0x02888002
+ .word 0xe1b09fa1
+ .word 0x01a01081
+ .word 0x02888001
+ .word 0xe2789020
+ .word 0xe1811932
+ .word 0xe1a02812
+ .word 0xe0433008
+ .word 0xe1a0f00e
+ .word 0xe3340000
+ .word 0x01a04005
+ .word 0x03a05000
+ .word 0x02433020
+ .word 0xe3a08000
+ .word 0xe1b09824
+ .word 0x01a04804
+ .word 0x02888010
+ .word 0xe1b09c24
+ .word 0x01a04404
+ .word 0x02888008
+ .word 0xe1b09e24
+ .word 0x01a04204
+ .word 0x02888004
+ .word 0xe1b09f24
+ .word 0x01a04104
+ .word 0x02888002
+ .word 0xe1b09fa4
+ .word 0x01a04084
+ .word 0x02888001
+ .word 0xe2789020
+ .word 0xe1844935
+ .word 0xe1a05815
+ .word 0xe0433008
+ .word 0xe1a0f00e
+ .word 0xe3310000
+ .word 0x01a01002
+ .word 0x03a02000
+ .word 0x02833020
+ .word 0xe3a08000
+ .word 0xe1b09821
+ .word 0x01a01801
+ .word 0x02888010
+ .word 0xe1b09c21
+ .word 0x01a01401
+ .word 0x02888008
+ .word 0xe1b09e21
+ .word 0x01a01201
+ .word 0x02888004
+ .word 0xe1b09f21
+ .word 0x01a01101
+ .word 0x02888002
+ .word 0xe1b09fa1
+ .word 0x01a01081
+ .word 0x02888001
+ .word 0xe2789020
+ .word 0xe1811932
+ .word 0xe1a02812
+ .word 0xe0833008
+ .word 0xe1a0f00e
+ .word 0xe3100101
+ .word 0x03130101
+ .word 0x1a0003c1
+ .word 0xe92d4000
+ .word 0xe31b0602
+ .word 0x12233102
+ .word 0xe31b0601
+ .word 0x12233102
+ .word 0x12200102
+ .word 0xe1a06880
+ .word 0xe0568883
+ .word 0xe020e003
+ .word 0xe2000102
+ .word 0xe1a038a6
+ .word 0x8a00001a
+ .word 0x01a09008
+ .word 0x0a00002e
+ .word 0xe2686000
+ .word 0xe1a068a6
+ .word 0xe0833006
+ .word 0xe1a092a6
+ .word 0xe1c66289
+ .word 0xe3590002
+ .word 0x33390000
+ .word 0xe2669020
+ .word 0xe1a08912
+ .word 0xe1a02632
+ .word 0xe1822911
+ .word 0xe1a01631
+ .word 0x0a000003
+ .word 0x11888108
+ .word 0x11828128
+ .word 0x11a02001
+ .word 0x13a01000
+ .word 0x3a000004
+ .word 0x21888002
+ .word 0x21888108
+ .word 0x21818128
+ .word 0x23a02000
+ .word 0x23a01000
+ .word 0xe3a09000
+ .word 0xea000015
+ .word 0xe1a068a8
+ .word 0xe1a082a6
+ .word 0xe1c66288
+ .word 0xe3580002
+ .word 0x33380000
+ .word 0xe2668020
+ .word 0xe1a09815
+ .word 0xe1a05635
+ .word 0xe1855814
+ .word 0xe1a04634
+ .word 0x0a000003
+ .word 0x11899109
+ .word 0x11859129
+ .word 0x11a05004
+ .word 0x13a04000
+ .word 0x3a000004
+ .word 0x21899005
+ .word 0x21899109
+ .word 0x21849129
+ .word 0x23a05000
+ .word 0x23a04000
+ .word 0xe3a08000
+ .word 0xe31e0102
+ .word 0x1a000009
+ .word 0xe0986009
+ .word 0xe0b22005
+ .word 0xe0b11004
+ .word 0x38bd8000
+ .word 0xe2833001
+ .word 0xe1b01061
+ .word 0xe1b02062
+ .word 0xe1866086
+ .word 0xe1a06066
+ .word 0xe8bd8000
+ .word 0xe0586009
+ .word 0xe0d22005
+ .word 0xe0d11004
+ .word 0x2a000003
+ .word 0xe2200102
+ .word 0xe2766000
+ .word 0xe2f22000
+ .word 0xe2e11000
+ .word 0xe3110102
+ .word 0x18bd8000
+ .word 0xe0966006
+ .word 0xe0b22002
+ .word 0xe0a11001
+ .word 0xe2433001
+ .word 0xe3110102
+ .word 0x18bd8000
+ .word 0xe191e002
+ .word 0x1bffff56
+ .word 0x18bd8000
+ .word 0xe20b8060
+ .word 0xe3380040
+ .word 0x03a00102
+ .word 0x13a00000
+ .word 0xe3a03000
+ .word 0xe8bd8000
+ .word 0xe3100101
+ .word 0x03130101
+ .word 0x1a000395
+ .word 0xe0118004
+ .word 0x5a0003b5
+ .word 0xe3c08103
+ .word 0xe3c39103
+ .word 0xe0200003
+ .word 0xe2000102
+ .word 0xe0883009
+ .word 0xe2433c3f
+ .word 0xe24330fe
+ .word 0xe31b0502
+ .word 0x1a00007f
+ .word 0xe3320000
+ .word 0x0a00005d
+ .word 0xe3350000
+ .word 0x0a00003d
+ .word 0xe92d4881
+ .word 0xe1a00821
+ .word 0xe1c17800
+ .word 0xe1a06824
+ .word 0xe1c48806
+ .word 0xe0090690
+ .word 0xe0060697
+ .word 0xe0070798
+ .word 0xe0977806
+ .word 0xe0a99826
+ .word 0xe0080890
+ .word 0xe0977808
+ .word 0xe0a90828
+ .word 0xe1a0b822
+ .word 0xe1c2e80b
+ .word 0xe1a06825
+ .word 0xe1c58806
+ .word 0xe009069b
+ .word 0xe006069e
+ .word 0xe00e0e98
+ .word 0xe09ee806
+ .word 0xe0a99826
+ .word 0xe008089b
+ .word 0xe09ee808
+ .word 0xe0a9b828
+ .word 0xe097700b
+ .word 0xe2a00000
+ .word 0xe097b00e
+ .word 0xe0b77000
+ .word 0xe2a00000
+ .word 0xe0518002
+ .word 0xe3a01000
+ .word 0xe3a06000
+ .word 0x31e01001
+ .word 0x30446005
+ .word 0x10559004
+ .word 0x03a01000
+ .word 0x31e01001
+ .word 0x30466008
+ .word 0xe1a04828
+ .word 0xe1c85804
+ .word 0xe1a08829
+ .word 0xe1c99808
+ .word 0xe0226894
+ .word 0xe0080895
+ .word 0xe0060599
+ .word 0xe0966808
+ .word 0xe0a22828
+ .word 0xe0090994
+ .word 0xe0966809
+ .word 0xe0a22829
+ .word 0xe09b6006
+ .word 0xe0b72002
+ .word 0xe0b01001
+ .word 0xe18ee10e
+ .word 0xe186612e
+ .word 0x48bd8881
+ .word 0xe0966006
+ .word 0xe0b22002
+ .word 0xe0a11001
+ .word 0xe2433001
+ .word 0xe8bd8881
+ .word 0xe1a05824
+ .word 0xe1c46805
+ .word 0xe1a08821
+ .word 0xe1c19808
+ .word 0xe0040895
+ .word 0xe0080896
+ .word 0xe0010699
+ .word 0xe0911808
+ .word 0xe0a44828
+ .word 0xe0090995
+ .word 0xe0911809
+ .word 0xe0a44829
+ .word 0xe1a08822
+ .word 0xe1c29808
+ .word 0xe0020895
+ .word 0xe0080896
+ .word 0xe0060699
+ .word 0xe0966808
+ .word 0xe0a22828
+ .word 0xe0090995
+ .word 0xe0966809
+ .word 0xe0a25829
+ .word 0xe0952001
+ .word 0xe2b41000
+ .word 0x41a0f00e
+ .word 0xe0966006
+ .word 0xe0b22002
+ .word 0xe0a11001
+ .word 0xe2433001
+ .word 0xe1a0f00e
+ .word 0xe3350000
+ .word 0x0a00001d
+ .word 0xe1a02821
+ .word 0xe1c16802
+ .word 0xe1a08824
+ .word 0xe1c49808
+ .word 0xe0010892
+ .word 0xe0080896
+ .word 0xe0040699
+ .word 0xe0944808
+ .word 0xe0a11828
+ .word 0xe0090992
+ .word 0xe0944809
+ .word 0xe0a11829
+ .word 0xe1a08825
+ .word 0xe1c59808
+ .word 0xe0050892
+ .word 0xe0080896
+ .word 0xe0060699
+ .word 0xe0966808
+ .word 0xe0a55828
+ .word 0xe0090992
+ .word 0xe0966809
+ .word 0xe0a52829
+ .word 0xe0922004
+ .word 0xe2b11000
+ .word 0x41a0f00e
+ .word 0xe0966006
+ .word 0xe0b22002
+ .word 0xe0a11001
+ .word 0xe2433001
+ .word 0xe1a0f00e
+ .word 0xe1a05824
+ .word 0xe1c46805
+ .word 0xe1a08821
+ .word 0xe1c19808
+ .word 0xe0010895
+ .word 0xe0080896
+ .word 0xe0020699
+ .word 0xe0922808
+ .word 0xe0a11828
+ .word 0xe0090995
+ .word 0xe0922809
+ .word 0xe0b11829
+ .word 0xe3a06000
+ .word 0x41a0f00e
+ .word 0xe0922002
+ .word 0xe0a11001
+ .word 0xe2433001
+ .word 0xe1a0f00e
+ .word 0xe3100101
+ .word 0x03130101
+ .word 0x1a000336
+ .word 0xe0118004
+ .word 0x5a000361
+ .word 0xe31b0601
+ .word 0x1a000008
+ .word 0xe1a08000
+ .word 0xe1a00003
+ .word 0xe1a03008
+ .word 0xe1a08001
+ .word 0xe1a01004
+ .word 0xe1a04008
+ .word 0xe1a08002
+ .word 0xe1a02005
+ .word 0xe1a05008
+ .word 0xe3c08103
+ .word 0xe3c39103
+ .word 0xe0200003
+ .word 0xe2000102
+ .word 0xe0493008
+ .word 0xe2833c3f
+ .word 0xe28330ff
+ .word 0xe92d4889
+ .word 0xe1a00821
+ .word 0xe1c17800
+ .word 0xe1a0b822
+ .word 0xe1c2e80b
+ .word 0xe28f6fd9
+ .word 0xe7d66420
+ .word 0xe0286690
+ .word 0xe2688502
+ .word 0xe0060698
+ .word 0xe1a069a6
+ .word 0xe2866002
+ .word 0xe1a086a1
+ .word 0xe0296698
+ .word 0xe2699202
+ .word 0xe1a08829
+ .word 0xe1c99808
+ .word 0xe0020699
+ .word 0xe0010698
+ .word 0xe0816822
+ .word 0xe1a06326
+ .word 0xe1b040a4
+ .word 0xe1b05065
+ .word 0x33a03000
+ .word 0x23a03102
+ .word 0xe1a087a4
+ .word 0xe0090896
+ .word 0xe1a09829
+ .word 0xe0080b99
+ .word 0xe0555008
+ .word 0xe0080990
+ .word 0xe0c44008
+ .word 0xe0080e99
+ .word 0xe0533808
+ .word 0xe0d55828
+ .word 0xe0080799
+ .word 0x30455808
+ .word 0x20555808
+ .word 0xe0c44828
+ .word 0xe1a01809
+ .word 0xe1a08124
+ .word 0xe0090896
+ .word 0xe1a09829
+ .word 0xe0080b99
+ .word 0xe0533988
+ .word 0xe0d556a8
+ .word 0xe0080990
+ .word 0x30455988
+ .word 0x20555988
+ .word 0xe0c446a8
+ .word 0xe0080e99
+ .word 0xe0533188
+ .word 0xe0d55ea8
+ .word 0xe0080799
+ .word 0x30455188
+ .word 0x20555188
+ .word 0xe0c44ea8
+ .word 0xe1a04d04
+ .word 0xe1844325
+ .word 0xe1a05d05
+ .word 0xe1855323
+ .word 0xe1a03d03
+ .word 0xe0811189
+ .word 0xe59d800c
+ .word 0xe3180702
+ .word 0x03180080
+ .word 0x0a000094
+ .word 0xe1a087a4
+ .word 0xe0090896
+ .word 0xe1a09829
+ .word 0xe0080b99
+ .word 0xe0555008
+ .word 0xe0080990
+ .word 0xe0c44008
+ .word 0xe0080e99
+ .word 0xe0533808
+ .word 0xe0d55828
+ .word 0xe0080799
+ .word 0x30455808
+ .word 0x20555808
+ .word 0xe0c44828
+ .word 0xe1a02b09
+ .word 0xe0811529
+ .word 0xe1a08124
+ .word 0xe0090896
+ .word 0xe1a09829
+ .word 0xe0080b99
+ .word 0xe0533988
+ .word 0xe0d556a8
+ .word 0xe0080990
+ .word 0x30455988
+ .word 0x20555988
+ .word 0xe0c446a8
+ .word 0xe0080e99
+ .word 0xe0533188
+ .word 0xe0d55ea8
+ .word 0xe0080799
+ .word 0x30455188
+ .word 0x20555188
+ .word 0xe0c44ea8
+ .word 0xe1a04d04
+ .word 0xe1844325
+ .word 0xe1a05d05
+ .word 0xe1855323
+ .word 0xe1a03d03
+ .word 0xe0922489
+ .word 0xe2a11000
+ .word 0xe59d800c
+ .word 0xe3180702
+ .word 0x0a00003f
+ .word 0xe1a087a4
+ .word 0xe0090896
+ .word 0xe1a09829
+ .word 0xe0080b99
+ .word 0xe0555008
+ .word 0xe0080990
+ .word 0xe0c44008
+ .word 0xe0080e99
+ .word 0xe0533808
+ .word 0xe0d55828
+ .word 0xe0080799
+ .word 0x30455808
+ .word 0x20555808
+ .word 0xe0c44828
+ .word 0xe1a04704
+ .word 0xe1844925
+ .word 0xe1a05705
+ .word 0xe1855923
+ .word 0xe1a03703
+ .word 0xe1a06e09
+ .word 0xe0922229
+ .word 0xe2a11000
+ .word 0xe1870800
+ .word 0xe18e780b
+ .word 0xe3a0e000
+ .word 0xe0559007
+ .word 0xe0d48000
+ .word 0x21a05009
+ .word 0x21a04008
+ .word 0xe0aee00e
+ .word 0xe3a0b000
+ .word 0xe0933003
+ .word 0xe0b55005
+ .word 0xe0b44004
+ .word 0xe0abb00b
+ .word 0xe0559007
+ .word 0xe0d48000
+ .word 0xe2dbb000
+ .word 0x21a05009
+ .word 0x21a04008
+ .word 0xe0aee00e
+ .word 0xe3a0b000
+ .word 0xe0933003
+ .word 0xe0b55005
+ .word 0xe0b44004
+ .word 0xe0abb00b
+ .word 0xe0559007
+ .word 0xe0d48000
+ .word 0xe2dbb000
+ .word 0x21a05009
+ .word 0x21a04008
+ .word 0xe0aee00e
+ .word 0xe1948005
+ .word 0x13866001
+ .word 0xe0966e0e
+ .word 0xe2b22000
+ .word 0xe2b11000
+ .word 0x48bd8889
+ .word 0xe8bd4889
+ .word 0xe0966006
+ .word 0xe0b22002
+ .word 0xe0a11001
+ .word 0xe2433001
+ .word 0xe1a0f00e
+ .word 0xe1870800
+ .word 0xe18e780b
+ .word 0xe3a0e000
+ .word 0xe0933003
+ .word 0xe0b55005
+ .word 0xe0a44004
+ .word 0xe0559007
+ .word 0xe0d48000
+ .word 0x21a05009
+ .word 0x21a04008
+ .word 0xe0aee00e
+ .word 0xe3a0b000
+ .word 0xe0933003
+ .word 0xe0b55005
+ .word 0xe0b44004
+ .word 0xe0abb00b
+ .word 0xe0559007
+ .word 0xe0d48000
+ .word 0xe2dbb000
+ .word 0x21a05009
+ .word 0x21a04008
+ .word 0xe0aee00e
+ .word 0xe3a0b000
+ .word 0xe0933003
+ .word 0xe0b55005
+ .word 0xe0b44004
+ .word 0xe0abb00b
+ .word 0xe0559007
+ .word 0xe0d48000
+ .word 0xe2dbb000
+ .word 0x21a05009
+ .word 0x21a04008
+ .word 0xe0aee00e
+ .word 0xe1846005
+ .word 0xe092248e
+ .word 0xe2b11000
+ .word 0x48bd8889
+ .word 0xe8bd4889
+ .word 0xe0922002
+ .word 0xe0a11001
+ .word 0xe2433001
+ .word 0xe1a0f00e
+ .word 0xe1870800
+ .word 0xe18e780b
+ .word 0xe0933003
+ .word 0xe0b55005
+ .word 0xe0a44004
+ .word 0xe0559007
+ .word 0xe0d48000
+ .word 0x21a05009
+ .word 0x21a04008
+ .word 0x22811020
+ .word 0xe3a0b000
+ .word 0xe0933003
+ .word 0xe0b55005
+ .word 0xe0b44004
+ .word 0xe0abb00b
+ .word 0xe0559007
+ .word 0xe0d48000
+ .word 0xe2dbb000
+ .word 0x21a05009
+ .word 0x21a04008
+ .word 0x22811010
+ .word 0xe3a0b000
+ .word 0xe0933003
+ .word 0xe0b55005
+ .word 0xe0b44004
+ .word 0xe0abb00b
+ .word 0xe0559007
+ .word 0xe0d48000
+ .word 0xe2dbb000
+ .word 0x21a05009
+ .word 0x21a04008
+ .word 0x22811008
+ .word 0xe1846005
+ .word 0xe3a02000
+ .word 0xe3310000
+ .word 0x48bd8889
+ .word 0xe8bd4889
+ .word 0xe1a01081
+ .word 0xe2433001
+ .word 0xe1a0f00e
+ .word 0x7e7f8080
+ .word 0x7a7b7c7d
+ .word 0x76777879
+ .word 0x73747576
+ .word 0x70717172
+ .word 0x6d6e6e6f
+ .word 0x6a6b6c6c
+ .word 0x6868696a
+ .word 0x65666667
+ .word 0x63636464
+ .word 0x60616162
+ .word 0x5e5f5f60
+ .word 0x5c5d5d5e
+ .word 0x5a5b5b5c
+ .word 0x5859595a
+ .word 0x56575758
+ .word 0x55555556
+ .word 0x53535454
+ .word 0x51525252
+ .word 0x50505051
+ .word 0x4e4f4f4f
+ .word 0x4d4d4d4e
+ .word 0x4b4c4c4c
+ .word 0x4a4a4b4b
+ .word 0x4949494a
+ .word 0x47484848
+ .word 0x46474747
+ .word 0x45454646
+ .word 0x44444445
+ .word 0x43434344
+ .word 0x42424243
+ .word 0x41414142
+ .word 0xe3100101
+ .word 0x03130101
+ .word 0x1a00025f
+ .word 0xe1946005
+ .word 0x03a0800a
+ .word 0x0afffc6c
+ .word 0xe1916002
+ .word 0x0a000297
+ .word 0xe92d4000
+ .word 0xe3c33103
+ .word 0xe2433001
+ .word 0xe3c06103
+ .word 0xe0566003
+ .word 0xe2000102
+ .word 0xb0863003
+ .word 0xb3a06000
+ .word 0xb1a0f00e
+ .word 0xe1a000c0
+ .word 0xe3a0e000
+ .word 0xea000002
+ .word 0xe1a0efa1
+ .word 0xe0922002
+ .word 0xe0a11001
+ .word 0xe0728005
+ .word 0xe0f19004
+ .word 0xe2fee000
+ .word 0x2a000002
+ .word 0xe0982005
+ .word 0xe0a91004
+ .word 0xe2200102
+ .word 0xe2566001
+ .word 0xaafffff3
+ .word 0xe3a06000
+ .word 0xe1918002
+ .word 0x01a00080
+ .word 0x03a03000
+ .word 0x12000102
+ .word 0x1bfffd52
+ .word 0xe8bd8000
+ .word 0xe3100101
+ .word 0x1a00027f
+ .word 0xe3110102
+ .word 0x0a000293
+ .word 0xe3c03103
+ .word 0xe2100102
+ .word 0x13a0800b
+ .word 0x1afffbe1
+ .word 0xe2833c3f
+ .word 0xe28330ff
+ .word 0xe1b030a3
+ .word 0x32414102
+ .word 0x22414101
+ .word 0xe1a05002
+ .word 0xe3a08202
+ .word 0xe3a01102
+ .word 0xe3a02000
+ .word 0xe3a0928b
+ .word 0xe1a069ab
+ .word 0xe3160001
+ .word 0x03a0926b
+ .word 0x031b0080
+ .word 0x03a09103
+ .word 0x3a000005
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe1816008
+ .word 0x31540006
+ .word 0x20444006
+ .word 0x21811088
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe18160a8
+ .word 0x31540006
+ .word 0x20444006
+ .word 0x21811008
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe1816128
+ .word 0x31540006
+ .word 0x20444006
+ .word 0x218110a8
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe18161a8
+ .word 0x31540006
+ .word 0x20444006
+ .word 0x21811128
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe1816228
+ .word 0x31540006
+ .word 0x20444006
+ .word 0x218111a8
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe18162a8
+ .word 0x31540006
+ .word 0x20444006
+ .word 0x21811228
+ .word 0xe2999201
+ .word 0xe1a08368
+ .word 0xbaffffd8
+ .word 0xe1946005
+ .word 0x13580020
+ .word 0x01a0f00e
+ .word 0xe92d4880
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe0aee00e
+ .word 0xe1826008
+ .word 0xe055b006
+ .word 0xe0d47001
+ .word 0x31b0e0ae
+ .word 0x21a0500b
+ .word 0x21a04007
+ .word 0x21822088
+ .word 0x21811fa8
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe0aee00e
+ .word 0xe18260a8
+ .word 0xe055b006
+ .word 0xe0d47001
+ .word 0x31b0e0ae
+ .word 0x21a0500b
+ .word 0x21a04007
+ .word 0x21822008
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe0aee00e
+ .word 0xe1826128
+ .word 0xe055b006
+ .word 0xe0d47001
+ .word 0x31b0e0ae
+ .word 0x21a0500b
+ .word 0x21a04007
+ .word 0x218220a8
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe0aee00e
+ .word 0xe18261a8
+ .word 0xe055b006
+ .word 0xe0d47001
+ .word 0x31b0e0ae
+ .word 0x21a0500b
+ .word 0x21a04007
+ .word 0x21822128
+ .word 0xe2599001
+ .word 0xe1a08268
+ .word 0x1affffd3
+ .word 0xe1946005
+ .word 0x13580080
+ .word 0x08bd8880
+ .word 0xe0955005
+ .word 0xe0b44004
+ .word 0xe0aee00e
+ .word 0xe2788000
+ .word 0xe0f2b005
+ .word 0xe0f17004
+ .word 0x31b0e0ae
+ .word 0x21a0500b
+ .word 0x21a04007
+ .word 0x33a08000
+ .word 0x23822001
+ .word 0xe3a06106
+ .word 0xe0988008
+ .word 0xe0b55005
+ .word 0xe0b44004
+ .word 0x28bd8880
+ .word 0xe0d5b002
+ .word 0xe0d4b001
+ .word 0x33a06001
+ .word 0xe8bd8880
+ .word 0xe3100101
+ .word 0x1a00021a
+ .word 0xe3c03103
+ .word 0xe2000102
+ .word 0xe3a06000
+ .word 0xe31b0601
+ .word 0x12200102
+ .word 0xe31b0602
+ .word 0x13c00102
+ .word 0xe1a0f00e
+ .word 0xe3100101
+ .word 0x1a000236
+ .word 0xe3c03103
+ .word 0xe3110102
+ .word 0x1a000008
+ .word 0xe1918002
+ .word 0x03a03000
+ .word 0x0a000005
+ .word 0xe92d4000
+ .word 0xe0116080
+ .word 0x43c11102
+ .word 0x42833001
+ .word 0xebfffcb4
+ .word 0xe8bd4000
+ .word 0xe2000102
+ .word 0xe3a06000
+ .word 0xe1a0f00e
+ .word 0xe3100101
+ .word 0x1a000232
+ .word 0xe3c06103
+ .word 0xe2000102
+ .word 0xe3a03016
+ .word 0xe31b0080
+ .word 0x13a03033
+ .word 0xe31b0702
+ .word 0x13a0303e
+ .word 0xe3833901
+ .word 0xe0538006
+ .word 0x9a000014
+ .word 0xe1a092a8
+ .word 0xe1c88289
+ .word 0xe3590002
+ .word 0x33390000
+ .word 0xe2689020
+ .word 0xe1a06912
+ .word 0xe1a02832
+ .word 0xe1822911
+ .word 0xe1a01831
+ .word 0x0a000003
+ .word 0x11866106
+ .word 0x11826126
+ .word 0x11a02001
+ .word 0x13a01000
+ .word 0x3a000004
+ .word 0x21866002
+ .word 0x21866106
+ .word 0x21816126
+ .word 0x23a02000
+ .word 0x23a01000
+ .word 0xe1a0f00e
+ .word 0xe1a03006
+ .word 0xe3a06000
+ .word 0xe1a0f00e
+ .word 0xe3100101
+ .word 0x1a000219
+ .word 0xe3c03103
+ .word 0xe2000102
+ .word 0xe3110102
+ .word 0x0a000049
+ .word 0x13a0603e
+ .word 0xe3866901
+ .word 0xe0568003
+ .word 0xda000045
+ .word 0xe2789020
+ .word 0xba000017
+ .word 0xe1b08912
+ .word 0x0a000041
+ .word 0xe1b08080
+ .word 0x231b0020
+ .word 0x331b0040
+ .word 0x1a000007
+ .word 0xe31b0060
+ .word 0x1a00000a
+ .word 0xe2898001
+ .word 0xe1b08812
+ .word 0x1a000001
+ .word 0xe1b080a1
+ .word 0xe1b08912
+ .word 0x2a000004
+ .word 0xe2699020
+ .word 0xe1a02932
+ .word 0xe1a02912
+ .word 0xe3a06101
+ .word 0xe1a0f00e
+ .word 0xe2699020
+ .word 0xe1e02932
+ .word 0xe1e02912
+ .word 0xe3a06103
+ .word 0xe1a0f00e
+ .word 0xe2789040
+ .word 0xba00001a
+ .word 0xe1928911
+ .word 0x0a000027
+ .word 0xe1b08080
+ .word 0x231b0020
+ .word 0x331b0040
+ .word 0x1a000007
+ .word 0xe31b0060
+ .word 0x1a00000c
+ .word 0xe2898001
+ .word 0xe1928811
+ .word 0x1a000001
+ .word 0xe3590001
+ .word 0x21b08911
+ .word 0x2a000006
+ .word 0xe2699020
+ .word 0xe1a01931
+ .word 0xe1b01911
+ .word 0xe3a02000
+ .word 0x03a03000
+ .word 0xe3a06101
+ .word 0xe1a0f00e
+ .word 0xe2699020
+ .word 0xe1e01931
+ .word 0xe1e01911
+ .word 0xe3e02000
+ .word 0xe3a06103
+ .word 0xe1a0f00e
+ .word 0xe0208d0b
+ .word 0xe0209c8b
+ .word 0xe1d88009
+ .word 0x4a000004
+ .word 0xe3a01000
+ .word 0xe3a02000
+ .word 0xe3a03000
+ .word 0xe3a06101
+ .word 0xe1a0f00e
+ .word 0xe3e01000
+ .word 0xe3e02000
+ .word 0xe3a03c3f
+ .word 0xe38330fe
+ .word 0xe3a06103
+ .word 0xe1a0f00e
+ .word 0xe3a06000
+ .word 0xe1a0f00e
+ .word 0xe3100101
+ .word 0x03130101
+ .word 0x1a0001d7
+ .word 0xe31b0602
+ .word 0x02233102
+ .word 0xe1a08880
+ .word 0xe1580883
+ .word 0x01510004
+ .word 0x01520005
+ .word 0x0a000004
+ .word 0x23300000
+ .word 0x33330000
+ .word 0x53a06202
+ .word 0x43a06102
+ .word 0xe1a0f00e
+ .word 0xe0309003
+ .word 0xe3a06206
+ .word 0x41a0f00e
+ .word 0xe1888001
+ .word 0xe1988002
+ .word 0x01a0f00e
+ .word 0xe3100102
+ .word 0x03a06202
+ .word 0x13a06102
+ .word 0xe1a0f00e
+ .word 0xe3100101
+ .word 0x1a0001f9
+ .word 0xe3c06103
+ .word 0xe2000102
+ .word 0xe92d4000
+ .word 0xe3a03901
+ .word 0xe383303e
+ .word 0xe0538006
+ .word 0x9a000023
+ .word 0xe1a092a8
+ .word 0xe1c88289
+ .word 0xe3590002
+ .word 0x33390000
+ .word 0xe2689020
+ .word 0xe1a06912
+ .word 0xe1a02832
+ .word 0xe1822911
+ .word 0xe1a01831
+ .word 0x0a000003
+ .word 0x11866106
+ .word 0x11826126
+ .word 0x11a02001
+ .word 0x13a01000
+ .word 0x3a000004
+ .word 0x21866002
+ .word 0x21866106
+ .word 0x21816126
+ .word 0x23a02000
+ .word 0x23a01000
+ .word 0xe20b5060
+ .word 0xe3855c01
+ .word 0xe3a04000
+ .word 0xebfff86d
+ .word 0xe1b08080
+ .word 0x21e01001
+ .word 0x22722000
+ .word 0x22811001
+ .word 0xe1310fc2
+ .word 0x1a000005
+ .word 0xe1a06002
+ .word 0xe3540000
+ .word 0x11b08aa7
+ .word 0x33877010
+ .word 0x8bfff9fe
+ .word 0xe8bd8000
+ .word 0xe8bd4000
+ .word 0xe3e06102
+ .word 0xe0266fc0
+ .word 0xe3a0800e
+ .word 0xeafffb03
+ .word 0xe1a09883
+ .word 0xe3790802
+ .word 0x30099004
+ .word 0xe0199083
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a000014
+ .word 0xe3190102
+ .word 0x1a000022
+ .word 0xe92d4000
+ .word 0xe0116080
+ .word 0x43c11102
+ .word 0x42800001
+ .word 0xe0146083
+ .word 0x43c44102
+ .word 0x42833001
+ .word 0xe3100101
+ .word 0x11b06880
+ .word 0x1bfffb5d
+ .word 0xe3130101
+ .word 0x11b06883
+ .word 0x1bfffb94
+ .word 0xebfffc24
+ .word 0xe3110102
+ .word 0x18bd8000
+ .word 0xe191e002
+ .word 0x1bfffbd2
+ .word 0xe8bd8000
+ .word 0xe3190102
+ .word 0x0a000009
+ .word 0xe1828081
+ .word 0xe1888005
+ .word 0xe1988084
+ .word 0x1afffa1f
+ .word 0xe023850b
+ .word 0xe0388000
+ .word 0x52008102
+ .word 0x5a00000a
+ .word 0xe3a08004
+ .word 0xeafffabf
+ .word 0xe1928081
+ .word 0x1afffa35
+ .word 0xe2008102
+ .word 0xea000004
+ .word 0xe1958084
+ .word 0x1afffa1b
+ .word 0xe2038102
+ .word 0xe31b0602
+ .word 0x12288102
+ .word 0xe31b0601
+ .word 0x12288102
+ .word 0xe28f0fe6
+ .word 0xe8900007
+ .word 0xe1800008
+ .word 0xe1a0f00e
+ .word 0xe1a09883
+ .word 0xe3790802
+ .word 0x30099004
+ .word 0xe0199083
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a00001f
+ .word 0xe3190102
+ .word 0x1a00002f
+ .word 0xe1918002
+ .word 0x11948005
+ .word 0x0a000013
+ .word 0xe0116080
+ .word 0x43c11102
+ .word 0x42800001
+ .word 0xe0146083
+ .word 0x43c44102
+ .word 0x42833001
+ .word 0xe3c08103
+ .word 0xe3c39103
+ .word 0xe0200003
+ .word 0xe2000102
+ .word 0xe0883009
+ .word 0xe2433c3f
+ .word 0xe24330fe
+ .word 0xe92d4000
+ .word 0xe3110102
+ .word 0x0bfffb98
+ .word 0xe3140102
+ .word 0x0bfffbaf
+ .word 0xe8bd4000
+ .word 0xeafffc50
+ .word 0xe0200003
+ .word 0xe2000102
+ .word 0xe3a01000
+ .word 0xe3a02000
+ .word 0xe3a03000
+ .word 0xe3a06000
+ .word 0xe1a0f00e
+ .word 0xe3190102
+ .word 0x0a000009
+ .word 0xe1828081
+ .word 0xe1888005
+ .word 0xe1988084
+ .word 0x1afff9db
+ .word 0xe0208003
+ .word 0xe2088102
+ .word 0xe28f0fb1
+ .word 0xe8900007
+ .word 0xe1800008
+ .word 0xe1a0f00e
+ .word 0xe1928081
+ .word 0x1afff9f1
+ .word 0xe1948005
+ .word 0x1afffff5
+ .word 0xe3a08005
+ .word 0xeafffa75
+ .word 0xe1958084
+ .word 0x1afff9d5
+ .word 0xe1918002
+ .word 0x1affffef
+ .word 0xe3a08006
+ .word 0xeafffa6f
+ .word 0xe1a09883
+ .word 0xe3790802
+ .word 0x30099004
+ .word 0xe0199083
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a000036
+ .word 0xe3190102
+ .word 0x1a000048
+ .word 0xe1918002
+ .word 0x11948005
+ .word 0x0a00001e
+ .word 0xe31b0601
+ .word 0x1a000008
+ .word 0xe1a08000
+ .word 0xe1a00003
+ .word 0xe1a03008
+ .word 0xe1a08001
+ .word 0xe1a01004
+ .word 0xe1a04008
+ .word 0xe1a08002
+ .word 0xe1a02005
+ .word 0xe1a05008
+ .word 0xe0116080
+ .word 0x43c11102
+ .word 0x42800001
+ .word 0xe0146083
+ .word 0x43c44102
+ .word 0x42833001
+ .word 0xe3c08103
+ .word 0xe3c39103
+ .word 0xe0200003
+ .word 0xe2000102
+ .word 0xe0493008
+ .word 0xe2833c3f
+ .word 0xe28330ff
+ .word 0xe92d4000
+ .word 0xe3110102
+ .word 0x0bfffb7e
+ .word 0xe3140102
+ .word 0x0bfffb63
+ .word 0xe8bd4000
+ .word 0xeafffcaf
+ .word 0xe3a08007
+ .word 0xe31b0601
+ .word 0x1a00000a
+ .word 0xe1919002
+ .word 0x1afffaa5
+ .word 0xe1949005
+ .word 0x0afffa3b
+ .word 0xe0200003
+ .word 0xe2000102
+ .word 0xe3a01000
+ .word 0xe3a02000
+ .word 0xe3a03000
+ .word 0xe3a06000
+ .word 0xe1a0f00e
+ .word 0xe1919002
+ .word 0x1afffff6
+ .word 0xe1949005
+ .word 0x1afffa98
+ .word 0xeafffa2f
+ .word 0xe3190102
+ .word 0x0a000005
+ .word 0xe1828081
+ .word 0xe1888005
+ .word 0xe1988084
+ .word 0x1afff983
+ .word 0xe3a08008
+ .word 0xeafffa27
+ .word 0xe1928081
+ .word 0x1afff99d
+ .word 0xe0208003
+ .word 0xe2088102
+ .word 0xe31b0601
+ .word 0x028f0e15
+ .word 0x128f0d05
+ .word 0xe8900007
+ .word 0xe1800008
+ .word 0xe3a03000
+ .word 0xe3a06000
+ .word 0xe1a0f00e
+ .word 0xe1958084
+ .word 0x1afff97b
+ .word 0xe0208003
+ .word 0xe2088102
+ .word 0xe31b0601
+ .word 0x128f0e12
+ .word 0x028f0e11
+ .word 0xe8900007
+ .word 0xe1800008
+ .word 0xe3a03000
+ .word 0xe3a06000
+ .word 0xe1a0f00e
+ .word 0xe1a09883
+ .word 0xe3790802
+ .word 0x30099004
+ .word 0xe0199083
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a000017
+ .word 0xe3190102
+ .word 0x1a000021
+ .word 0xe1948005
+ .word 0x03a0800a
+ .word 0x0afffa01
+ .word 0xe1916002
+ .word 0x0a00002c
+ .word 0xe0116080
+ .word 0x43c11102
+ .word 0x42800001
+ .word 0xe0146083
+ .word 0x43c44102
+ .word 0x42833001
+ .word 0xe92d4000
+ .word 0xe3c33103
+ .word 0xe3140102
+ .word 0x0bfffb14
+ .word 0xe2439001
+ .word 0xe3c03103
+ .word 0xe3140102
+ .word 0x0bfffaf7
+ .word 0xe0536009
+ .word 0xe1a03009
+ .word 0xeafffd88
+ .word 0xe3190102
+ .word 0x0a000005
+ .word 0xe1828081
+ .word 0xe1888005
+ .word 0xe1988084
+ .word 0x1afff942
+ .word 0xe3a08009
+ .word 0xeafff9e6
+ .word 0xe1928081
+ .word 0x1afff95c
+ .word 0xe3a08009
+ .word 0xeafff9e2
+ .word 0xe1958084
+ .word 0x1afff942
+ .word 0xe3100101
+ .word 0x03c03103
+ .word 0x02000102
+ .word 0x03a06000
+ .word 0x01a0f00e
+ .word 0xe1916002
+ .word 0x0a000006
+ .word 0xe3c03103
+ .word 0xe2000102
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12833001
+ .word 0xe3a06000
+ .word 0xeafffad8
+ .word 0xe2000102
+ .word 0xe3a03000
+ .word 0xe1a0f00e
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x40007fff
+ .word 0x00000000
+ .word 0x00000000
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a000013
+ .word 0xe1918002
+ .word 0x02000102
+ .word 0x0a00000d
+ .word 0xe3c03103
+ .word 0xe2100102
+ .word 0x13a0800b
+ .word 0x1afff95b
+ .word 0xe92d4000
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12833001
+ .word 0xebfffabe
+ .word 0xe2833c3f
+ .word 0xe28330ff
+ .word 0xe1b030a3
+ .word 0xe8bd4000
+ .word 0xeafffd72
+ .word 0xe3a03000
+ .word 0xe3a06000
+ .word 0xe1a0f00e
+ .word 0xe1928081
+ .word 0x1afff921
+ .word 0xe3100102
+ .word 0x13a0800b
+ .word 0x1afff949
+ .word 0xe24f008c
+ .word 0xe8900007
+ .word 0xe1a0f00e
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a00000a
+ .word 0xe1918002
+ .word 0x03a03000
+ .word 0x0afffddd
+ .word 0xe3c03103
+ .word 0xe92d4000
+ .word 0xe0116080
+ .word 0x43c11102
+ .word 0x42833001
+ .word 0xebfffaa0
+ .word 0xe8bd4000
+ .word 0xeafffdd5
+ .word 0xe1928081
+ .word 0x1a000008
+ .word 0xe2008102
+ .word 0xe31b0601
+ .word 0x12288102
+ .word 0xe31b0602
+ .word 0x13c88102
+ .word 0xe24f00f4
+ .word 0xe8900007
+ .word 0xe1800008
+ .word 0xe1a0f00e
+ .word 0xe92d4000
+ .word 0xebfff8d2
+ .word 0xe3360000
+ .word 0x4a000001
+ .word 0xebfff8fa
+ .word 0x18bd8000
+ .word 0xe31b0601
+ .word 0x12200102
+ .word 0xe31b0602
+ .word 0x13c00102
+ .word 0xe8bd8000
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x53c03103
+ .word 0x5afffdc5
+ .word 0xe1928081
+ .word 0x1afff8ed
+ .word 0xe2008102
+ .word 0xe24f0f55
+ .word 0xe8900007
+ .word 0xe1800008
+ .word 0xe1a0f00e
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4afffff3
+ .word 0xe3c06103
+ .word 0xe2000102
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12866001
+ .word 0xeafffdc3
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4affffe8
+ .word 0xe1913002
+ .word 0x02000102
+ .word 0x0afffe2b
+ .word 0xe3c03103
+ .word 0xe2000102
+ .word 0xe92d4000
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12833001
+ .word 0xebfffa61
+ .word 0xe8bd4000
+ .word 0xeafffdd8
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0xe1a09883
+ .word 0xe3790802
+ .word 0x30099004
+ .word 0xe0199083
+ .word 0xe3180102
+ .word 0x11926081
+ .word 0x1a00001b
+ .word 0xe3190102
+ .word 0x11956084
+ .word 0x1a000018
+ .word 0xe92d4000
+ .word 0xe3180102
+ .word 0x12000102
+ .word 0x138000ff
+ .word 0x13800c7f
+ .word 0x13c11102
+ .word 0xe3190102
+ .word 0x12033102
+ .word 0x138330ff
+ .word 0x13833c7f
+ .word 0x13c44102
+ .word 0xe0116080
+ .word 0x43c11102
+ .word 0x42800001
+ .word 0xe0146083
+ .word 0x43c44102
+ .word 0x42833001
+ .word 0xe3100101
+ .word 0x11b06880
+ .word 0x1bfff9c0
+ .word 0xe3130101
+ .word 0x11b06883
+ .word 0x1bfff9f7
+ .word 0xe8bd4000
+ .word 0xeafffe00
+ .word 0xe3170a01
+ .word 0x03a06201
+ .word 0x13a06203
+ .word 0xe3180102
+ .word 0x11928081
+ .word 0x0a000004
+ .word 0xe2118101
+ .word 0x0afff950
+ .word 0xe3190102
+ .word 0x11958084
+ .word 0x0a000001
+ .word 0xe2148101
+ .word 0x0afff94b
+ .word 0xe31b0501
+ .word 0x01a0f00e
+ .word 0xe3a0800f
+ .word 0xeafff947
+ .word 0xe3100101
+ .word 0x0afffe05
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a000005
+ .word 0xe3c06103
+ .word 0xe2000102
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12866001
+ .word 0xeafffdfc
+ .word 0xe3110101
+ .word 0x03a08000
+ .word 0x13a0800c
+ .word 0xe1926081
+ .word 0x03a0800d
+ .word 0xe3a06102
+ .word 0xeafff927
+ .word 0xedd8a200
+ .word 0xee181102
+ .word 0xee106111
+ .word 0xee308110
+ .word 0xe3180005
+ .word 0x0e016110
+ .word 0x0e192103
+ .word 0x0e280102
+ .word 0x0e192104
+ .word 0x0e280102
+ .word 0xe1a0f009
+ .word 0xecb8a203
+ .word 0xe2466001
+ .word 0xecb8b203
+ .word 0xee1a2101
+ .word 0xee0a2103
+ .word 0xe2566001
+ .word 0x1afffffa
+ .word 0xee1a2101
+ .word 0xe1a0f009
+ .word 0xecb8b203
+ .word 0xee094103
+ .word 0xe2566001
+ .word 0x01a0f009
+ .word 0xecb8b203
+ .word 0xee1c4101
+ .word 0xee0c4103
+ .word 0xe2566001
+ .word 0x1afffffa
+ .word 0xe1a0f009
+ .word 0xee08a109
+ .word 0xee108111
+ .word 0xe0389048
+ .word 0xe2a99000
+ .word 0xe3a06902
+ .word 0xe1190006
+ .word 0x01a060a6
+ .word 0x0afffffc
+ .word 0xe3580000
+ .word 0xba00000e
+ .word 0xea000002
+ .word 0xee1a2102
+ .word 0xe1190086
+ .word 0x1e1a2100
+ .word 0xe1b060a6
+ .word 0x1afffffa
+ .word 0xee1a3102
+ .word 0xe3190001
+ .word 0x0e1a2162
+ .word 0x1e1b2160
+ .word 0x1e1b3100
+ .word 0xea000009
+ .word 0xee1a2102
+ .word 0xe1190086
+ .word 0x1e4a2100
+ .word 0xe1b060a6
+ .word 0x1afffffa
+ .word 0xee1a3102
+ .word 0xe3190001
+ .word 0x0e1a2162
+ .word 0x1e4b2160
+ .word 0x1e4b3100
+ .word 0xee308110
+ .word 0xe318000c
+ .word 0x1a0001b7
+ .word 0xee92f113
+ .word 0x03a06101
+ .word 0x13a06103
+ .word 0xe3180010
+ .word 0x03a06000
+ .word 0xee088102
+ .word 0xea00010c
+ .word 0x80003ffe
+ .word 0xca20ad9a
+ .word 0xb5e946e9
+ .word 0x00004003
+ .word 0x83125100
+ .word 0xb57f6509
+ .word 0x80004005
+ .word 0x803ff895
+ .word 0x9dacd228
+ .word 0x80004004
+ .word 0x8eac025b
+ .word 0x3e7076bb
+ .word 0x00004007
+ .word 0x9c041fd0
+ .word 0xa933ef60
+ .word 0x80004008
+ .word 0xc05ff4e0
+ .word 0x6c83bb96
+ .word 0x00003ffe
+ .word 0xb17217f7
+ .word 0xd1cf0000
+ .word 0x00003fcd
+ .word 0xf35793c0
+ .word 0x00000000
+ .word 0x00003ffe
+ .word 0xb504f333
+ .word 0xf9de6484
+ .word 0x00003ffd
+ .word 0xde5bd8a9
+ .word 0x37287195
+ .word 0xe3100101
+ .word 0x1a000079
+ .word 0xe1918002
+ .word 0x0afff8eb
+ .word 0xe3100102
+ .word 0x13a08018
+ .word 0x1afff83e
+ .word 0xe3c03103
+ .word 0xe3a00c3f
+ .word 0xe38000fe
+ .word 0xe0433000
+ .word 0xe92d4000
+ .word 0xe24dd04c
+ .word 0xe1a09407
+ .word 0xe389901f
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d9040
+ .word 0xed09020f
+ .word 0xed09c203
+ .word 0xe8890007
+ .word 0xed998200
+ .word 0xe31b0601
+ .word 0x0a000011
+ .word 0xe2838001
+ .word 0xe0889108
+ .word 0xe0689109
+ .word 0xe1a09349
+ .word 0xe359001c
+ .word 0x2a000010
+ .word 0xe24f8b0b
+ .word 0xe2488feb
+ .word 0xe0888209
+ .word 0xe8980130
+ .word 0xe1320008
+ .word 0x01310005
+ .word 0x00444003
+ .word 0x01300004
+ .word 0x1a000007
+ .word 0xe3a06000
+ .word 0xee019110
+ .word 0xea00003e
+ .word 0xe3530001
+ .word 0x0e90f11e
+ .word 0x03a06000
+ .word 0x0e089108
+ .word 0x0a000039
+ .word 0xed5f113d
+ .word 0xee90f111
+ .word 0xd2433001
+ .word 0xde28010e
+ .word 0xee18110e
+ .word 0xee09110e
+ .word 0xce280109
+ .word 0xee480101
+ .word 0xee181100
+ .word 0xe24f8f5e
+ .word 0xe3a06003
+ .word 0xe1a0900f
+ .word 0xeaffff62
+ .word 0xe24f8f59
+ .word 0xe3a06003
+ .word 0xe1a0900f
+ .word 0xeaffff67
+ .word 0xee4a2104
+ .word 0xee1a1100
+ .word 0xee091100
+ .word 0xe3330000
+ .word 0x1a000008
+ .word 0xe31b0601
+ .word 0x1a000017
+ .word 0xee1a2160
+ .word 0xee0a0160
+ .word 0xee91f110
+ .word 0x03a06101
+ .word 0x13a06103
+ .word 0x1e089100
+ .word 0xea00001a
+ .word 0xee083110
+ .word 0xed5f2263
+ .word 0xee1a2100
+ .word 0xee1b3100
+ .word 0xee090102
+ .word 0xee282102
+ .word 0xee2a2101
+ .word 0xee0a2103
+ .word 0xee081102
+ .word 0xe31b0601
+ .word 0x1a000005
+ .word 0xee080162
+ .word 0xee91f110
+ .word 0x03a06101
+ .word 0x13a06103
+ .word 0x1e089100
+ .word 0xea000009
+ .word 0xee08a101
+ .word 0xed5f016b
+ .word 0xee181162
+ .word 0xe3a06101
+ .word 0xe31b00e0
+ .word 0x1a000003
+ .word 0xe31b0702
+ .word 0x1e180102
+ .word 0x1e90f111
+ .word 0x13a06103
+ .word 0xe28d9040
+ .word 0xed899200
+ .word 0xe8990007
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c03103
+ .word 0xe2000102
+ .word 0xe8bd8000
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a00000c
+ .word 0xe1918002
+ .word 0x0afff86c
+ .word 0xe3c03103
+ .word 0xe3100102
+ .word 0x13a08018
+ .word 0x1afff7be
+ .word 0xe92d4000
+ .word 0xe3110102
+ .word 0x13c11102
+ .word 0x12833001
+ .word 0xebfff921
+ .word 0xe8bd4000
+ .word 0xeaffff79
+ .word 0xe1928081
+ .word 0x1afff78a
+ .word 0xe3100102
+ .word 0x13a08018
+ .word 0x1afff7b2
+ .word 0xe24f0b01
+ .word 0xe2400fba
+ .word 0xe8900007
+ .word 0xe1a0f00e
+ .word 0x00003fff
+ .word 0xb8aa3b29
+ .word 0x5c17f0bc
+ .word 0x00003ffe
+ .word 0xb1800000
+ .word 0x00000000
+ .word 0x80003ff2
+ .word 0xde8082e3
+ .word 0x08654362
+ .word 0x00003ff1
+ .word 0x845a2157
+ .word 0x3490f106
+ .word 0x00003ff8
+ .word 0xf83a5f91
+ .word 0x50952c99
+ .word 0x00003feb
+ .word 0xc99b1867
+ .word 0x2822a93e
+ .word 0x00003ff5
+ .word 0xa57862e1
+ .word 0x46a6fb39
+ .word 0x00003ffb
+ .word 0xe8b9428e
+ .word 0xfecff592
+ .word 0x00003fbd
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00003ffd
+ .word 0xffffffff
+ .word 0xffffffff
+ .word 0xe3100101
+ .word 0x1a00005f
+ .word 0xe1916002
+ .word 0x0a00005a
+ .word 0xe1a05000
+ .word 0xe92d4000
+ .word 0xe24dd04c
+ .word 0xe1a09407
+ .word 0xe389901f
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d9040
+ .word 0xed09020f
+ .word 0xed09c203
+ .word 0xe8890007
+ .word 0xed998200
+ .word 0xe3a04000
+ .word 0xe24f80dc
+ .word 0xe1a0900f
+ .word 0xeafffeca
+ .word 0x02868801
+ .word 0x01b088a8
+ .word 0x1a000030
+ .word 0xe2866001
+ .word 0xe1844086
+ .word 0xed5f1127
+ .word 0xee28a100
+ .word 0xee92f111
+ .word 0xba000024
+ .word 0xee181100
+ .word 0xe24f80d4
+ .word 0xe3a06003
+ .word 0xe1a0900f
+ .word 0xeafffec7
+ .word 0xee0a4109
+ .word 0xe24f8c01
+ .word 0xe3a06002
+ .word 0xe1a0900f
+ .word 0xeafffec2
+ .word 0xee0a210e
+ .word 0xee1a2100
+ .word 0xee2c4102
+ .word 0xee4a1104
+ .word 0xee09016e
+ .word 0xe3a06101
+ .word 0xe31b00e0
+ .word 0x1a000004
+ .word 0xe31b0702
+ .word 0x0a000002
+ .word 0xee09110e
+ .word 0xee90f111
+ .word 0x13a06103
+ .word 0xe28d9040
+ .word 0xed898200
+ .word 0xe8990007
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c03103
+ .word 0xe08330c4
+ .word 0xe1a00f84
+ .word 0xe8bd8000
+ .word 0xee90f118
+ .word 0xae08810e
+ .word 0xa3a06101
+ .word 0xbd5f0150
+ .word 0xb3a06103
+ .word 0xeaffffeb
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe28f0b01
+ .word 0xe2800f05
+ .word 0xe8900007
+ .word 0xe1800f84
+ .word 0xe3a03601
+ .word 0xe3150102
+ .word 0x12633000
+ .word 0xe3a06101
+ .word 0xe8bd8000
+ .word 0xe28f0e3f
+ .word 0xe890000f
+ .word 0xe1a0f00e
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x5affff9a
+ .word 0xe1928081
+ .word 0x1afff6fc
+ .word 0xe3a04000
+ .word 0xe3100102
+ .word 0x024f0b02
+ .word 0x02400f47
+ .word 0x08900007
+ .word 0x13a00000
+ .word 0x13a01000
+ .word 0x13a03000
+ .word 0x13a06000
+ .word 0xe1800f84
+ .word 0xe1a0f00e
+ .word 0xe92d4000
+ .word 0xe24dd04c
+ .word 0xe1a09407
+ .word 0xe389901f
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d9040
+ .word 0xed09020f
+ .word 0xed09c203
+ .word 0xe31b0601
+ .word 0xe8890007
+ .word 0x0d998200
+ .word 0x1d999200
+ .word 0xe8890038
+ .word 0x0d999200
+ .word 0x1d998200
+ .word 0xe3100101
+ .word 0x03130101
+ .word 0x1a000096
+ .word 0xeee8a101
+ .word 0xeef8a102
+ .word 0xee91f112
+ .word 0x1a000044
+ .word 0xe31b0601
+ .word 0x01a08fa0
+ .word 0x11a08fa3
+ .word 0xe3180001
+ .word 0x1e19210e
+ .word 0x1ee8b102
+ .word 0x1ef8b103
+ .word 0x1e92f113
+ .word 0x03a08000
+ .word 0xee91f118
+ .word 0xca000002
+ .word 0x0a000069
+ .word 0xee90f118
+ .word 0x0a000026
+ .word 0xee90f118
+ .word 0xbe188100
+ .word 0x0a000015
+ .word 0xee90f119
+ .word 0x0a000006
+ .word 0xe1a04008
+ .word 0xe28f9fbd
+ .word 0xedd92100
+ .word 0xee92f111
+ .word 0xceb2f111
+ .word 0xcafffe58
+ .word 0xea000032
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe28f0e2a
+ .word 0xe890000f
+ .word 0xe1800f88
+ .word 0xe3a06000
+ .word 0xe8bd8000
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe1a00f88
+ .word 0xe3a01000
+ .word 0xe3a02000
+ .word 0xe3a03000
+ .word 0xe3a06000
+ .word 0xe8bd8000
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3170802
+ .word 0x1afff793
+ .word 0xe3877002
+ .word 0xe24f0b02
+ .word 0xe2400fad
+ .word 0xe8900007
+ .word 0xe1800f88
+ .word 0xe8bd8000
+ .word 0xee90f118
+ .word 0xb3a08019
+ .word 0xba000107
+ .word 0x0a000038
+ .word 0xee90f119
+ .word 0x1e91f118
+ .word 0x0a000021
+ .word 0xe3a04000
+ .word 0xee688100
+ .word 0xee180101
+ .word 0xe28d8040
+ .word 0xed888200
+ .word 0xe5985000
+ .word 0xee309110
+ .word 0xe3190004
+ .word 0x1affff67
+ .word 0xee90f118
+ .word 0x0a000010
+ .word 0xe24f8b02
+ .word 0xe2488e31
+ .word 0xedd81100
+ .word 0xee90f111
+ .word 0x1eb0f111
+ .word 0x1affff28
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe8bd4000
+ .word 0xe1a00005
+ .word 0xeaffff70
+ .word 0xe3150102
+ .word 0x0e088109
+ .word 0x03a06101
+ .word 0x1ddf0163
+ .word 0x13a06103
+ .word 0xeaffff3a
+ .word 0xe24f8b02
+ .word 0xe2488fdb
+ .word 0xedd82100
+ .word 0xee90f112
+ .word 0x1e91f112
+ .word 0x1eb1f112
+ .word 0x03a0801b
+ .word 0x0a0000d9
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe28f0e13
+ .word 0xe890000f
+ .word 0xe3a06000
+ .word 0xe8bd8000
+ .word 0xee91f118
+ .word 0xd3a0801a
+ .word 0xda0000ca
+ .word 0xe28d9040
+ .word 0xed898200
+ .word 0xe8990007
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe2000102
+ .word 0xe3a03000
+ .word 0xe3a06000
+ .word 0xe8bd8000
+ .word 0xe1a09883
+ .word 0xe3790802
+ .word 0x30099004
+ .word 0xe0199083
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a000010
+ .word 0xe3190102
+ .word 0x0affff5d
+ .word 0xe1958084
+ .word 0x1a000002
+ .word 0xe31b0601
+ .word 0x0affffa2
+ .word 0xeaffff58
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe8bd4000
+ .word 0xeafff616
+ .word 0xe3190102
+ .word 0x0a00000d
+ .word 0xe1828081
+ .word 0xe1888005
+ .word 0xe1988084
+ .word 0x0affff91
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe8bd4000
+ .word 0xeafff5fe
+ .word 0xe1928081
+ .word 0x1a000002
+ .word 0xe31b0601
+ .word 0x1affff83
+ .word 0xeaffff39
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe8bd4000
+ .word 0xeafff60d
+ .word 0x00000000
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00003fff
+ .word 0x00003ffe
+ .word 0xffffffff
+ .word 0xffffffff
+ .word 0x0000400f
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00003ffd
+ .word 0xa2f9836e
+ .word 0x4e44152a
+ .word 0x00004000
+ .word 0xc9100000
+ .word 0x00000000
+ .word 0x80003fee
+ .word 0x95777a5c
+ .word 0xf72cece6
+ .word 0x00003fce
+ .word 0xc407fb4c
+ .word 0x9efca5fe
+ .word 0x80003fd6
+ .word 0xd72106e0
+ .word 0x424cdf56
+ .word 0x00003fde
+ .word 0xb091e343
+ .word 0x56a17fa8
+ .word 0x80003fe5
+ .word 0xd7322a5a
+ .word 0xee055b44
+ .word 0x00003fec
+ .word 0xb8ef1d29
+ .word 0x27831824
+ .word 0x80003ff2
+ .word 0xd00d00d0
+ .word 0x09f0d114
+ .word 0x00003ff8
+ .word 0x88888888
+ .word 0x88858061
+ .word 0x80003ffc
+ .word 0xaaaaaaaa
+ .word 0xaaaaa603
+ .word 0xe3100101
+ .word 0x1a00004d
+ .word 0xe1916002
+ .word 0x0a000043
+ .word 0xe92d4000
+ .word 0xe24dd04c
+ .word 0xe1a09407
+ .word 0xe389901f
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d9040
+ .word 0xed09020f
+ .word 0xed09c203
+ .word 0xe8890007
+ .word 0xed998200
+ .word 0xee90f118
+ .word 0xe0a44004
+ .word 0xbe188100
+ .word 0xe31b0601
+ .word 0x1ddf1172
+ .word 0x1e080101
+ .word 0x13a04001
+ .word 0xe24f80fc
+ .word 0xe1a0900f
+ .word 0xeafffd3d
+ .word 0x13a08010
+ .word 0x1a000037
+ .word 0xe0244006
+ .word 0xee90f118
+ .word 0xbe188100
+ .word 0xa2244001
+ .word 0xeddf1169
+ .word 0xee90f111
+ .word 0xba00001b
+ .word 0xee181100
+ .word 0xe24f8f43
+ .word 0xe3a06008
+ .word 0xe1a0900f
+ .word 0xeafffd3a
+ .word 0xee1a1140
+ .word 0xee091140
+ .word 0xe3a06101
+ .word 0xe31b00e0
+ .word 0x1a000004
+ .word 0xe31b0702
+ .word 0x1e1a2100
+ .word 0x1e0a0100
+ .word 0x1e90f111
+ .word 0x13a06103
+ .word 0xe28d9040
+ .word 0xed899200
+ .word 0xe8990007
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe1a03000
+ .word 0xe1a00f84
+ .word 0xe8bd8000
+ .word 0xed5f116d
+ .word 0xee181161
+ .word 0xe3a06103
+ .word 0xeaffffee
+ .word 0xe31b0601
+ .word 0x1a000002
+ .word 0xe2000102
+ .word 0xe3a03000
+ .word 0xe1a0f00e
+ .word 0xe24f0f7a
+ .word 0xe890000f
+ .word 0xe1a0f00e
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x5affffac
+ .word 0xe1928081
+ .word 0x1afff586
+ .word 0xe3a08011
+ .word 0xeafff5af
+ .word 0xe28d9040
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe8bd4000
+ .word 0xeafff5a5
+ .word 0x80003ffe
+ .word 0xb25dedaf
+ .word 0x30f3242c
+ .word 0x00004002
+ .word 0xa270bb27
+ .word 0x61c93957
+ .word 0x80004004
+ .word 0x9ec1654d
+ .word 0x36d4f820
+ .word 0x00004004
+ .word 0xe4d539b0
+ .word 0x56a451ad
+ .word 0x80004003
+ .word 0xdaf2ad41
+ .word 0xd05311c4
+ .word 0x80004003
+ .word 0xbe974377
+ .word 0xcc30f9e6
+ .word 0x00004006
+ .word 0x96f3e4b2
+ .word 0xc8e37cbc
+ .word 0x80004007
+ .word 0xbeee77e2
+ .word 0xb5423cf3
+ .word 0x00004007
+ .word 0xd0927880
+ .word 0xf5c2170b
+ .word 0x80004006
+ .word 0xa43601f1
+ .word 0x5c3e6196
+ .word 0x00003fff
+ .word 0xc90fdaa2
+ .word 0x2168c234
+ .word 0x00003fbf
+ .word 0xc4c68000
+ .word 0x00000000
+ .word 0x00004000
+ .word 0xc90fdaa2
+ .word 0x2168c234
+ .word 0x00003fc0
+ .word 0xc4c68000
+ .word 0x00000000
+ .word 0x00003fff
+ .word 0xc90fdaa2
+ .word 0x2168c235
+ .word 0x00003fdf
+ .word 0x80000000
+ .word 0x00000000
+ .word 0xe3100101
+ .word 0x1a000075
+ .word 0xe31b0501
+ .word 0x01916002
+ .word 0x0a00006f
+ .word 0xe92d4000
+ .word 0xe24dd04c
+ .word 0xe1a09407
+ .word 0xe389901f
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d9040
+ .word 0xed09020f
+ .word 0xed09c203
+ .word 0xe8890007
+ .word 0xed998200
+ .word 0xee90f118
+ .word 0xe0a44004
+ .word 0xbe188100
+ .word 0xee90f11e
+ .word 0xba000044
+ .word 0xee90f119
+ .word 0xba000004
+ .word 0xc3a08014
+ .word 0xcaffffa6
+ .word 0xe31b0501
+ .word 0x13140001
+ .word 0x1a00004f
+ .word 0xe3a0520d
+ .word 0xe3140001
+ .word 0x13a05103
+ .word 0xe31b0501
+ .word 0x13a0520e
+ .word 0x13140001
+ .word 0x13a05000
+ .word 0xee381109
+ .word 0xee19110e
+ .word 0xee488101
+ .word 0xee080100
+ .word 0xe24f8f5f
+ .word 0xe3a06005
+ .word 0xe1a0900f
+ .word 0xeafffca3
+ .word 0xe24f8e15
+ .word 0xe3a06005
+ .word 0xe1a0900f
+ .word 0xeafffca8
+ .word 0xee4a2104
+ .word 0xe3150102
+ .word 0x1e188100
+ .word 0xee1a1100
+ .word 0xee091100
+ .word 0xe1b04105
+ .word 0x2a000006
+ .word 0xee1a2160
+ .word 0xee0a0160
+ .word 0xee91f110
+ .word 0x03a06101
+ .word 0x13a06103
+ .word 0x1e089100
+ .word 0xea00000d
+ .word 0x5d5f2257
+ .word 0x4d5f2252
+ .word 0xee090102
+ .word 0xee282102
+ .word 0xee2a2101
+ .word 0xee0a2103
+ .word 0xee081162
+ .word 0xe3a06101
+ .word 0xe31b00e0
+ .word 0x1a000003
+ .word 0xe31b0702
+ .word 0x1e080102
+ .word 0x1e90f111
+ .word 0x13a06103
+ .word 0xe3150201
+ .word 0x1e189101
+ .word 0xe28d9040
+ .word 0xed899200
+ .word 0xe8990007
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c03103
+ .word 0xe2000102
+ .word 0xe8bd8000
+ .word 0xe3a05201
+ .word 0xe3140001
+ .word 0x13a05000
+ .word 0xe31b0501
+ .word 0x13a05101
+ .word 0x13140001
+ .word 0x13a05103
+ .word 0xed5f116c
+ .word 0xee90f111
+ .word 0xae181100
+ .word 0xaaffffc1
+ .word 0xe3150102
+ .word 0x1e188100
+ .word 0xee089100
+ .word 0xe1b04105
+ .word 0x2affffd2
+ .word 0xe3a06101
+ .word 0xeaffffde
+ .word 0xee089108
+ .word 0xe3a06000
+ .word 0xeaffffdd
+ .word 0xe2000102
+ .word 0xe3a03000
+ .word 0xe1a0f00e
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x5affff84
+ .word 0xe1928081
+ .word 0x1afff4cb
+ .word 0xe3a08015
+ .word 0xeafff4f4
+ .word 0x00003ffe
+ .word 0xa2f9836e
+ .word 0x4e44152a
+ .word 0x00003fff
+ .word 0xc9100000
+ .word 0x00000000
+ .word 0x80003fed
+ .word 0x95777a5c
+ .word 0xf72cece6
+ .word 0x80003fef
+ .word 0x95d5b975
+ .word 0x16391da8
+ .word 0x00003ff6
+ .word 0xe0741531
+ .word 0xdd56f650
+ .word 0x80003ffc
+ .word 0x8895af2a
+ .word 0x6847fcd5
+ .word 0x00003fea
+ .word 0x85bba783
+ .word 0xb3c748a9
+ .word 0x80003ff3
+ .word 0xa37b24c8
+ .word 0x4a42092e
+ .word 0x00003ff9
+ .word 0xd23cf50b
+ .word 0xf10aca84
+ .word 0x80003ffd
+ .word 0xeef5823f
+ .word 0xdecea969
+ .word 0x00000000
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00003ffe
+ .word 0xffffffff
+ .word 0xffffffff
+ .word 0x00005fff
+ .word 0x80000000
+ .word 0x00000000
+ .word 0xe3100101
+ .word 0x1a00005c
+ .word 0xe1916002
+ .word 0x0a000057
+ .word 0xe92d4000
+ .word 0xe24dd04c
+ .word 0xe1a09407
+ .word 0xe389901f
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d9040
+ .word 0xed09020f
+ .word 0xed09c203
+ .word 0xe8890007
+ .word 0xed998200
+ .word 0xe24f80f8
+ .word 0xe1a0900f
+ .word 0xeafffc09
+ .word 0x13a08012
+ .word 0x1affff03
+ .word 0xe1a04006
+ .word 0xeddf1163
+ .word 0xee28a100
+ .word 0xee92f111
+ .word 0xba000028
+ .word 0xee181100
+ .word 0xe24f8c01
+ .word 0xe3a06003
+ .word 0xe1a0900f
+ .word 0xeafffc08
+ .word 0xee0a2109
+ .word 0xee184102
+ .word 0xe24f80f4
+ .word 0xe3a06004
+ .word 0xe1a0900f
+ .word 0xeafffc02
+ .word 0xee0a2109
+ .word 0xe3140001
+ .word 0x0e4c0142
+ .word 0x1e18c104
+ .word 0x1e4a0144
+ .word 0xe3a06101
+ .word 0xe31b00e0
+ .word 0x1a000006
+ .word 0xe31b0702
+ .word 0x0a000004
+ .word 0xe3140001
+ .word 0x0e4c1102
+ .word 0x1e4a1104
+ .word 0xee90f111
+ .word 0x13a06103
+ .word 0xe3a04000
+ .word 0xe28d9040
+ .word 0xed898200
+ .word 0xe8990007
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd04c
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c03103
+ .word 0xe0833004
+ .word 0xe2000102
+ .word 0xe8bd8000
+ .word 0xed5fa253
+ .word 0xee289100
+ .word 0xe3140001
+ .word 0x1a000006
+ .word 0xe3a06101
+ .word 0xee91f112
+ .word 0xaaffffe9
+ .word 0xee180104
+ .word 0xe3a04a02
+ .word 0xe2644000
+ .word 0xeaffffe6
+ .word 0xe3a06103
+ .word 0xee91f112
+ .word 0xbe180104
+ .word 0xee188100
+ .word 0xee580109
+ .word 0xee180163
+ .word 0xaaffffde
+ .word 0xe3a04a02
+ .word 0xeaffffdd
+ .word 0xe2000102
+ .word 0xe3a03000
+ .word 0xe1a0f00e
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x5affff9d
+ .word 0xe1928081
+ .word 0x1afff43c
+ .word 0xe3a08013
+ .word 0xeafff465
+ .word 0x80003ffe
+ .word 0xd66bd6cd
+ .word 0x8c3de934
+ .word 0x80004002
+ .word 0x87e9fae4
+ .word 0x6b531a29
+ .word 0x80004003
+ .word 0xa40bfdcf
+ .word 0x15e65691
+ .word 0x80004002
+ .word 0xdb053288
+ .word 0x30e70eb4
+ .word 0x00004002
+ .word 0xf0624f0a
+ .word 0x56388310
+ .word 0x00004004
+ .word 0xee505190
+ .word 0x6d1eb4e8
+ .word 0x00004005
+ .word 0xac509020
+ .word 0x5b6d243b
+ .word 0x00004004
+ .word 0xa443e5e6
+ .word 0x24ad4b90
+ .word 0x00003fdf
+ .word 0x80000000
+ .word 0x00000000
+ .word 0x00003ffe
+ .word 0xffffffff
+ .word 0xffffffff
+ .word 0x00003ffd
+ .word 0x8930a2f4
+ .word 0xf66ab18a
+ .word 0x00003ffe
+ .word 0x860a91c1
+ .word 0x6b9b2c23
+ .word 0x00003fbc
+ .word 0xb766aaaa
+ .word 0xaaaaaaab
+ .word 0x00003fff
+ .word 0x860a91c1
+ .word 0x6b9b2c23
+ .word 0x00003fbd
+ .word 0xb766aaaa
+ .word 0xaaaaaaab
+ .word 0x00003fff
+ .word 0xc90fdaa2
+ .word 0x2168c234
+ .word 0x00003fbf
+ .word 0xc4c68000
+ .word 0x00000000
+ .word 0x00003fff
+ .word 0xc90fdaa2
+ .word 0x2168c234
+ .word 0x00003fbf
+ .word 0xc4c68000
+ .word 0x00000000
+ .word 0x00004000
+ .word 0x860a91c1
+ .word 0x6b9b2c23
+ .word 0x00003fbe
+ .word 0xb766aaaa
+ .word 0xaaaaaaab
+ .word 0x00004000
+ .word 0xa78d3631
+ .word 0xc681f72b
+ .word 0x00003fc0
+ .word 0xd6ecd555
+ .word 0x55555555
+ .word 0x00004000
+ .word 0xc90fdaa2
+ .word 0x2168c234
+ .word 0x00003fc0
+ .word 0xc4c68000
+ .word 0x00000000
+ .word 0xe3100101
+ .word 0x03130101
+ .word 0x1a00008b
+ .word 0xe1946005
+ .word 0x1a000005
+ .word 0xe1918002
+ .word 0x03a08016
+ .word 0x0afff474
+ .word 0xe3100102
+ .word 0x01a00003
+ .word 0x0a00007e
+ .word 0xe2036102
+ .word 0xe3100102
+ .word 0x12266007
+ .word 0xe3c00102
+ .word 0xe3c33102
+ .word 0xe92d4000
+ .word 0xe24dd058
+ .word 0xe1a09407
+ .word 0xe389901f
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d9040
+ .word 0xed09020f
+ .word 0xed09c203
+ .word 0xe889003f
+ .word 0xedd90200
+ .word 0xe1a05006
+ .word 0xee490100
+ .word 0xea000016
+ .word 0xe3100101
+ .word 0x1a000083
+ .word 0xe1916002
+ .word 0x0a000061
+ .word 0xe2005102
+ .word 0xe3c00102
+ .word 0xe92d4000
+ .word 0xe24dd058
+ .word 0xe1a09407
+ .word 0xe389901f
+ .word 0xe58d9000
+ .word 0xe10f9000
+ .word 0xe3899080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c7981f
+ .word 0xe3c9901f
+ .word 0xee209110
+ .word 0xe28d9040
+ .word 0xed09020f
+ .word 0xed09c203
+ .word 0xe8890007
+ .word 0xed998200
+ .word 0xee90f119
+ .word 0xce580109
+ .word 0xc2255003
+ .word 0xed5f116d
+ .word 0xee90f111
+ .word 0xda000007
+ .word 0xee393109
+ .word 0xee182103
+ .word 0xee2a2109
+ .word 0xee0a2100
+ .word 0xee39110a
+ .word 0xee091100
+ .word 0xee4a0101
+ .word 0xe2255001
+ .word 0xed5f217e
+ .word 0xee289100
+ .word 0xeed1f112
+ .word 0xba000035
+ .word 0xee181100
+ .word 0xe24f8f9b
+ .word 0xe3a06004
+ .word 0xe1a0900f
+ .word 0xeafffb27
+ .word 0xe24f8f93
+ .word 0xe3a06004
+ .word 0xe1a0900f
+ .word 0xeafffb2c
+ .word 0xee4a2104
+ .word 0xee1a1100
+ .word 0xee091100
+ .word 0xe3150002
+ .word 0x1e189101
+ .word 0xe3150007
+ .word 0x1a000006
+ .word 0xee1a2160
+ .word 0xee0a0160
+ .word 0xee91f110
+ .word 0x03a06101
+ .word 0x13a06103
+ .word 0x1e089100
+ .word 0xea00000f
+ .word 0xe24f8f96
+ .word 0xe0859085
+ .word 0xe0888189
+ .word 0xedd82200
+ .word 0xee090102
+ .word 0xee282102
+ .word 0xee2a2101
+ .word 0xee0a2103
+ .word 0xee081162
+ .word 0xe3a06101
+ .word 0xe31b00e0
+ .word 0x1a000003
+ .word 0xe31b0702
+ .word 0x1e080102
+ .word 0x1e90f111
+ .word 0x13a06103
+ .word 0xe3150102
+ .word 0x1e189101
+ .word 0xe28d9040
+ .word 0xed899200
+ .word 0xe8990007
+ .word 0xed19020f
+ .word 0xed19c203
+ .word 0xe28dd058
+ .word 0xe10f9000
+ .word 0xe3c99080
+ .word 0xe129f009
+ .word 0xe1a00000
+ .word 0xe3c03103
+ .word 0xe2000102
+ .word 0xe8bd8000
+ .word 0xe3150007
+ .word 0x1e089100
+ .word 0x1affffd2
+ .word 0xed5f11b8
+ .word 0xee191160
+ .word 0xe3a06103
+ .word 0xeaffffe9
+ .word 0xe3a01000
+ .word 0xe3a02000
+ .word 0xe2000102
+ .word 0xe3a03000
+ .word 0xe1a0f00e
+ .word 0xe1a09883
+ .word 0xe3790802
+ .word 0x30099004
+ .word 0xe0199083
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x4a000005
+ .word 0xe3190102
+ .word 0x0affff68
+ .word 0xe1958084
+ .word 0x1afff342
+ .word 0xe3a04102
+ .word 0xeaffff64
+ .word 0xe3190102
+ .word 0x0a000005
+ .word 0xe1828081
+ .word 0xe1888005
+ .word 0xe1988084
+ .word 0x1afff332
+ .word 0xe3a08017
+ .word 0xeafff3d6
+ .word 0xe1928081
+ .word 0x1afff34c
+ .word 0xe3a01102
+ .word 0xeaffff58
+ .word 0xe1a08880
+ .word 0xe3780802
+ .word 0x30088001
+ .word 0xe0188080
+ .word 0x5affff76
+ .word 0xe1928081
+ .word 0x1afff33e
+ .word 0xe3a01102
+ .word 0xeaffff72
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0x00000000
+ .word 0xe59a2080
+ .word 0xe3320000
+ .word 0x5a00002b
+ .word 0xe92d4000
+ .word 0xeb00017d
+ .word 0xe8bd0004
+ .word 0xe8bd4000
+ .word 0xe5922000
+ .word 0xe132000a
+ .word 0x0e502110
+ .word 0xe59a2084
+ .word 0xe3c22b01
+ .word 0xe58a2084
+ .word 0xe24f2b1b
+ .word 0xe2422f2a
+ .word 0xe24f3d01
+ .word 0xe2433f05
+ .word 0xe1510002
+ .word 0xa1530001
+ .word 0xb1a0f00e
+ .word 0xe590103c
+ .word 0xe1510002
+ .word 0xa1530001
+ .word 0xb1a0f00e
+ .word 0xe2804044
+ .word 0xe5145004
+ .word 0xe3150001
+ .word 0x1cb48203
+ .word 0xe3150002
+ .word 0x1cb49203
+ .word 0xe3150004
+ .word 0x1cb4a203
+ .word 0xe3150008
+ .word 0x1cb4b203
+ .word 0xe3150010
+ .word 0x1cb4c203
+ .word 0xe3150020
+ .word 0x1cb4d203
+ .word 0xe3150040
+ .word 0x1cb4e203
+ .word 0xe3150080
+ .word 0x1cb4f203
+ .word 0xe1a052a5
+ .word 0xe3855481
+ .word 0xee205110
+ .word 0xe5900030
+ .word 0xeaffffe4
+ .word 0xe24f2a06
+ .word 0xe2422ed3
+ .word 0xe24f3d03
+ .word 0xe2433f07
+ .word 0xe1510002
+ .word 0xa1530001
+ .word 0xb1a0f00e
+ .word 0xe590103c
+ .word 0xe1510002
+ .word 0xa1530001
+ .word 0xb1a0f00e
+ .word 0xe28a3000
+ .word 0xe2804044
+ .word 0xe5145004
+ .word 0xe3150001
+ .word 0x18b400c2
+ .word 0x188300c2
+ .word 0xe2833010
+ .word 0xe3150002
+ .word 0x18b400c2
+ .word 0x188300c2
+ .word 0xe2833010
+ .word 0xe3150004
+ .word 0x18b400c2
+ .word 0x188300c2
+ .word 0xe2833010
+ .word 0xe3150008
+ .word 0x18b400c2
+ .word 0x188300c2
+ .word 0xe2833010
+ .word 0xe3150010
+ .word 0x18b400c2
+ .word 0x188300c2
+ .word 0xe2833010
+ .word 0xe3150020
+ .word 0x18b400c2
+ .word 0x188300c2
+ .word 0xe2833010
+ .word 0xe3150040
+ .word 0x18b400c2
+ .word 0x188300c2
+ .word 0xe2833010
+ .word 0xe3150080
+ .word 0x18b400c2
+ .word 0x188300c2
+ .word 0xe24f3c01
+ .word 0xe2433f22
+ .word 0xe1a052a5
+ .word 0xe3855401
+ .word 0xe58a5080
+ .word 0xe5900030
+ .word 0xeaffffd2
+ .word 0xe3e00000
+ .word 0xe1b0f00e
+ .word 0xe92d401e
+ .word 0xe58a1004
+ .word 0xe3a0e000
+ .word 0xe58ae000
+ .word 0xe10f3000
+ .word 0xe3830080
+ .word 0xe129f000
+ .word 0xe24f102c
+ .word 0xeb00011c
+ .word 0xe3a00000
+ .word 0xee504110
+ .word 0xe3300000
+ .word 0x158a0008
+ .word 0x1a000008
+ .word 0xe3a02102
+ .word 0xee302110
+ .word 0xe1a00c22
+ .word 0xe58a0008
+ .word 0xe3300081
+ .word 0x03a04c0d
+ .word 0x0e008109
+ .word 0x0e100100
+ .word 0xee404110
+ .word 0xeb000112
+ .word 0xe129f003
+ .word 0xe8bd801e
+ .word 0xe92d400f
+ .word 0xe3a00000
+ .word 0xe58a0084
+ .word 0xe92d4000
+ .word 0xeb0000fe
+ .word 0xe8bd0001
+ .word 0xe8bd4000
+ .word 0xe5900008
+ .word 0xe3300081
+ .word 0x1a00000d
+ .word 0xe24f0f8e
+ .word 0xe890000e
+ .word 0xe28a0000
+ .word 0xe8a0000e
+ .word 0xe8a0000e
+ .word 0xe8a0000e
+ .word 0xe8a0000e
+ .word 0xe8a0000e
+ .word 0xe8a0000e
+ .word 0xe8a0000e
+ .word 0xe8a0000e
+ .word 0xe59f003c
+ .word 0xe58a0080
+ .word 0xe8bd800f
+ .word 0xe24f0e27
+ .word 0xe890000e
+ .word 0xe28a0000
+ .word 0xe8a0001e
+ .word 0xe8a0001e
+ .word 0xe8a0001e
+ .word 0xe8a0001e
+ .word 0xe8a0001e
+ .word 0xe8a0001e
+ .word 0xe8a0001e
+ .word 0xe8a0001e
+ .word 0xe59f0008
+ .word 0xe58a0080
+ .word 0xe8bd800f
+ .word 0x81070000
+ .word 0x01070000
+ .word 0xe92d4007
+ .word 0xe28fe074
+ .word 0xe92d4000
+ .word 0xeb0000d7
+ .word 0xe8bd0001
+ .word 0xe8bd4000
+ .word 0xe5900000
+ .word 0xe3300000
+ .word 0x01a0f00e
+ .word 0xe5901080
+ .word 0xe3310000
+ .word 0x5a00000e
+ .word 0xe92d4002
+ .word 0xee501110
+ .word 0xe3110c01
+ .word 0x01a0e001
+ .word 0x1590e084
+ .word 0xe3ceec0d
+ .word 0xe3110b01
+ .word 0x138eec05
+ .word 0xe580e084
+ .word 0xee301110
+ .word 0xe5801080
+ .word 0xed800200
+ .word 0xed80420c
+ .word 0xee40e110
+ .word 0xe8bd8002
+ .word 0xe92d4000
+ .word 0xe3a0e000
+ .word 0xe580e084
+ .word 0xe8bd8000
+ .word 0xe92d4007
+ .word 0xe92d4000
+ .word 0xeb0000b9
+ .word 0xe8bd0001
+ .word 0xe8bd4000
+ .word 0xe580a000
+ .word 0xe5900008
+ .word 0xe3300081
+ .word 0x0e501110
+ .word 0xe33a0000
+ .word 0x0a000014
+ .word 0xe3300081
+ .word 0x1a00000b
+ .word 0xe59a1080
+ .word 0xee201110
+ .word 0xed9a0200
+ .word 0xed9a420c
+ .word 0xe24f1a06
+ .word 0xe2411efd
+ .word 0xeb0000b0
+ .word 0xe59a1084
+ .word 0xe3110b01
+ .word 0x13a01c05
+ .word 0x1e401110
+ .word 0xe8bd8007
+ .word 0xe3300081
+ .word 0x03a01c0d
+ .word 0x0e401110
+ .word 0xe24f1b19
+ .word 0xe2411f1e
+ .word 0xeb0000a5
+ .word 0xe8bd8007
+ .word 0xe3300081
+ .word 0x03a01c0d
+ .word 0x0e401110
+ .word 0xe8bd4007
+ .word 0xea0000a4
+ .word 0xe92d4400
+ .word 0xe3a0a000
+ .word 0xebffffd7
+ .word 0xe8bd8400
+ .word 0xe92d4000
+ .word 0xeb000091
+ .word 0xe8bd0001
+ .word 0xe8bd4000
+ .word 0xe5900000
+ .word 0xe3300000
+ .word 0x01a0f00e
+ .word 0xe5901080
+ .word 0xe3310000
+ .word 0x5a000007
+ .word 0xee501110
+ .word 0xe3110c01
+ .word 0x01a02001
+ .word 0x15902084
+ .word 0xe3822c09
+ .word 0xe5802084
+ .word 0xee402110
+ .word 0xe1a0f00e
+ .word 0xe3a01001
+ .word 0xe5801084
+ .word 0xe1a0f00e
+ .word 0xe92d4000
+ .word 0xeb00007c
+ .word 0xe8bd0001
+ .word 0xe8bd4000
+ .word 0xe5900000
+ .word 0xe3300000
+ .word 0x01a0f00e
+ .word 0xe5901080
+ .word 0xe3310000
+ .word 0x5a00000e
+ .word 0xee501110
+ .word 0xe3110b01
+ .word 0x01a0f00e
+ .word 0xe3110c01
+ .word 0x01a02001
+ .word 0x15902084
+ .word 0xe3822c01
+ .word 0xe3c22b02
+ .word 0xe5802084
+ .word 0xee301110
+ .word 0xe5801080
+ .word 0xed800200
+ .word 0xed80420c
+ .word 0xee402110
+ .word 0xe1a0f00e
+ .word 0xe3a01000
+ .word 0xe5801084
+ .word 0xe1a0f00e
+ .word 0xe92d40fe
+ .word 0xe59a2080
+ .word 0xe3320000
+ .word 0x5a000010
+ .word 0xe3a0700c
+ .word 0xe92d4000
+ .word 0xeb00005b
+ .word 0xe8bd0004
+ .word 0xe8bd4000
+ .word 0xe5922000
+ .word 0xe132000a
+ .word 0x159a6084
+ .word 0x1a000005
+ .word 0xee506110
+ .word 0xee302110
+ .word 0xe58a2080
+ .word 0xed8a0200
+ .word 0xed8a420c
+ .word 0xee406110
+ .word 0xe2066b01
+ .word 0xea000001
+ .word 0xe3a07010
+ .word 0xe3a06000
+ .word 0xe59a2080
+ .word 0xe4802004
+ .word 0xe3a02008
+ .word 0xe89a0038
+ .word 0xe08aa007
+ .word 0xe3130101
+ .word 0x0a000009
+ .word 0xe3c33101
+ .word 0xe3140102
+ .word 0x0a000008
+ .word 0xe3c44102
+ .word 0xe3130901
+ .word 0x02833001
+ .word 0x0a000004
+ .word 0xe38330ff
+ .word 0xe3833c7f
+ .word 0xea000006
+ .word 0xe3140102
+ .word 0x1a000004
+ .word 0xe92d0340
+ .word 0xe1a06883
+ .word 0xe2968802
+ .word 0x1bfff338
+ .word 0xe8bd0340
+ .word 0xe8a00038
+ .word 0xe2522001
+ .word 0x1affffe7
+ .word 0xe24f2a07
+ .word 0xe2422f6f
+ .word 0xe24f3b01
+ .word 0xe2433f5a
+ .word 0xe1510002
+ .word 0xa1530001
+ .word 0xa3a00001
+ .word 0xb1a00006
+ .word 0xe8bd80fe
+ .word 0xe92d40ff
+ .word 0xe59a1080
+ .word 0xe3310000
+ .word 0x53a07010
+ .word 0x43a0700c
+ .word 0xe4902004
+ .word 0xe3c224ff
+ .word 0x53822401
+ .word 0x43822481
+ .word 0xe58a2080
+ .word 0xe3a02008
+ .word 0xe8b00038
+ .word 0xe1846005
+ .word 0xe1966083
+ .word 0x0a000003
+ .word 0xe1a06883
+ .word 0xe2966802
+ .word 0x13140102
+ .word 0x03833101
+ .word 0xe88a0038
+ .word 0xe08aa007
+ .word 0xe2522001
+ .word 0x1afffff3
+ .word 0xe04aa187
+ .word 0xe3310000
+ .word 0x58bd80ff
+ .word 0xe92d4000
+ .word 0xeb00000b
+ .word 0xe8bd0004
+ .word 0xe8bd4000
+ .word 0xe5922000
+ .word 0xe132000a
+ .word 0x18bd80ff
+ .word 0xee506110
+ .word 0xe59a2080
+ .word 0xee202110
+ .word 0xed9a0200
+ .word 0xed9a420c
+ .word 0xee406110
+ .word 0xe8bd80ff
+ .word 0xe24dd008
+ .word 0xe58d0000
+ .word 0xe59f0008
+ .word 0xe58d0004
+ .word 0xe49d0004
+ .word 0xe1a0f00e
+ .word 0x00000000
+ .word 0x00000000
+ .word 0xe92d4003
+ .word 0xe59f0004
+ .word 0xe5801000
+ .word 0xe8bd8003
+ .word 0x00000000
+ .word 0xe92d4007
+ .word 0xe51f0010
+ .word 0xe59f1004
+ .word 0xe5801000
+ .word 0xe8bd8007
+ .word 0x00000000
+ .word 0xe1a0d00c
+ .word 0xe8dd7fff
+ .word 0xe0000000
+ .word 0xe28dd03c
+ .word 0xe8bd8000
+ .word 0xe3a00000
+ .word 0xea000009
+ .word 0xe3a00001
+ .word 0xea000007
+ .word 0xe3a00002
+ .word 0xea000005
+ .word 0xe3a00003
+ .word 0xea000003
+ .word 0xe3a00004
+ .word 0xea000001
+ .word 0xe3e00000
+ .word 0xeaffffff
+ .word 0xe59f1000
+ .word 0xe1a0f001
+ .word 0x00000000
+ .word 0xe3a00005
+ .word 0xeafffffa
+ .word 0xe1a00000
+ .word 0xe59f1030
+ .word 0xe24fb010
+ .word 0xe05b1001
+ .word 0x01a0f00e
+ .word 0xe59fb024
+ .word 0xe08bb001
+ .word 0xe28f2020
+ .word 0xe4920004
+ .word 0xe3700001
+ .word 0xd1a0f00e
+ .word 0xe79b3000
+ .word 0xe0833001
+ .word 0xe78b3000
+ .word 0xeafffff8
+ .word 0x0000f370
+ .word 0x00008000
+ .word 0x000073ac
+ .word 0x000073b0
+ .word 0xffffffff
+
--- /dev/null
+/* $NetBSD: armfpe_glue.S,v 1.6 1996/03/18 19:54:59 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * arm_fpe_glue.S
+ *
+ * Glue code for calling the ARM FPE core code
+ *
+ * Created : 21/12/95
+ */
+
+#include "assym.h"
+#include <machine/cpu.h>
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+/* Offsets into fpe core for function addresses */
+
+#define ARM_FPE_CORE_ABORT 0
+#define ARM_FPE_CORE_INITWS 4
+#define ARM_FPE_CORE_INITCONTEXT 8
+#define ARM_FPE_CORE_CHANGECONTEXT 12
+#define ARM_FPE_CORE_SHUTDOWN 16
+#define ARM_FPE_CORE_ACTIVATECONTEXT 20
+#define ARM_FPE_CORE_DEACTIVATECONTEXT 24
+#define ARM_FPE_CORE_SAVECONTEXT 28
+#define ARM_FPE_CORE_LOADCONTEXT 32
+#define ARM_FPE_CORE_DISABLE 36
+#define ARM_FPE_CORE_ENABLE 40
+
+/*
+ * Ok Lots of little stubs for calling the fpe core
+ * routines from C
+ */
+
+ .text
+ .align
+
+arm_fpe_header:
+ .word _arm_fpe_mod
+
+ .global _arm_fpe_core_disable
+_arm_fpe_core_disable:
+ stmfd sp!, {r0-r7, lr}
+ ldr r0, [pc, #arm_fpe_header - . - 8]
+ ldr r0, [r0, #ARM_FPE_CORE_DISABLE]
+
+ add lr, pc, #L1 - . - 8
+ mov pc, r0
+L1:
+ ldmfd sp!, {r0-r7, pc}
+
+
+ .global _arm_fpe_core_enable
+_arm_fpe_core_enable:
+ stmfd sp!, {r0-r7, lr}
+ ldr r0, [pc, #arm_fpe_header - . - 8]
+ ldr r0, [r0, #ARM_FPE_CORE_ENABLE]
+
+ add lr, pc, #L2 - . - 8
+ mov pc, r0
+L2:
+ ldmfd sp!, {r0-r7, pc}
+
+
+ .global _arm_fpe_core_initws
+_arm_fpe_core_initws:
+ stmfd sp!, {r10, lr}
+ mov r10, r0
+ ldr r3, [pc, #arm_fpe_header - . - 8]
+ ldr r3, [r3, #ARM_FPE_CORE_INITWS]
+
+ add lr, pc, #L3 - . - 8
+ mov pc, r3
+L3:
+ ldmfd sp!, {r10, pc}
+
+
+ .global _arm_fpe_core_abort
+_arm_fpe_core_abort:
+ stmfd sp!, {r1-r7, r10, lr}
+ mov r10, r0
+ mov r0, r1
+ mov r1, r2
+ ldr r3, [pc, #arm_fpe_header - . - 8]
+ ldr r3, [r3, #ARM_FPE_CORE_ABORT]
+
+ add lr, pc, #L4 - . - 8
+ mov pc, r3
+L4:
+ ldmfd sp!, {r1-r7, r10, pc}
+
+
+/* Only needs to preserve r10 */
+
+ .global _arm_fpe_core_initcontext
+_arm_fpe_core_initcontext:
+ stmfd sp!, {r0-r7, r10, lr}
+ mov r10, r0
+ ldr r3, [pc, #arm_fpe_header - . - 8]
+ ldr r3, [r3, #ARM_FPE_CORE_INITCONTEXT]
+
+ add lr, pc, #L5 - . - 8
+ mov pc, r3
+L5:
+ ldmfd sp!, {r0-r7, r10, pc}
+
+
+/* Only needs to preserve r10 */
+
+ .global _arm_fpe_core_changecontext
+_arm_fpe_core_changecontext:
+ stmfd sp!, {r1-r7, r10, lr}
+ mov r10, r0
+ ldr r3, [pc, #arm_fpe_header - . - 8]
+ ldr r3, [r3, #ARM_FPE_CORE_CHANGECONTEXT]
+
+ add lr, pc, #L6 - . - 8
+ mov pc, r3
+L6:
+ ldmfd sp!, {r1-r7, r10, pc}
+
+
+/* All regs preerved */
+
+ .global _arm_fpe_core_shutdown
+_arm_fpe_core_shutdown:
+ stmfd sp!, {r0-r7, r10, lr}
+ ldr r3, [pc, #arm_fpe_header - . - 8]
+ ldr r3, [r3, #ARM_FPE_CORE_SHUTDOWN]
+
+ add lr, pc, #L7 - . - 8
+ mov pc, r3
+L7:
+ ldmfd sp!, {r0-r7, r10, pc}
+
+
+/* Preserve r10 */
+ .global _arm_fpe_core_savecontext
+_arm_fpe_core_savecontext:
+ stmfd sp!, {r1-r7, r10, lr}
+ mov r10, r0
+ mov r0, r1
+ mov r1, r2
+ ldr r3, [pc, #arm_fpe_header - . - 8]
+ ldr r3, [r3, #ARM_FPE_CORE_SAVECONTEXT]
+
+ add lr, pc, #L8 - . - 8
+ mov pc, r3
+L8:
+ ldmfd sp!, {r1-r7, r10, pc}
+
+
+/* Preserve r10 */
+
+ .global _arm_fpe_core_loadcontext
+_arm_fpe_core_loadcontext:
+ stmfd sp!, {r0-r7, r10, lr}
+ mov r10, r0
+ mov r0, r1
+ ldr r3, [pc, #arm_fpe_header - . - 8]
+ ldr r3, [r3, #ARM_FPE_CORE_LOADCONTEXT]
+
+ add lr, pc, #L9 - . - 8
+ mov pc, r3
+L9:
+ ldmfd sp!, {r0-r7, r10, pc}
+
+
+/* Only needs to preserve r10 */
+
+ .global _arm_fpe_core_activatecontext
+_arm_fpe_core_activatecontext:
+ stmfd sp!, {r0-r7, r10, lr}
+ mov r10, r0
+ ldr r3, [pc, #arm_fpe_header - . - 8]
+ ldr r3, [r3, #ARM_FPE_CORE_ACTIVATECONTEXT]
+
+ add lr, pc, #L10 - . - 8
+ mov pc, r3
+L10:
+ ldmfd sp!, {r0-r7, r10, pc}
+
+
+/* Only needs to preserve r10 */
+
+ .global _arm_fpe_core_deactivatecontext
+_arm_fpe_core_deactivatecontext:
+ stmfd sp!, {r1-r7, r10, lr}
+ ldr r3, [pc, #arm_fpe_header - . - 8]
+ ldr r3, [r3, #ARM_FPE_CORE_DEACTIVATECONTEXT]
+
+ add lr, pc, #L11 - . - 8
+ mov pc, r3
+L11:
+ ldmfd sp!, {r1-r7, r10, pc}
+
+
+/* Simple call back function that panics */
+
+ .global _arm_fpe_panic
+_arm_fpe_panic:
+ adr r0, fpe_panic_text
+ b _panic
+
+fpe_panic_text:
+ .asciz "armfpe: we are panicing"
+ .align 0
+
+
+/*
+ * Call back routine from FPE on completion of an instruction
+ */
+
+ .global _arm_fpe_post_proc_glue
+_arm_fpe_post_proc_glue:
+ stmfd sp!, {r0-r6, r10-r12, lr}
+
+/* This could be optimised as we are going from UND32->SVC32 mode */
+
+ mrs r4, cpsr_all
+ bic r3, r4, #(PSR_MODE)
+ orr r3, r3, #(PSR_SVC32_MODE)
+ msr cpsr_all, r3
+
+ mov r0, r12
+
+/* Reserve a trapframe on the SVC stack */
+
+ sub sp, sp, #(TRAPFRAMESIZE)
+ mov r1, sp
+
+ ldr r2, [r0, #-0x0008] /* Copy spsr */
+ str r2, [r1, #0x0000]
+
+ ldr r2, [r0, #0x0000] /* Copy r0 */
+ str r2, [r1, #0x0004]
+ ldr r2, [r0, #0x0004]
+ str r2, [r1, #0x0008]
+ ldr r2, [r0, #0x0008]
+ str r2, [r1, #0x000c]
+ ldr r2, [r0, #0x000c]
+ str r2, [r1, #0x0010]
+ ldr r2, [r0, #0x0010]
+ str r2, [r1, #0x0014]
+ ldr r2, [r0, #0x0014]
+ str r2, [r1, #0x0018]
+ ldr r2, [r0, #0x0018]
+ str r2, [r1, #0x001c]
+ ldr r2, [r0, #0x001c]
+ str r2, [r1, #0x0020]
+ ldr r2, [r0, #0x0020]
+ str r2, [r1, #0x0024]
+ ldr r2, [r0, #0x0024]
+ str r2, [r1, #0x0028]
+ ldr r2, [r0, #0x0028]
+ str r2, [r1, #0x002c]
+ ldr r2, [r0, #0x002c]
+ str r2, [r1, #0x0030]
+ ldr r2, [r0, #0x0030] /* Copy r12 */
+ str r2, [r1, #0x0034]
+ ldr r2, [r0, #0x0034] /* Copy usr r13 */
+ str r2, [r1, #0x0038]
+ ldr r2, [r0, #0x0038] /* Copy usr r14 */
+ str r2, [r1, #0x003c]
+ ldr r2, [r0, #0x003c] /* Copy old pc */
+ str r2, [r1, #0x0044]
+
+ str r14, [r1, #0x0040] /* SVC r14 */
+
+/*
+ * OK Question Time ...
+ *
+ * Do I need to save SVC r14 ?
+ * It only needs saving if this routine can interrupt something already
+ * running in SVC mode. Since FP is only valid from USR32 mode this
+ * should not happen.
+ */
+
+ mov r5, r14
+ mov r6, r12
+
+/* More optimisation ... Need to code a assembly version of userret() */
+
+ bl _arm_fpe_postproc
+
+/* Release the trapframe on the SVC stack */
+
+ ldr r2, [sp, #0x0000] /* Copy spsr */
+ str r2, [r6, #-0x0008]
+
+ ldr r2, [sp, #0x0004] /* Copy r0 */
+ str r2, [r6, #0x0000]
+ ldr r2, [sp, #0x0008] /* Copy r1 */
+ str r2, [r6, #0x0004]
+ ldr r2, [sp, #0x000c] /* Copy r2 */
+ str r2, [r6, #0x0008]
+ ldr r2, [sp, #0x0010] /* Copy r3 */
+ str r2, [r6, #0x000c]
+ ldr r2, [sp, #0x0014] /* Copy r4 */
+ str r2, [r6, #0x0010]
+ ldr r2, [sp, #0x0018] /* Copy r5 */
+ str r2, [r6, #0x0014]
+ ldr r2, [sp, #0x001c] /* Copy r6 */
+ str r2, [r6, #0x0018]
+ ldr r2, [sp, #0x0020] /* Copy r7 */
+ str r2, [r6, #0x001c]
+ ldr r2, [sp, #0x0024] /* Copy r8 */
+ str r2, [r6, #0x0020]
+ ldr r2, [sp, #0x0028] /* Copy r9 */
+ str r2, [r6, #0x0024]
+ ldr r2, [sp, #0x002c] /* Copy r10 */
+ str r2, [r6, #0x0028]
+ ldr r2, [sp, #0x0030] /* Copy r11 */
+ str r2, [r6, #0x002c]
+ ldr r2, [sp, #0x0034] /* Copy r12 */
+ str r2, [r6, #0x0030]
+ ldr r2, [sp, #0x0038] /* Copy usr r13 */
+ str r2, [r6, #0x0034]
+ ldr r2, [sp, #0x003c] /* Copy usr r14 */
+ str r2, [r6, #0x0038]
+ ldr r2, [sp, #0x0044] /* Copy pc */
+ str r2, [r6, #0x003c]
+
+ add sp, sp, #(TRAPFRAMESIZE)
+
+ mov r14, r5
+
+ msr cpsr_all, r4
+
+ ldmfd sp!, {r0-r6, r10-r12, pc}
+
+
+/*
+ * Call back routine from FPE when the an exception occurs
+ */
+
+ .global _arm_fpe_exception_glue
+_arm_fpe_exception_glue:
+ stmfd sp!, {r0-r5, r10-r12, lr}
+
+/* This could be optimised as we are going from UND32->SVC32 mode */
+
+ mrs r4, cpsr_all
+ bic r3, r4, #(PSR_MODE)
+ orr r3, r3, #(PSR_SVC32_MODE)
+ msr cpsr_all, r3
+
+ ldr r1, [r12, #15*4]
+ mov r2, r12
+
+ mov r5, r14
+
+ bl _arm_fpe_exception
+
+ mov r14, r5
+
+ msr cpsr_all, r4
+
+ ldmfd sp!, {r0-r5, r10-r12, lr}
+
+/* Now pull the original trapframe that the FPE pushed off the stack */
+
+ ldmdb r12, {r0, r1}
+
+ msr cpsr_all, r1
+ msr spsr_all, r0
+
+ mov sp, r12
+
+ ldmia sp, {r0-r14}^
+ mov r0, r0
+ add sp, sp, #15*4
+ ldmfd sp!, {pc}^
+
+ .global _fpe_nexthandler
+_fpe_nexthandler:
+ .word _undefinedinstruction_bounce
--- /dev/null
+/* $NetBSD: armfpe_init.c,v 1.6 1996/03/18 19:55:01 mark Exp $ */
+
+/*
+ * Copyright (C) 1996 Mark Brinicombe
+ * Copyright (C) 1995 Neil A Carson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * arm_fpe.c
+ *
+ * Stuff needed to interface the ARM floating point emulator module to RiscBSD.
+ *
+ * Created : 22/10/95
+ */
+
+/*#define DEBUG*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/acct.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+
+#include <machine/cpu.h>
+#include <machine/cpus.h>
+#include <machine/katelib.h>
+#include <machine/frame.h>
+
+#include "armfpe.h" /* Prototypes for things */
+
+extern int want_resched;
+extern u_int fpe_nexthandler;
+
+void undefinedinstruction_bounce __P(());
+void arm_fpe_exception_glue __P((int exception));
+void arm_fpe_panic __P(());
+void undefined_entry __P(());
+void arm_fpe_post_proc_glue __P(());
+
+/*
+ * A module header, pointing into the module
+ */
+
+extern u_int arm_fpe_mod[];
+extern u_int undefined_handler_address;
+
+/*
+ * Error messages for the various exceptions, numbered 0-5
+ */
+
+static char *exception_errors[] = {
+ "Floating point invalid operation",
+ "Floating point division by zero (0)",
+ "Floating point overflow",
+ "Floating point underflow",
+ "Floating point operation inexact",
+ "Floating point major faliure... core fault trapped... not good!"
+};
+
+/*
+ * Relocate the FPE.
+ */
+
+void
+arm_fpe_mod_reloc(void)
+{
+ int cnt;
+ arm_fpe_mod_hdr_t *arm_fpe_mod_hdr = (arm_fpe_mod_hdr_t *)arm_fpe_mod;
+
+ /* Go through the module header, and convert all offsets into absolute
+ * addresses. Careful here - the last two fields of the header do _NOT_
+ * want to be relocated!
+ */
+
+ for (cnt = 0; cnt < (sizeof(arm_fpe_mod_hdr_t) >> 2) - 2; cnt ++) {
+#ifdef DEBUG
+ printf("FPE: entry %02x = %08x ", cnt, arm_fpe_mod[cnt]);
+#endif
+ arm_fpe_mod[cnt] += (u_int) arm_fpe_mod;
+#ifdef DEBUG
+ printf(" reloc=%08x\n", arm_fpe_mod[cnt]);
+#endif
+ }
+ /* Print a startup message, and a couple of variables needed, these may need
+ * checking to make *sure* they are OK!
+ */
+
+#ifdef DEBUG
+ printf("FPE: global workspace size = %d bytes, context size = %d bytes\n",
+ arm_fpe_mod_hdr->WorkspaceLength, arm_fpe_mod_hdr->ContextLength);
+ printf("FPE: base=%08x\n", (u_int)arm_fpe_mod);
+#endif
+}
+
+/*
+ * Initialisation point. The kernel calls this during the configuration of the cpu
+ * in order to install the FPE.
+ * The FPE specification needs to be filled in the specified cpu_t structure
+ * and the FPE needs to be installed on the CPU undefined instruction vector.
+ */
+
+int
+initialise_arm_fpe(cpu)
+ cpu_t *cpu;
+{
+ int error;
+
+ cpu->fpu_class = FPU_CLASS_FPE;
+ cpu->fpu_type = FPU_TYPE_ARMLTD_FPE;
+ strcpy(cpu->fpu_model, "Advanced RISC Machines floating point emulator");
+ error = arm_fpe_boot();
+ if (error != 0) {
+ strcat(cpu->fpu_model, " - boot failed");
+ return(1);
+ }
+
+/* Return with start failure so the old FPE is installed */
+
+/* strcat(cpu->fpu_model, " - boot aborted");*/
+
+ return(0);
+}
+
+/*
+ * The actual FPE boot routine.
+ * This has to do a number of things :
+ * 1. Relocate the FPE - Note this requires write access to the kernel text area
+ * 2. Allocated memory for the FPE
+ * 3. Initialise the FPE
+ */
+
+int
+arm_fpe_boot(void)
+{
+ u_int workspace;
+ int id;
+ arm_fpe_mod_hdr_t *arm_fpe_mod_hdr = (arm_fpe_mod_hdr_t *)arm_fpe_mod;
+
+ /* First things first ... Relocate the FPE pointers */
+
+ arm_fpe_mod_reloc();
+
+ /* Now we must do some memory allocation */
+
+ workspace = (u_int)malloc(arm_fpe_mod_hdr->WorkspaceLength, M_DEVBUF, M_NOWAIT);
+#ifdef DEBUG
+ printf("Gloabl workspace at 0x%08x\n", workspace);
+#endif
+
+ if (!workspace)
+ return(ENOMEM);
+
+ *arm_fpe_mod_hdr->main_ws_ptr_addr = workspace;
+
+ *arm_fpe_mod_hdr->local_handler_ptr_addr = (u_int)&undefined_handler_address;
+ *arm_fpe_mod_hdr->old_handler_ptr_addr = undefined_handler_address;
+
+ /* Initialise out gloable workspace */
+
+#ifdef DEBUG
+ printf("Initing workspace ");
+#endif
+
+ id = arm_fpe_core_initws(workspace, (u_int)&fpe_nexthandler, (u_int)&fpe_nexthandler);
+
+#ifdef DEBUG
+ printf("id=%08x\n", id);
+#endif
+
+ /* Set up an exception handler */
+
+ *arm_fpe_mod_hdr->exc_handler_ptr_addr = (u_int)arm_fpe_exception_glue;
+
+ /* Set up post instruction handler */
+#if defined(CPU_ARM6) || defined(CPU_ARM7)
+ *arm_fpe_mod_hdr->fp_post_proc_addr = (((((u_int)arm_fpe_post_proc_glue -
+ (u_int)arm_fpe_mod_hdr->fp_post_proc_addr - 8)>>2) & 0x00ffffff) | 0xea000000);
+#ifdef DEBUG
+ printf("arm_fpe_mod_hdr->fp_post_proc_addr = %08x (%08x)",
+ arm_fpe_mod_hdr->fp_post_proc_addr,
+ *arm_fpe_mod_hdr->fp_post_proc_addr);
+#endif
+#else
+#error ARMFPE currently only supports ARM6 and ARM7
+#endif
+
+#ifdef DEBUG
+ printf("Initialising proc0 FPE context\n");
+#endif
+
+ /* Initialise proc0's FPE context */
+
+ arm_fpe_core_initcontext(FP_CONTEXT(&proc0));
+ arm_fpe_core_changecontext(FP_CONTEXT(&proc0));
+
+ return(0);
+}
+
+
+/*
+ * Callback routine from the FPE when instruction emulation completes
+ */
+
+void
+arm_fpe_postproc(fpframe, frame)
+ u_int fpframe;
+ struct trapframe *frame;
+{
+ register u_int s;
+ register int sig;
+ register struct proc *p;
+
+ p = curproc;
+ p->p_md.md_regs = frame;
+
+/* take pending signals */
+
+ while ((sig = (CURSIG(p))) != 0) {
+ postsig(sig);
+ }
+
+ p->p_priority = p->p_usrpri;
+
+ if (want_resched) {
+ /*
+ * Since we are curproc, a clock interrupt could
+ * change our priority without changing run queues
+ * (the running process is not kept on a run queue).
+ * If this happened after we setrunqueue ourselves but
+ * before we switch()'ed, we might not be on the queue
+ * indicated by our priority
+ */
+
+ s = splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nivcsw++;
+
+ mi_switch();
+
+ (void)splx(s);
+ while ((sig = (CURSIG(p))) != 0) {
+ postsig(sig);
+ }
+ }
+
+/* Profiling. */
+
+ if (p->p_flag & P_PROFIL) {
+ extern int psratio;
+ u_int pc;
+
+ pc = ReadWord(fpframe + 15*4);
+
+ if (pc <0x1000 || pc > 0xefc00000)
+ printf("armfpe_postproc: pc=%08x\n", pc);
+
+/* addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);*/
+ addupc_task(p, pc, (int)(p->p_sticks - p->p_sticks) * psratio);
+ }
+
+ curpriority = p->p_priority;
+}
+
+
+/*
+ * Callback routine from the FPE when an exception occurs.
+ */
+
+void
+arm_fpe_exception(exception, pc, fpframe)
+ int exception;
+ u_int pc;
+ u_int fpframe;
+{
+ if (exception >= 0 && exception < 6)
+ printf("fpe exception: %d - %s\n", exception, exception_errors[exception]);
+ else
+ printf("fpe exception: %d - unknown\n", exception);
+
+ trapsignal(curproc, SIGFPE, exception);
+
+ printf("PC=%08x\n", ReadWord(fpframe + 60));
+
+ userret(curproc, pc, curproc->p_sticks);
+}
+
+
+void
+arm_fpe_copycontext(c1, c2)
+ u_int c1;
+ u_int c2;
+{
+ fp_context_frame_t fpcontext;
+
+ arm_fpe_core_savecontext(c1, (int *)&fpcontext, 0);
+ arm_fpe_core_loadcontext(c2, (int *)&fpcontext);
+}
+
+/* End of armfpe_init.c */
--- /dev/null
+/* $NetBSD: fpe.c,v 1.2 1996/03/18 19:58:09 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fpe.c
+ *
+ * Floating Point Emulator
+ *
+ * Currently calculations are only performed to single precision
+ *
+ * Created : 11/02/95
+ */
+
+/* FPE Compile options
+ *
+ * FPE_SPEEDUPS - use assembly speedups in place of C routines
+ * FPE_NODEBUG - don't compile in the debugging code
+ * FPE_PROF - compile in FPE profiling code
+ * FPE_INLINE - define this as inline to inline some functions
+ */
+
+#define FPE_SPEEDUPS
+#define FPE_NODEBUG
+/*#define FPE_PROF*/
+#define FPE_INLINE __inline
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/syslog.h>
+
+#include <machine/cpu.h>
+#include <machine/cpus.h>
+#include <machine/katelib.h>
+#include <machine/frame.h>
+#include <machine/undefined.h>
+#include <machine/fp.h>
+
+typedef struct {
+ int opcode;
+ int precision;
+ int rounding;
+ int fpregm;
+ int fpregn;
+ int fpregd;
+ int regd;
+} fp_op_data_t;
+
+/* Types and stuctures used to hold floating point numbers */
+
+typedef struct {
+ u_int32_t exponent;
+ u_int32_t mantissa_hi;
+ u_int32_t mantissa_lo;
+} fpe_reg_t;
+
+typedef struct {
+ u_int mantissa:23;
+ u_int exponent:8;
+ u_int sign:1;
+} fpe_sprec_t;
+
+typedef struct {
+ u_int mantissa_hi:20;
+ u_int exponent:11;
+ u_int sign:1;
+ u_int32_t mantissa_lo;
+} fpe_dprec_t;
+
+typedef struct {
+ u_int32_t exponent;
+ u_int32_t mantissa_hi;
+ u_int32_t mantissa_lo;
+} fpe_eprec_t;
+
+typedef struct {
+ u_int32_t word1;
+ u_int32_t word2;
+ u_int32_t word3;
+} fpe_pprec_t;
+
+typedef struct {
+ u_int32_t exponent;
+ u_int64_t mantissa;
+} fpe_qreg_t;
+
+/* FPE status and control registers */
+
+u_int fpe_status = 0x02000000;
+u_int fpe_control = 0x00000000;
+
+#define FPE_STATUS_MASK 0x001f1f1f
+#define FPE_CONTROL_MASK 0x9cffffff
+
+/* Array containing the emulated registers */
+
+fpe_reg_t fpe_registers[16] = {
+ { 0, 0, 0 }, /* f0 */
+ { 0, 0, 0 }, /* f1 */
+ { 0, 0, 0 }, /* f2 */
+ { 0, 0, 0 }, /* f3 */
+ { 0, 0, 0 }, /* f4 */
+ { 0, 0, 0 }, /* f5 */
+ { 0, 0, 0 }, /* f6 */
+ { 0, 0, 0 }, /* f7 */
+ { 0x0000, 0x00000000, 0x00000000 }, /* 0.0 */
+ { 0x3fff, 0x80000000, 0x00000000 }, /* 1.0 */
+ { 0x4000, 0x80000000, 0x00000000 }, /* 2.0 */
+ { 0x4000, 0xc0000000, 0x00000000 }, /* 3.0 */
+ { 0x4001, 0x80000000, 0x00000000 }, /* 4.0 */
+ { 0x4001, 0xa0000000, 0x00000000 }, /* 5.0 */
+ { 0x3ffe, 0x80000000, 0x00000000 }, /* 0.5 */
+ { 0x4002, 0xa0000000, 0x00000000 }, /* 10.0 */
+};
+
+fpe_reg_t *fpregs;
+
+/* Prototypes for instruction emulation functions */
+
+typedef int (*fpe_handler_t) __P((unsigned int, trapframe_t *));
+typedef int (*fpe_dop_handler_t) __P((fp_op_data_t *, trapframe_t *));
+
+int fpe_mvf __P((fp_op_data_t *, trapframe_t *));
+int fpe_mnf __P((fp_op_data_t *, trapframe_t *));
+int fpe_adf __P((fp_op_data_t *, trapframe_t *));
+int fpe_muf __P((fp_op_data_t *, trapframe_t *));
+int fpe_suf __P((fp_op_data_t *, trapframe_t *));
+int fpe_dvf __P((fp_op_data_t *, trapframe_t *));
+int fpe_muf __P((fp_op_data_t *, trapframe_t *));
+int fpe_rdf __P((fp_op_data_t *, trapframe_t *));
+int fpe_rsf __P((fp_op_data_t *, trapframe_t *));
+int fpe_abs __P((fp_op_data_t *, trapframe_t *));
+
+/* Table of handler functions for register to registers operations */
+
+fpe_dop_handler_t fpe_dops[32] = {
+ fpe_adf, /* 00000 ADF Add */
+ fpe_mvf, /* 00001 MVF Move */
+ fpe_muf, /* 00010 MUL Multiply */
+ fpe_mnf, /* 00011 MNF Move negated */
+ fpe_suf, /* 00100 SUF Subtract */
+ fpe_abs, /* 00101 ABS Absolute value */
+ fpe_rsf, /* 00110 RSF Reverse subtract */
+ NULL, /* 00111 RND Round to integer */
+ fpe_dvf, /* 01000 DVF Divide */
+ NULL, /* 01001 SQT Square root */
+ fpe_rdf, /* 01010 RDF Reverse divide */
+ NULL, /* 01011 LOG Logarithm to base 10 */
+ NULL, /* 01100 POW Power */
+ NULL, /* 01101 LGN Logarithm to base e */
+ NULL, /* 01110 RPW Reverse power */
+ NULL, /* 01111 EXP Exponent */
+ NULL, /* 10000 RMF Remainder */
+ NULL, /* 10001 SIN Sine */
+ fpe_muf, /* 10010 FML Fast multiply */
+ NULL, /* 10011 COS Cosine */
+ fpe_dvf, /* 10100 FDV Fast divide */
+ NULL, /* 10101 TAN Tangent */
+ fpe_rdf, /* 10110 FRD Fast reverse divide */
+ NULL, /* 10111 ASN Arc sine */
+ NULL, /* 11000 ROL Rolar angle */
+ NULL, /* 11001 ACS Arc cosine */
+ NULL, /* 11010 undefined */
+ NULL, /* 11011 ATN Arc tangent */
+ NULL, /* 11100 undefined */
+ NULL, /* 11101 undefined */
+ NULL, /* 11110 undefined */
+ NULL, /* 11111 undefined */
+};
+
+/* Prototypes for instruction emulation functions */
+
+int fpe_flt __P((fp_op_data_t *, trapframe_t *));
+int fpe_fix __P((fp_op_data_t *, trapframe_t *));
+int fpe_wfs __P((fp_op_data_t *, trapframe_t *));
+int fpe_rfs __P((fp_op_data_t *, trapframe_t *));
+int fpe_wfc __P((fp_op_data_t *, trapframe_t *));
+int fpe_rfc __P((fp_op_data_t *, trapframe_t *));
+int fpe_cmf __P((fp_op_data_t *, trapframe_t *));
+int fpe_cnf __P((fp_op_data_t *, trapframe_t *));
+
+/* Table of handler functions for fp register transfer operations */
+
+fpe_dop_handler_t fpe_regtrans[16] = {
+ fpe_flt, /* 0000 FLT Integer to FP */
+ fpe_fix, /* 0001 FIX FP to Integer */
+ fpe_wfs, /* 0010 Write FP status */
+ fpe_rfs, /* 0011 Read FP status */
+ fpe_wfc, /* 0100 Write FP control */
+ fpe_rfc, /* 0101 Read FP control */
+ NULL, /* 0110 undefined */
+ NULL, /* 0111 undefined */
+ NULL, /* 1000 undefined */
+ fpe_cmf, /* 1001 Compare FP */
+ NULL, /* 1010 undefined */
+ fpe_cnf, /* 1011 Compare negated FP */
+ NULL, /* 1100 undefined */
+ fpe_cmf, /* 1101 Compare FP with exception */
+ NULL, /* 1110 undefined */
+ fpe_cnf, /* 1111 Compare negated FP with exception */
+};
+
+/* Prototypes for instruction emulation functions */
+
+int fpe_ldfstf __P((unsigned int address, trapframe_t *));
+
+FPE_INLINE int stofpe __P((u_int32_t */*address*/, fpe_reg_t */*fpreg*/));
+int dtofpe __P((u_int32_t *, fpe_reg_t *));
+int etofpe __P((u_int32_t *, fpe_reg_t *));
+int ptofpe __P((u_int32_t *, fpe_reg_t *));
+FPE_INLINE int fpetos __P((u_int32_t *, fpe_reg_t *));
+int fpetod __P((u_int32_t *, fpe_reg_t *));
+int fpetoe __P((u_int32_t *, fpe_reg_t *));
+int fpetop __P((u_int32_t *, fpe_reg_t *));
+
+int fpe_dump(void);
+
+int coproc1_handler __P((unsigned int, unsigned int, trapframe_t *));
+int coproc2_handler __P((unsigned int, unsigned int, trapframe_t *));
+
+/* Prototypes for assembly functions */
+
+u_int32_t nc_fp_add __P((u_int32_t, u_int32_t));
+u_int32_t nc_fp_sub __P((u_int32_t, u_int32_t));
+u_int32_t nc_fp_mul __P((u_int32_t, u_int32_t));
+u_int32_t nc_fp_div __P((u_int32_t, u_int32_t));
+u_int32_t nc_fp_fix __P((u_int32_t));
+u_int32_t nc_fp_cmp __P((u_int32_t, u_int32_t));
+
+#define FPP_ADD 0
+#define FPP_SUB 1
+#define FPP_MUL 2
+#define FPP_DIV 3
+#define FPP_CMF 4
+#define FPP_CNF 5
+#define FPP_FIX 6
+#define FPP_FLT 7
+#define FPP_ABS 8
+#define FPP_MOV 9
+#define FPP_MVN 10
+#define FPP_RDV 11
+#define FPP_RSB 12
+#define FPP_STRS 13
+#define FPP_STRD 14
+#define FPP_STRE 15
+#define FPP_STRP 16
+#define FPP_LDRS 17
+#define FPP_LDRD 18
+#define FPP_LDRE 19
+#define FPP_LDRP 20
+#define FPP_MAX 21
+
+#ifdef FPE_PROF
+u_int fp_profile[FPP_MAX];
+
+#define FPP_INC(x) ++fp_profile[x]
+#else
+#define FPP_INC(x)
+#endif
+
+/*
+* If FPE is defined then we are being built into the kernel.
+* If not then we are being built as a standalone loadable module.
+*/
+
+#ifdef FPE
+#define PRINTF(x) ;
+#define FPE_DUMP() ;
+#else
+#define PRINTF(x) (*printf_store)(x)
+#define FPE_DUMP() fpe_dump()
+
+void (*printf_store)();
+void (*install_coproc_store)();
+
+#ifdef NOTEXT
+void
+fpe_printf(char *a, ...)
+{
+}
+#endif
+
+/* Standalone initialisation point */
+
+int
+init_fpe(printf_handler, coproc_handler)
+ void (*printf_handler)();
+ void (*coproc_handler)();
+{
+ int loop;
+
+ printf_store = printf_handler;
+ install_coproc_store = coproc_handler;
+#ifdef NOTEXT
+ printf_store = fpe_printf;
+#endif
+ (*install_coproc_store)(FP_COPROC, coproc1_handler);
+ (*install_coproc_store)(FP_COPROC2, coproc2_handler);
+
+#ifdef FPE_PROF
+ for (loop = 0; loop < FPP_MAX; ++loop)
+ fp_profile[loop] = 0;
+#endif
+
+ PRINTF(("FPE installed\n"));
+ return(0);
+}
+#endif
+
+
+/*
+ * Main entry point after an undefined instruction.
+ * The instruction has been identified as a co-proc 2 instruction.
+ * We get the address of the instruction, the instruction itself and
+ * and pointer to the trap frame.
+ * Currently we do support this (LFM/SFM) so its gallows time
+ */
+
+int
+coproc2_handler(address, instruction, frame)
+ unsigned int address;
+ unsigned int instruction;
+ trapframe_t *frame;
+{
+ log(LOG_ERR, "Coprocessor 2 FP instruction 0x%08x not supported yet.", instruction);
+ return(1);
+}
+
+
+void
+init_fpe_state(p)
+ struct proc *p;
+{
+ struct fp_state *fpstate;
+ int loop;
+
+ fpstate = &p->p_addr->u_pcb.pcb_fpstate;
+ fpstate->fp_flags |= 1;
+
+ for (loop = 8; loop < 16; ++loop)
+ fpstate->fp_registers[loop] = *((fp_reg_t *)&fpe_registers[loop]);
+}
+
+
+int
+initialise_fpe(cpu)
+ cpu_t *cpu;
+{
+ cpu->fpu_class = FPU_CLASS_FPE;
+ cpu->fpu_type = FPU_TYPE_SP_FPE;
+ strcpy(cpu->fpu_model, "Single precision floating point emulator");
+ install_coproc_handler(FP_COPROC, coproc1_handler);
+ install_coproc_handler(FP_COPROC2, coproc2_handler);
+ init_fpe_state(curproc);
+ return(0);
+}
+
+
+/*
+ * Main entry point after an undefined instruction.
+ * The instruction has been identified as a co-proc 1 instruction.
+ * We get the address of the instruction, the instruction itself and
+ * and pointer to the trap frame.
+ */
+
+int
+coproc1_handler(address, instruction, frame)
+ unsigned int address;
+ unsigned int instruction;
+ trapframe_t *frame;
+{
+ struct fp_state *fpstate;
+ PRINTF(("FPE instruction 0x%08x -> 0x%08x\n",
+ address, instruction));
+
+/* Get the fp registers pointer */
+
+ fpstate = &curproc->p_addr->u_pcb.pcb_fpstate;
+
+ fpstate->fp_flags |= 2; /* so statclock can tell if we are spending time in the fpe */
+
+ if (fpstate->fp_flags & 1)
+ fpregs = (fpe_reg_t *) &fpstate->fp_registers;
+ else
+ fpregs = fpe_registers;
+
+/* Test for a FP data transfer operation */
+
+ if ((instruction & (1 << 25)) == 0) {
+ int err;
+
+ PRINTF(("FP data transfer\n"));
+ err = fpe_ldfstf(instruction, frame);
+ FPE_DUMP();
+ fpstate->fp_flags &= ~2;
+ return(err);
+ }
+
+/* Test for a FP data operation */
+
+ else if ((instruction & (1 << 4)) == 0) {
+ fp_op_data_t op_data;
+
+ op_data.opcode = (instruction >> 19) & 0x1e;
+ if (instruction & 0x00008000)
+ op_data.opcode |= 0x01;
+
+ op_data.precision = ((instruction & (1<<19)) ? 2 : 0)
+ | ((instruction & (1<<7)) ? 1 : 0);
+ op_data.rounding = (instruction >> 5) & 3;
+ op_data.fpregm = (instruction) & 15;
+ op_data.fpregn = (instruction >> 16) & 7;
+ op_data.fpregd = (instruction >> 12) & 7;
+
+ PRINTF(("FP data op = %d\n", op_data.opcode));
+ if (fpe_dops[op_data.opcode]) {
+ int err;
+ err = (*fpe_dops[op_data.opcode])(&op_data, frame);
+#ifndef FPE_NODEBUG
+ if (err == 0)
+ FPE_DUMP();
+#endif
+ fpstate->fp_flags &= ~2;
+ return(err);
+ }
+ else {
+ fpstate->fp_flags &= ~2;
+ return(1);
+ }
+ }
+
+/* Test for a FP register transfer operation */
+
+ else {
+ fp_op_data_t op_data;
+
+ op_data.opcode = (instruction >> 20) & 0x0f;
+
+ op_data.precision = ((instruction & (1<<19)) ? 2 : 0)
+ | ((instruction & (1<<7)) ? 1 : 0);
+ op_data.rounding = (instruction >> 5) & 3;
+ op_data.fpregm = (instruction) & 15;
+ op_data.fpregn = (instruction >> 16) & 7;
+ op_data.regd = (instruction >> 12) & 15;
+
+ PRINTF(("FP reg trans = %d\n", op_data.opcode));
+ if (fpe_regtrans[op_data.opcode]) {
+ int err;
+
+ PRINTF(("FP reg trans op = %d\n", op_data.opcode));
+ err = (*fpe_regtrans[op_data.opcode])(&op_data, frame);
+#ifndef FPE_NODEBUG
+ if (err == 0 && (op_data.opcode == 0 || op_data.opcode == 2
+ || op_data.opcode == 4))
+ FPE_DUMP();
+#endif
+ fpstate->fp_flags &= ~2;
+ return(err);
+ }
+ else {
+ fpstate->fp_flags &= ~2;
+ return(1);
+ }
+ }
+
+/* Well if it gets here then it was not a decodable FP instruction */
+
+ fpstate->fp_flags &= ~2;
+ return(1);
+}
+
+
+/* Precision convertion routines */
+
+FPE_INLINE int
+stofpe(address, fpreg)
+ u_int32_t *address;
+ fpe_reg_t *fpreg;
+{
+ fpe_sprec_t real;
+ u_int32_t *words = (u_int32_t *)ℜ
+
+ if ((address[0] & ~(1<<31)) == 0) {
+ PRINTF(("single=0\n"));
+
+ fpreg->mantissa_hi = 0;
+ fpreg->mantissa_lo = 0;
+ fpreg->exponent = address[0] & (1<<31);
+ return(0);
+ }
+
+ words[0] = address[0];
+ PRINTF(("word=%08x\n", address[0]));
+
+ PRINTF(("sign = %d exponent=%08x mantissa=%08x\n", real.sign,
+ real.exponent, real.mantissa));
+ fpreg->mantissa_hi = real.mantissa << 8;
+ fpreg->mantissa_lo = 0;
+ fpreg->exponent = ((int)real.exponent - 0x80) + 0x4000;
+ fpreg->exponent |= (real.sign << 31);
+ return(0);
+}
+
+
+int
+dtofpe(address, fpreg)
+ u_int32_t *address;
+ fpe_reg_t *fpreg;
+{
+ fpe_dprec_t real;
+
+ if ((address[0] & ~(1<<31)) == 0 && address[1] == 0) {
+ PRINTF(("double=0\n"));
+
+ fpreg->mantissa_hi = 0;
+ fpreg->mantissa_lo = 0;
+ fpreg->exponent = address[0] & (1<<31);
+ return(0);
+ }
+
+ real = *(fpe_dprec_t *)address;
+ PRINTF(("sign = %d exponent=%08x mantissa=%08x %08x\n", real.sign,
+ real.exponent, real.mantissa_lo, real.mantissa_hi));
+ fpreg->mantissa_hi = real.mantissa_hi << 11;
+ fpreg->mantissa_hi |= real.mantissa_lo >> 21;
+ fpreg->mantissa_lo = real.mantissa_lo << 11;
+ fpreg->exponent = (real.exponent - 0x400) + 0x4000;
+ fpreg->exponent |= (real.sign << 31);
+
+ return(0);
+}
+
+
+#ifndef FPE_SPEEDUPS
+int
+etofpe(address, fpreg)
+ u_int32_t *address;
+ fpe_reg_t *fpreg;
+{
+ bcopy((char *)address, (char *)fpreg, 12);
+ return(0);
+}
+#endif
+
+
+int
+ptofpe(address, fpreg)
+ u_int32_t *address;
+ fpe_reg_t *fpreg;
+{
+ fpe_pprec_t real;
+
+ real = *(fpe_pprec_t *)address;
+ return(1);
+}
+
+
+FPE_INLINE int
+fpetos(address, fpreg)
+ u_int32_t *address;
+ fpe_reg_t *fpreg;
+{
+ fpe_sprec_t real;
+ int exp;
+
+ if (fpreg->mantissa_hi == 0 && fpreg->mantissa_lo == 0
+ && (fpreg->exponent & ~(1<<31)) == 0) {
+ PRINTF(("single=0\n"));
+
+ address[0] = fpreg->exponent & (1<<31);
+ return(0);
+ }
+
+ real.sign = (fpreg->exponent >> 31) & 1;
+ real.mantissa = (fpreg->mantissa_hi >> 8);
+ exp = ((int)(fpreg->exponent & 0x7fff) - 0x4000) + 0x80;
+
+ if (exp < 0 || exp > 0xff) {
+ PRINTF(("ermm exponent out of range !\n"));
+ exp = 0x80;
+ }
+
+ real.exponent = exp;
+
+ PRINTF(("single=%08x\n", *((unsigned int *)&real)));
+
+ *(fpe_sprec_t *)address = real;
+ if (real.sign == 1 && real.mantissa == 0 && real.exponent == 0)
+ printf("single result = %08x", *address);
+ return(0);
+}
+
+
+int
+fpetod(address, fpreg)
+ u_int32_t *address;
+ fpe_reg_t *fpreg;
+{
+ fpe_dprec_t real;
+ u_int32_t *words = (u_int32_t *)ℜ
+ int exp;
+
+ if (fpreg->mantissa_lo == 0 && (fpreg->exponent & ~(1<<31)) == 0) {
+ PRINTF(("double=0\n"));
+
+ address[0] = fpreg->exponent & (1<<31);
+ address[1] = 0;
+ return(0);
+ }
+
+ real.sign = (fpreg->exponent >> 31) & 1;
+ real.mantissa_hi = (fpreg->mantissa_hi >> 11);
+ real.mantissa_lo = (fpreg->mantissa_hi << 21) | (fpreg->mantissa_lo >> 11);
+ exp = ((int)(fpreg->exponent & 0x7fff) - 0x4000) + 0x400;
+
+ if (exp < 0 || exp > 0x7ff) {
+ PRINTF(("ermm exponent out of range !\n"));
+ exp = 0x400;
+ }
+
+ real.exponent = exp;
+
+ PRINTF(("double=%08x%08x\n", words[0], words[1]));
+
+ address[0] = words[0];
+ address[1] = words[1];
+ return(0);
+}
+
+#ifndef FPE_SPEEDUPS
+int
+fpetoe(address, fpreg)
+ u_int32_t *address;
+ fpe_reg_t *fpreg;
+{
+ bcopy((char *)fpreg, (char *)address, 12);
+ return(0);
+}
+#endif
+
+
+int
+fpetop(address, fpreg)
+ u_int32_t *address;
+ fpe_reg_t *fpreg;
+{
+ return(1);
+}
+
+
+/* Unary fp data operations */
+
+/*
+ * int fpe_mvf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * MVF - Move FP register to FP register
+ */
+
+int
+fpe_mvf(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ FPP_INC(FPP_MOV);
+ PRINTF(("MVF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+ fpregs[op->fpregd] = fpregs[op->fpregm];
+ return(0);
+}
+
+
+/*
+* int fpe_mnf(fp_op_data_t *op, trapframe_t *frame)
+*
+* MNF - Move FP register to FP register negated
+*/
+
+int
+fpe_mnf(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[8];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ fpe_qreg_t result;
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_MVN);
+ PRINTF(("MNF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_result = nc_fp_sub(single_a, single_b);
+ stofpe(&single_result, (fpe_reg_t *) &result);
+
+ fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+ return(0);
+}
+
+
+/*
+* int fpe_abs(fp_op_data_t *op, trapframe_t *frame)
+*
+* ABS - Absolute value of a FP register
+*/
+
+int
+fpe_abs(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[8];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ fpe_qreg_t result;
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_ABS);
+ PRINTF(("ABS prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real2);
+ fpetos(&single_b, (fpe_reg_t *) &real1);
+ single_result = nc_fp_cmp(single_a, single_b);
+ if (single_result & 0x80000000) {
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_result = nc_fp_sub(single_a, single_b);
+ stofpe(&single_result, (fpe_reg_t *) &result);
+
+ fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+ } else {
+ fpregs[op->fpregd] = fpregs[op->fpregm];
+ }
+
+ return(0);
+}
+
+
+/* Binary fp data operations */
+
+/*
+ * int fpe_adf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * ADF - Floating point add
+ */
+
+int
+fpe_adf(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ fpe_qreg_t result;
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_ADD);
+ PRINTF(("ADF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_result = nc_fp_add(single_a, single_b);
+ stofpe(&single_result, (fpe_reg_t *) &result);
+ fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+ return(0);
+}
+
+
+/*
+ * int fpe_suf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * SUF - Floating point subtract
+ */
+
+int
+fpe_suf(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ fpe_qreg_t result;
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_SUB);
+ PRINTF(("SUF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_result = nc_fp_sub(single_a, single_b);
+ stofpe(&single_result, (fpe_reg_t *) &result);
+ fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+ return(0);
+}
+
+
+/*
+ * int fpe_muf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * MUF - Floating point multiply
+ */
+
+int
+fpe_muf(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ fpe_qreg_t result;
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_MUL);
+ PRINTF(("MUF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_result = nc_fp_mul(single_a, single_b);
+ stofpe(&single_result, (fpe_reg_t *) &result);
+ fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+ return(0);
+}
+
+
+/*
+ * int fpe_dvf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * DVF - Floating point divide
+ */
+
+int fpe_dvf(fp_op_data_t *op, trapframe_t *frame)
+{
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ fpe_qreg_t result;
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_DIV);
+ PRINTF(("DVF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_result = nc_fp_div(single_a, single_b);
+ stofpe(&single_result, (fpe_reg_t *) &result);
+ fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+ return(0);
+}
+
+
+/*
+ * int fpe_rdf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * RDF - Floating point reverse divide
+ */
+
+int
+fpe_rdf(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+ fpe_qreg_t result;
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_RDV);
+ PRINTF(("RDF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_result = nc_fp_div(single_a, single_b);
+ stofpe(&single_result, (fpe_reg_t *) &result);
+ fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+ return(0);
+}
+
+
+/*
+ * int fpe_rsf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * RSF - Floating point reverse subtract
+ */
+
+int
+fpe_rsf(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+ fpe_qreg_t result;
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_RSB);
+ PRINTF(("RSF prec=%d rnd=%d fd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_result = nc_fp_sub(single_a, single_b);
+ stofpe(&single_result, (fpe_reg_t *) &result);
+ fpregs[op->fpregd] = *(fpe_reg_t *) &result;
+ return(0);
+}
+
+
+/* FPE Register transfer instructions */
+
+/*
+* int fpe_flt(fp_op_data_t *op, trapframe_t *frame)
+*
+* FLT - Integer register to float register
+*/
+
+int
+fpe_flt(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ int regd;
+ fpe_reg_t real;
+ int *regs = &frame->tf_r0;
+
+ FPP_INC(FPP_FLT);
+ PRINTF(("FLT prec=%d rnd=%d rd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->regd, op->fpregn, op->fpregm));
+
+ regd = regs[op->regd];
+
+ if (regd > 0)
+ real.mantissa_lo = regd;
+ else
+ real.mantissa_lo = -regd;
+ real.mantissa_hi = 0;
+
+ if (regd == 0)
+ real.exponent = 0;
+ else {
+ real.exponent = 16383 + 63;
+
+ while ((real.mantissa_hi & (1 << 31)) == 0) {
+ --real.exponent;
+ real.mantissa_hi = real.mantissa_hi << 1;
+ if (real.mantissa_lo & (1 << 31))
+ real.mantissa_hi |= 1;
+ real.mantissa_lo = real.mantissa_lo << 1;
+ }
+ }
+
+ if (regd < 0)
+ real.exponent |= (1 <<31);
+
+ fpregs[op->fpregn] = real;
+
+ return(0);
+}
+
+
+/*
+ * int fpe_fix(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * FIX - Float register to integer register
+ */
+
+int
+fpe_fix(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t src = *(fpe_qreg_t *) &fpregs[op->fpregm];
+ u_int32_t single_argument;
+ unsigned int *regs = &frame->tf_r0;
+
+ FPP_INC(FPP_FIX);
+ PRINTF(("FIX prec=%d rnd=%d rd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->regd, op->fpregn, op->fpregm));
+
+ fpetos(&single_argument, (fpe_reg_t *) &src);
+
+/*
+ * Call the assembler (32-bit) code for now
+ */
+ regs[op->regd] = nc_fp_fix(single_argument);
+ return(0);
+}
+
+
+/*
+ * int fpe_wfs(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * WFS - Write FP status register
+ */
+
+int fpe_wfs(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ unsigned int *regs = &frame->tf_r0;
+
+ PRINTF(("WFS rd=%d\n", op->regd));
+
+ fpe_status = (fpe_status & ~FPE_STATUS_MASK)
+ | (regs[op->regd] & FPE_STATUS_MASK);
+
+ return(0);
+}
+
+
+/*
+* int fpe_rfs(fp_op_data_t *op, trapframe_t *frame)
+*
+* RFS - Read FP status register
+*/
+
+int
+fpe_rfs(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ unsigned int *regs = &frame->tf_r0;
+
+ PRINTF(("RFS rd=%d\n", op->regd));
+
+ regs[op->regd] = fpe_status;
+
+ return(0);
+}
+
+
+/*
+ * int fpe_wfc(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * WFC - Write FP control register
+ */
+
+int
+fpe_wfc(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ unsigned int *regs = &frame->tf_r0;
+
+ PRINTF(("WFC rd=%d\n", op->regd));
+
+ fpe_control = (fpe_control & ~FPE_CONTROL_MASK)
+ | (regs[op->regd] & FPE_CONTROL_MASK);
+
+ return(0);
+}
+
+
+/*
+ * int fpe_rfc(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * RFC - Read FP control register
+ */
+
+int
+fpe_rfc(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ unsigned int *regs = &frame->tf_r0;
+
+ PRINTF(("RFC rd=%d\n", op->regd));
+
+ regs[op->regd] = fpe_control;
+
+ return(0);
+}
+
+
+/*
+ * int fpe_cmf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * CMF - FP compare
+ */
+
+int
+fpe_cmf(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_CMF);
+ PRINTF(("CMF prec=%d rnd=%d rd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->regd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_result = nc_fp_cmp(single_a, single_b);
+ frame->tf_spsr = (frame->tf_spsr & ~0xf0000000) | (single_result & 0xf0000000);
+ return(0);
+}
+
+
+/*
+ * int fpe_cnf(fp_op_data_t *op, trapframe_t *frame)
+ *
+ * CNF - FP compare negated
+ */
+
+int
+fpe_cnf(op, frame)
+ fp_op_data_t *op;
+ trapframe_t *frame;
+{
+ fpe_qreg_t real0 = *(fpe_qreg_t *)&fpregs[8];
+ fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn];
+ fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm];
+ u_int32_t single_a, single_b, single_result;
+
+ FPP_INC(FPP_CNF);
+ PRINTF(("CNF prec=%d rnd=%d rd=%d fn=%d fm=%d\n",
+ op->precision, op->rounding, op->regd, op->fpregn, op->fpregm));
+
+ fpetos(&single_a, (fpe_reg_t *) &real0);
+ fpetos(&single_b, (fpe_reg_t *) &real2);
+ single_b = nc_fp_sub(single_a, single_b);
+
+ fpetos(&single_a, (fpe_reg_t *) &real1);
+ single_result = nc_fp_cmp(single_a, single_b);
+ frame->tf_spsr = (frame->tf_spsr & ~0xf0000000) | (single_result & 0xf0000000);
+ return(0);
+}
+
+
+/*
+ * int fpe_ldfstf(unsigned in instruction, trapframe_t *frame)
+ *
+ * LDF/STF - Load / store FP registers to / from memory
+ */
+
+
+int
+fpe_ldfstf(instruction, frame)
+ unsigned int instruction;
+ trapframe_t *frame;
+{
+ unsigned int *regs = &frame->tf_r0;
+ int offset;
+ int fpreg;
+ int reg;
+ u_int32_t address;
+ int precision;
+ int error = 0;
+
+ offset = (instruction & 0xff) << 2;
+
+ fpreg = (instruction >> 12) & 0x07;
+ reg = (instruction >> 16) & 0x0f;
+ precision = ((instruction & (1<<22)) ? 2 : 0)
+ | ((instruction & (1<<15)) ? 1 : 0);
+
+ if (!(instruction & (1<<23)))
+ offset = -offset;
+
+ if (reg == 15)
+ printf("WARNING: LDF/STF using r15\n");
+
+ address = regs[reg];
+
+ if ((instruction & (1<<24)))
+ address += offset;
+
+ if (!(instruction & (1 << 20))) {
+ PRINTF(("STF rd=%d fd=%d prec=%d offset=%d address = %08x\n",
+ reg, fpreg, precision, offset, address));
+
+ switch(precision) {
+ case 0 :
+ FPP_INC(FPP_STRS);
+ error = fpetos((u_int32_t *)address, &fpregs[fpreg]);
+ break;
+ case 1 :
+ FPP_INC(FPP_STRD);
+ error = fpetod((u_int32_t *)address, &fpregs[fpreg]);
+ break;
+ case 2 :
+ FPP_INC(FPP_STRE);
+ error = fpetoe((u_int32_t *)address, &fpregs[fpreg]);
+ break;
+ case 3 :
+ FPP_INC(FPP_STRP);
+ error = fpetop((u_int32_t *)address, &fpregs[fpreg]);
+ break;
+ }
+ } else {
+ PRINTF(("LDF rd=%d fd=%d prec=%d offset=%d address = %08x\n",
+ reg, fpreg, precision, offset, address));
+
+ switch(precision) {
+ case 0 :
+ FPP_INC(FPP_LDRS);
+ error = stofpe((u_int32_t *)address, &fpregs[fpreg]);
+ break;
+ case 1 :
+ FPP_INC(FPP_LDRD);
+ error = dtofpe((u_int32_t *)address, &fpregs[fpreg]);
+ break;
+ case 2 :
+ FPP_INC(FPP_LDRE);
+ error = etofpe((u_int32_t *)address, &fpregs[fpreg]);
+ break;
+ case 3 :
+ FPP_INC(FPP_LDRP);
+ error = ptofpe((u_int32_t *)address, &fpregs[fpreg]);
+ break;
+ }
+ }
+
+ if (!(instruction & (1<<24)))
+ address += offset;
+
+ if ((instruction & (1<<21)))
+ regs[reg] = address;
+
+ return(error);
+}
+
+
+/* Debugging functions */
+
+int
+fpe_dump()
+{
+ int loop;
+
+ for (loop = 0; loop < 8; loop+=2) {
+ PRINTF(("f%2d : %08x %08x %08x f%2d : %08x %08x %08x\n",
+ loop, fpregs[loop].mantissa_hi,
+ fpregs[loop].mantissa_lo, fpregs[loop].exponent,
+ loop+1, fpregs[loop+1].mantissa_hi,
+ fpregs[loop+1].mantissa_lo, fpregs[loop+1].exponent));
+ }
+ PRINTF(("\x1b[0mFPSR=%08x FPCR=%08x\n", fpe_status, fpe_control));
+ return(0);
+}
+
+
+#ifdef FPE_PROF
+void
+fpe_dump_prof()
+{
+ printf("adf : %6d\n", fp_profile[FPP_ADD]);
+ printf("suf : %6d\n", fp_profile[FPP_SUB]);
+ printf("muf : %6d\n", fp_profile[FPP_MUL]);
+ printf("dvf : %6d\n", fp_profile[FPP_DIV]);
+ printf("cmf : %6d\n", fp_profile[FPP_CMF]);
+ printf("cnf : %6d\n", fp_profile[FPP_CNF]);
+ printf("fix : %6d\n", fp_profile[FPP_FIX]);
+ printf("flt : %6d\n", fp_profile[FPP_FLT]);
+ printf("abs : %6d\n", fp_profile[FPP_ABS]);
+ printf("mvf : %6d\n", fp_profile[FPP_MOV]);
+ printf("mnf : %6d\n", fp_profile[FPP_MVN]);
+ printf("rdf : %6d\n", fp_profile[FPP_RDV]);
+ printf("rsf : %6d\n", fp_profile[FPP_RSB]);
+ printf("strs: %6d\n", fp_profile[FPP_STRS]);
+ printf("strd: %6d\n", fp_profile[FPP_STRD]);
+ printf("stre: %6d\n", fp_profile[FPP_STRE]);
+ printf("strp: %6d\n", fp_profile[FPP_STRP]);
+ printf("ldrs: %6d\n", fp_profile[FPP_LDRS]);
+ printf("ldrd: %6d\n", fp_profile[FPP_LDRD]);
+ printf("ldre: %6d\n", fp_profile[FPP_LDRE]);
+ printf("ldrp: %6d\n", fp_profile[FPP_LDRP]);
+}
+#else
+void
+fpe_dump_prof()
+{
+ printf("kernel not compiled with FPE profiling\n");
+}
+#endif
+
+/* End of fpe.c */
--- /dev/null
+/* $NetBSD: fpeadd.S,v 1.2 1996/03/18 19:58:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fpeadd.S
+ *
+ * FP addition
+ *
+ * Created : 11/02/95
+ */
+
+/* std. registers
+ */
+sp .req r13
+lr .req r14
+pc .req r15
+
+
+.global _nc_fp_add
+
+mant1 .req r2
+xp1 .req r3
+mant2 .req r4
+xp2 .req r5
+wrk1 .req r14
+
+_nc_fp_add:
+ stmfd r13!,{r2-r5,r14}
+ mov xp1,r0,lsr #23 /* get exponent+sign */
+ bic mant1,r0,xp1,lsl #23 /* get mantissa */
+ cmp r0,#0
+ orrne mant1,mant1,#1<<23 /* set on bit to left of point */
+ and xp1,xp1,#255 /* remove sign */
+
+ mov xp2,r1,lsr #23 /* get exponent+sign */
+ bic mant2,r1,xp2,lsl #23 /* get mantissa */
+ cmp r1,#0
+ orrne mant2,mant2,#1<<23 /* set on bit to left of point */
+ and xp2,xp2,#255 /* remove sign */
+
+ eors wrk1,r0,r1 /* both +ve/-ve? */
+ bmi fp_add_neg /* no, unequal signs */
+
+ subs wrk1,xp1,xp2 /* exp. difference */
+ addpl mant1,mant1,mant2,lsr wrk1 /* xp1>exp2, round mant2 down */
+ rsbmi wrk1,wrk1,#0 /* as +ve difference */
+ addmi mant1,mant2,mant1,lsr wrk1 /* xp1<exp2, round mant1 down */
+ movmi xp1,xp2 /* exponent of result */
+ and r0,r0,#1<<31 /* set sign of result */
+ /* normalise mantissa & exponent */
+fp_add_rounddown:
+ cmp mant1,#1<<24
+ blt fp_add_normexit
+ add xp1,xp1,#1
+ mov mant1,mant1,lsr #1
+ b fp_add_rounddown
+
+ /* r0 or r1 is -ve */
+fp_add_neg:
+ subs wrk1,xp1,xp2 /* exp. difference */
+ movpl mant2,mant2,lsr wrk1 /* exp1>xp2, round mant2 */
+ rsbmi wrk1,wrk1,#0 /* as +ve difference */
+ movmi mant1,mant1,lsr wrk1 /* exp1<exp2, round mant1 */
+ movmi xp1,xp2 /* exponent of result */
+
+ tst r0,#1<<31 /* r0 -ve? */
+ subeq mant1,mant1,mant2 /* no, r0=r0-r1 */
+ subne mant1,mant2,mant1 /* yes, r0=r1-r0 */
+ cmp mant1,#0
+ rsbmi mant1,mant1,#0 /* +ve mantissa */
+ movmi r0,#1<<31 /* -ve result */
+ movpl r0,#0 /* +ve result */
+ /* normalise result - adjust mantissa & exponent */
+ cmp mant1,#0 /* check for 0 - special case */
+ moveq r0,#0
+ beq fp_add_exit
+fp_add_roundup:
+ tst mant1,#1<<23
+ bne fp_add_normexit
+ sub xp1,xp1,#1
+ mov mant1,mant1,lsl #1
+ b fp_add_roundup
+ /* combine result */
+fp_add_normexit:
+ orr r0,r0,xp1,lsl #23 /* set exponent */
+ bic mant1,mant1,#1<<23 /* clear hi-order */
+ orr r0,r0,mant1 /* full result */
+fp_add_exit:
+ ldmfd r13!,{r2-r5,pc}
--- /dev/null
+/* $NetBSD: fpecmf.S,v 1.2 1996/03/18 19:58:13 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fpecmf.S
+ *
+ * FP compare
+ *
+ * Created : 11/02/95
+ */
+
+pc .req r15
+
+/* compare r0 with r1. sets status bits (in arm!) for result.*/
+
+ .global _nc_fp_cmp
+
+_nc_fp_cmp:
+ cmp r1,#0 /* r1 -ve? */
+ bmi fp_cmp_r0
+ cmp r0,r1 /* no - do normal cmp */
+ mrs r0, cpsr_all
+ mov pc, r14
+fp_cmp_r0:
+ cmp r0,#0 /* r0 -ve? */
+ bmi fp_cmp_neg /* r0 & r1 -ve */
+ cmp r0,r1
+ mrs r0, cpsr_all
+ mov pc, r14
+fp_cmp_neg:
+ cmp r1,r0 /* opposite compare */
+
+ mrs r0, cpsr_all
+ mov pc, r14
+
--- /dev/null
+/* $NetBSD: fpediv.S,v 1.2 1996/03/18 19:58:14 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fpediv.S
+ *
+ * FP divide
+ *
+ * Created : 11/02/95
+ */
+
+.global _nc_fp_div
+
+pc .req r15
+
+mant1 .req r2
+xp1 .req r3
+mant2 .req r4
+xp2 .req r14
+q .req r1
+p .req r14
+
+_nc_fp_div:
+ stmfd r13!,{r2-r4,r14}
+ /* check for null result */
+ cmp r0,#0
+ cmpne r1,#0
+ moveq r0,#0
+ beq fp_div_exit
+
+ mov xp1,r0,lsr #23 /* get exponent+sign */
+ bic mant1,r0,xp1,lsl #23 /* get mantissa */
+ orr mant1,mant1,#1<<23 /* set on bit to left of point */
+ and xp1,xp1,#255 /* remove sign */
+
+ mov xp2,r1,lsr #23 /* get exponent+sign */
+ bic mant2,r1,xp2,lsl #23 /* get mantissa */
+ orr mant2,mant2,#1<<23 /* set on bit to left of point */
+ and xp2,xp2,#255 /* remove sign */
+
+ sub xp1,xp1,xp2
+ adds xp1,xp1,#127 /* exponent result */
+ movmi r0,#0 /* underflow */
+ bmi fp_div_exit
+ eor r0,r0,r1 /* sign of result */
+ and r0,r0,#1<<31 /* clear rest of result */
+ /* do the divide to full precision */
+ mov q,#0 /* quotient */
+ mov p,#1<<23 /* number binary places to do */
+fp_divloop: /* do binary places */
+ cmp mant1,mant2 /* number>divisor? */
+ orrcs q,q,p /* yes - set bit in binary place */
+ subcs mant1,mant1,mant2 /* discard accounted value */
+ movs mant1,mant1,lsl #1 /* shift up remainder, if any */
+ movnes p,p,lsr#1 /* next binary place, if remainder */
+ bne fp_divloop /* next place if any */
+
+ cmp q,#1<<23 /* normalise? */
+ sublt xp1,xp1,#1 /* yes, adjust exponent */
+ movlt q,q,lsl #1 /* & mantissa */
+ /* combine result */
+ orr r0,r0,xp1,lsl #23 /* set exponent */
+ bic q,q,#1<<23 /* clear hi-order */
+ orr r0,r0,q /* result */
+fp_div_exit:
+ ldmfd r13!,{r2-r4,pc}
+
--- /dev/null
+/* $NetBSD: fpefix.S,v 1.2 1996/03/18 19:58:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fpefix.S
+ *
+ * FP register to integer
+ *
+ * Created : 11/02/95
+ */
+
+/* std. registers
+ */
+sp .req r13
+lr .req r14
+pc .req r15
+
+
+mant1 .req r0
+xp1 .req r1
+
+ .global _nc_fp_fix
+
+_nc_fp_fix:
+ cmp r0,#0
+ moveq pc,r14
+ mov xp1,r0,lsr #23
+ bic mant1,r0,xp1,lsl #23
+ orr mant1,mant1,#1<<23
+ tst xp1,#1<<8
+ rsbne mant1,mant1,#0
+ bic xp1,xp1,#1<<8
+ subs xp1,xp1,#127
+ movmi r0,#0
+ movmi pc,r14
+ rsbs xp1,xp1,#23
+ movpl mant1,mant1,asr xp1
+ rsbmi xp1,xp1,#0
+ movmi mant1,mant1,asl xp1
+ mov pc,r14
--- /dev/null
+/* $NetBSD: fpemul.S,v 1.2 1996/03/18 19:58:16 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fpemul.S
+ *
+ * FP multiply
+ *
+ * Created : 11/02/95
+ */
+
+.global _nc_fp_mul
+
+pc .req r15
+
+mant1 .req r2
+xp1 .req r3
+mant2 .req r1
+xp2 .req r4
+wrk1 .req r14
+reshigh .req r4
+
+_nc_fp_mul:
+ stmfd r13!,{r2-r4,r14}
+ /* check for null result - bloody lucky but you never know... */
+ cmp r0,#0
+ cmpne r1,#0
+ moveq r0,#0
+ beq fp_mul_exit
+
+ mov xp1,r0,lsr #23 /* get exponent+sign */
+ bic mant1,r0,xp1,lsl #23 /* get mantissa */
+ orr mant1,mant1,#1<<23 /* set on bit to left of point */
+ and xp1,xp1,#255 /* remove sign */
+
+ eor r0,r0,r1 /* sign of result */
+ and r0,r0,#1<<31 /* clear rest of result */
+
+ mov xp2,r1,lsr #23 /* get exponent+sign */
+ bic mant2,r1,xp2,lsl #23 /* get mantissa */
+ orr mant2,mant2,#1<<23 /* set on bit to left of point */
+ and xp2,xp2,#255 /* remove sign */
+
+ add xp1,xp1,xp2
+ subs xp1,xp1,#127 /* exponent result */
+ movmi r0,#0 /* underflow */
+ bmi fp_mul_exit
+ /* do the multiply to 30 bits precision */
+ mov wrk1,mant1,lsr#9 /* top 15 bits */
+ mov reshigh,mant2,lsr#9 /* top 15 bits */
+ bic mant1,mant1,wrk1,lsl#9 /* low 9 bits */
+ bic mant2,mant2,reshigh,lsl#9 /* low 9 bits */
+ mul mant2,wrk1,mant2 /* top*low */
+ mul mant1,reshigh,mant1 /* low*top */
+ mul reshigh,wrk1,reshigh /* top*top */
+ add reshigh,reshigh,mant1,lsr#9 /* top + middle bit1 */
+ add reshigh,reshigh,mant2,lsr#9 /* top + middle bit2 */
+ /* adjust for carry */
+ tst reshigh,#1<<29
+ addne xp1,xp1,#1 /* adjust exponent */
+ movne reshigh,reshigh,lsr#1 /* shift result right */
+ /* combine result */
+ orr r0,r0,xp1,lsl #23 /* set exponent */
+ bic reshigh,reshigh,#1<<28 /* clear hi-order */
+ orr r0,r0,reshigh,lsr #5 /* top 23 bits */
+fp_mul_exit:
+ ldmfd r13!,{r2-r4,pc}
--- /dev/null
+/* $NetBSD: fpesub.S,v 1.2 1996/03/18 19:58:18 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fpesub.S
+ *
+ * FP subtract
+ *
+ * Created : 11/02/95
+ */
+
+.global _nc_fp_sub
+
+pc .req r15
+
+mant1 .req r2
+xp1 .req r3
+mant2 .req r4
+xp2 .req r5
+wrk1 .req r14
+
+_nc_fp_sub:
+ stmfd r13!,{r2-r5,r14}
+ mov xp1,r0,lsr #23 /* get exponent+sign */
+ bic mant1,r0,xp1,lsl #23 /* get mantissa */
+ cmp r0,#0
+ orrne mant1,mant1,#1<<23 /* set on bit to left of point */
+ and xp1,xp1,#255 /* remove sign */
+
+ mov xp2,r1,lsr #23 /* get exponent+sign */
+ bic mant2,r1,xp2,lsl #23 /* get mantissa */
+ cmp r1,#0
+ orrne mant2,mant2,#1<<23 /* set on bit to left of point */
+ and xp2,xp2,#255 /* remove sign */
+
+ eors wrk1,r0,r1 /* both +ve/-ve? */
+ bmi fp_sub_unequal /* no - special case */
+
+ subs wrk1,xp1,xp2 /* exp. difference */
+ subpl mant1,mant1,mant2,lsr wrk1 /* exp1>exp2, round mant2 & subtract */
+ rsbmi wrk1,wrk1,#0 /* as +ve difference */
+ rsbmi mant1,mant2,mant1,lsr wrk1 /* exp1<exp2, round mant1 & subtract */
+ movmi xp1,xp2 /* exponent of result */
+ and r0,r0,#1<<31 /* default sign of result */
+ cmp mant1,#0 /* flip sign? */
+ rsbmi mant1,mant1,#0 /* yes - flip mantissa */
+ eormi r0,r0,#1<<31 /* and final sign */
+ /* normalise result - adjust mantissa & exponent */
+ cmp mant1,#0 /* check for 0 - special case */
+ moveq r0,#0
+ beq fp_sub_exit
+fp_sub_roundup:
+ tst mant1,#1<<23
+ bne fp_sub_normexit
+ sub xp1,xp1,#1
+ mov mant1,mant1,lsl #1
+ b fp_sub_roundup
+
+ /* r0 & r1 have different signs - add */
+fp_sub_unequal:
+ subs wrk1,xp1,xp2 /* exp. difference */
+ addpl mant1,mant1,mant2,lsr wrk1 /* exp1>exp2, round mant2 & add */
+ rsbmi wrk1,wrk1,#0 /* as +ve difference */
+ addmi mant1,mant2,mant1,lsr wrk1 /* exp1<exp2, round mant1 & add */
+ movmi xp1,xp2 /* exponent of result */
+ and r0,r0,#1<<31 /* sign of result */
+ /* normalise result - adjust mantissa & exponent */
+fp_sub_rounddown:
+ cmp mant1,#1<<24
+ blt fp_sub_normexit
+ add xp1,xp1,#1
+ mov mant1,mant1,lsr #1
+ b fp_sub_rounddown
+ /* combine result */
+fp_sub_normexit:
+ orr r0,r0,xp1,lsl #23 /* set exponent */
+ bic mant1,mant1,#1<<23 /* clear hi-order */
+ orr r0,r0,mant1 /* full result */
+fp_sub_exit:
+ ldmfd r13!,{r2-r5,pc}
+
--- /dev/null
+/* $NetBSD: fpetoe.S,v 1.2 1996/03/18 19:58:19 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Neil Carson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fpetoe.S
+ *
+ * optimised functions for coping extended precision registers
+ *
+ * Created : 11/02/95
+ */
+
+lr .req r14
+pc .req r15
+
+ .text
+ .align 0
+ .global _etofpe
+_etofpe:
+ ldmia r0, {r0, r2-r3}
+ stmia r1, {r0, r2-r3}
+ mov r0, #0
+ mov pc, r14
+
+ .align 0
+ .global _fpetoe
+_fpetoe:
+ ldmia r1, {r1, r2-r3}
+ stmia r0, {r1, r2-r3}
+ mov r0, #0
+ mov pc, r14
--- /dev/null
+/* $NetBSD: ansi.h,v 1.3 1996/03/16 01:31:48 jtc Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ansi.h 8.2 (Berkeley) 1/4/94
+ */
+
+#ifndef _ANSI_H_
+#define _ANSI_H_
+
+/*
+ * Types which are fundamental to the implementation and may appear in
+ * more than one standard header are defined here. Standard headers
+ * then use:
+ * #ifdef _BSD_SIZE_T_
+ * typedef _BSD_SIZE_T_ size_t;
+ * #undef _BSD_SIZE_T_
+ * #endif
+ */
+#define _BSD_CLOCK_T_ unsigned long /* clock() */
+#define _BSD_PTRDIFF_T_ int /* ptr1 - ptr2 */
+#define _BSD_SIZE_T_ unsigned int /* sizeof() */
+#define _BSD_SSIZE_T_ int /* byte count or error */
+#define _BSD_TIME_T_ long /* time() */
+#define _BSD_VA_LIST_ char * /* va_list */
+
+/*
+ * Runes (wchar_t) is declared to be an ``int'' instead of the more natural
+ * ``unsigned long'' or ``long''. Two things are happening here. It is not
+ * unsigned so that EOF (-1) can be naturally assigned to it and used. Also,
+ * it looks like 10646 will be a 31 bit standard. This means that if your
+ * ints cannot hold 32 bits, you will be in trouble. The reason an int was
+ * chosen over a long is that the is*() and to*() routines take ints (says
+ * ANSI C), but they use _RUNE_T_ instead of int. By changing it here, you
+ * lose a bit of ANSI conformance, but your programs will still work.
+ *
+ * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type. When wchar_t
+ * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains
+ * defined for ctype.h.
+ */
+#define _BSD_WCHAR_T_ int /* wchar_t */
+#define _BSD_WINT_T_ int /* wint_t */
+#define _BSD_RUNE_T_ int /* rune_t */
+
+#endif /* _ANSI_H_ */
--- /dev/null
+/* $NetBSD: asm.h,v 1.2 1996/03/14 23:11:03 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)asm.h 5.5 (Berkeley) 5/7/91
+ */
+
+#ifndef _ARM32_ASM_H_
+#define _ARM32_ASM_H_
+
+#ifdef PROF
+/*
+ * XXX assumes that arguments are not passed in %eax
+ */
+# define _BEGIN_ENTRY /*.data; 1:; .long 0;*/ .text; .align 0
+# define _END_ENTRY /*movl $1b,%eax; call PIC_PLT(mcount)*/
+#else
+# define _BEGIN_ENTRY .text; .align 0
+# define _END_ENTRY
+#endif
+
+#ifdef __STDC__
+# define _C_FUNC(x) _ ## x
+#else
+# define _C_FUNC(x) _/**/x
+#endif
+#define _ASM_FUNC(x) x
+
+#define _ENTRY(x) .globl x; /*.type x,@function;*/ x:
+
+#define ENTRY(y) _BEGIN_ENTRY; _ENTRY(_C_FUNC(y)); _END_ENTRY
+#define TWOENTRY(y,z) _BEGIN_ENTRY; _ENTRY(_C_FUNC(y)); _ENTRY(_C_FUNC(z)); \
+ _END_ENTRY
+#define ASENTRY(y) _BEGIN_ENTRY; _ENTRY(_ASM_FUNC(y)); _END_ENTRY
+
+#define ASMSTR .asciz
+
+#define RCSID(x) .text; .asciz x
+
+#endif /* !_ARM_ASM_H_ */
--- /dev/null
+/* $NetBSD: beep.h,v 1.2 1996/03/14 23:11:04 mark Exp $ */
+
+/*
+ * Copyright (c) Mark Brinicombe 1995 All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+struct wavebuffer {
+ caddr_t addr;
+ int size;
+};
+
+#define BEEP_GENERATE _IO ( 'B', 100)
+#define BEEP_SETRATE _IO ( 'B', 101)
+#define BEEP_SET _IOW ( 'B', 102, struct wavebuffer )
+
+/* End of beep.h */
--- /dev/null
+/* $NetBSD: bootconfig.h,v 1.2 1996/03/14 23:11:06 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * bootconfig.h
+ *
+ * boot configuration structure
+ *
+ * Created : 12/09/94
+ *
+ * Based on kate/boot/bootconfig.h
+ */
+
+typedef struct _PhysMem {
+ u_int address;
+ u_int pages;
+} PhysMem;
+
+typedef struct _BootConfig {
+ u_int kernvirtualbase;
+ u_int kernphysicalbase;
+ u_int kernsize;
+ u_int argvirtualbase;
+ u_int argphysicalbase;
+ u_int argsize;
+ u_int scratchvirtualbase;
+ u_int scratchphysicalbase;
+ u_int scratchsize;
+
+ u_int display_start;
+ u_int display_size;
+ u_int width;
+ u_int height;
+ u_int bitsperpixel;
+
+ PhysMem dram[4];
+ PhysMem vram[1];
+
+ u_int dramblocks;
+ u_int vramblocks;
+ u_int pagesize;
+ u_int drampages;
+ u_int vrampages;
+
+ char kernelname[80];
+
+ u_int framerate;
+ u_char machine_id[4];
+} BootConfig;
+
+#ifdef _KERNEL
+extern BootConfig bootconfig;
+#endif
+
+/* End of bootconfig.h */
--- /dev/null
+/* $NetBSD: cdefs.h,v 1.1 1996/01/31 23:21:36 mark Exp $ */
+
+/*
+ * Written by J.T. Conklin <jtc@wimsey.com> 01/17/95.
+ * Public domain.
+ */
+
+#ifndef _MACHINE_CDEFS_H_
+#define _MACHINE_CDEFS_H_
+
+#ifdef __STDC__
+#define _C_LABEL(x) _STRING(_ ## x)
+#else
+#define _C_LABEL(x) _STRING(_/**/x)
+#endif
+
+#ifdef __GNUC__
+#ifdef __STDC__
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_" #alias "\",11,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs \"" msg "\",30,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#else
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_/**/alias\",11,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs msg,30,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#endif
+#endif
+
+#endif /* !_MACHINE_CDEFS_H_ */
--- /dev/null
+/* $NetBSD: cpu.h,v 1.6 1996/04/02 21:45:25 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * cpu.h
+ *
+ * CPU specific symbols
+ *
+ * Created : 18/09/94
+ *
+ * Based on kate/katelib/arm6.h
+ */
+
+#ifndef _ARM32_CPU_H_
+#define _ARM32_CPU_H_
+
+#ifndef _LOCORE
+#include <machine/frame.h>
+#endif
+#include <machine/psl.h>
+
+/*
+ * If we are not an ARM6 then we MUST use late aborts as only the ARM6
+ * supports early aborts.
+ * For the ARM6 we will use early abort unless otherwise configured
+ * This reduces the overheads of LDR/STR aborts and no correction is required.
+ */
+
+#ifndef CPU_ARM6
+#define CPU_LATE_ABORTS
+#endif
+
+#define COPY_SIGCODE /* copy sigcode above user stack in exec */
+
+/*
+ * ARM Process Status Register
+ *
+ * The picture in the ARM manuals looks like this:
+ * 3 3 2 2 2
+ * 1 0 9 8 7 8 7 6 5 4 0
+ * +-------+---------------------------------------+-+-+-+---------+
+ * | flags | reserved |I|F| |M M M M M|
+ * |n z c v| | | | |4 3 2 1 0|
+ * +-------+---------------------------------------+-+-+-+---------+
+ */
+
+#define PSR_FLAGS 0xf0000000 /* flags */
+#define PSR_N_bit (1 << 31) /* negative */
+#define PSR_Z_bit (1 << 30) /* zero */
+#define PSR_C_bit (1 << 29) /* carry */
+#define PSR_V_bit (1 << 28) /* overflow */
+
+#define I32_bit (1 << 7)
+#define F32_bit (1 << 6)
+
+#define PSR_MODE 0x0000001f
+#define PSR_USR32_MODE 0x00000010
+#define PSR_FIQ32_MODE 0x00000011
+#define PSR_IRQ32_MODE 0x00000012
+#define PSR_SVC32_MODE 0x00000013
+#define PSR_ABT32_MODE 0x00000017
+#define PSR_UND32_MODE 0x0000001b
+
+#define CPU_ID_DESIGNER_MASK 0xff000000
+#define CPU_ID_ARM_LTD 0x41000000
+#define CPU_ID_DEC 0x44000000
+#define CPU_ID_MAKER_MASK 0x00ff0000
+#define CPU_ID_GPS 0x00560000
+#define CPU_ID_VLSI 0x00000000
+#define CPU_ID_CPU_MASK 0x0000fff0
+#define ID_ARM610 0x00000610
+#define ID_ARM700 0x00007000
+#define ID_ARM710 0x00007100
+#define ID_SARM110 0x0000a100
+#define CPU_ID_REVISION_MASK 0x0000000f
+
+#define CPU_CONTROL_MMU_ENABLE 0x0001
+#define CPU_CONTROL_AFLT_ENABLE 0x0002
+#define CPU_CONTROL_DC_ENABLE 0x0004
+#define CPU_CONTROL_WBUF_ENABLE 0x0008
+#define CPU_CONTROL_32BP_ENABLE 0x0010
+#define CPU_CONTROL_32BD_ENABLE 0x0020
+#define CPU_CONTROL_LABT_ENABLE 0x0040
+#define CPU_CONTROL_BEND_ENABLE 0x0080
+#define CPU_CONTROL_SYST_ENABLE 0x0100
+#define CPU_CONTROL_ROM_ENABLE 0x0200
+#define CPU_CONTROL_CPCLK 0x0400
+#define CPU_CONTROL_IC_ENABLE 0x1000
+
+/* StrongARM has separate instruction and data caches */
+
+#ifdef CPU_SA
+#define CPU_CONTROL_IDC_ENABLE (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE)
+#else
+#define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE
+#endif
+
+#define FAULT_TYPE_MASK 0x0f
+#define FAULT_USER 0x10
+
+#define FAULT_WRTBUF_0 0x00
+#define FAULT_WRTBUF_1 0x02
+#define FAULT_BUSERR_0 0x04
+#define FAULT_BUSERR_1 0x06
+#define FAULT_BUSERR_2 0x08
+#define FAULT_BUSERR_3 0x0a
+#define FAULT_ALIGN_0 0x01
+#define FAULT_ALIGN_1 0x03
+#define FAULT_BUSTRNL1 0x0c
+#define FAULT_BUSTRNL2 0x0e
+#define FAULT_TRANS_S 0x05
+#define FAULT_TRANS_P 0x07
+#define FAULT_DOMAIN_S 0x09
+#define FAULT_DOMAIN_P 0x0b
+#define FAULT_PERM_S 0x0d
+#define FAULT_PERM_P 0x0f
+
+#ifdef _LOCORE
+#define IRQdisable \
+ stmfd sp!, {r0} ; \
+ mrs r0, cpsr_all ; \
+ orr r0, r0, #(I32_bit | F32_bit) ; \
+ msr cpsr_all, r0 ; \
+ ldmfd sp!, {r0}
+
+#define IRQenable \
+ stmfd sp!, {r0} ; \
+ mrs r0, cpsr_all ; \
+ bic r0, r0, #(I32_bit | F32_bit) ; \
+ msr cpsr_all, r0 ; \
+ ldmfd sp!, {r0}
+
+#else
+#define IRQdisable SetCPSR(I32_bit | F32_bit, I32_bit | F32_bit);
+#define IRQenable SetCPSR(I32_bit | F32_bit, 0);
+#endif /* _LOCORE */
+
+/*
+ * Return TRUE/FALSE (1/0) depending on whether the frame came from USR
+ * mode or not.
+ */
+
+#define CLKF_USERMODE(frame) ((frame->if_spsr & PSR_MODE) == PSR_USR32_MODE)
+
+#define CLKF_BASEPRI(frame) (1)
+
+#define CLKF_PC(frame) (frame->if_pc)
+
+/*#define CLKF_INTR(frame) ((frame->if_spsr & PSR_MODE) == PSR_IRQ32_MODE)*/
+
+/* Hack to treat FPE time as interrupt time so we can measure it */
+#define CLKF_INTR(frame) ((frame->if_spsr & PSR_MODE) == PSR_UND32_MODE)
+
+/*
+ * definitions of cpu-dependent requirements
+ * referenced in generic code
+ */
+
+#define cpu_wait(p) /* nothing */
+
+/*
+ * Notify the current process (p) that it has a signal pending,
+ * process as soon as possible.
+ */
+
+#define signotify(p) setsoftast()
+
+#endif /* _ARM32_CPU_H_ */
+
+/* End of cpu.h */
--- /dev/null
+/* $NetBSD: cpus.h,v 1.3 1996/03/14 23:11:08 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * cpus.h
+ *
+ * cpu device header file
+ *
+ * Created : 26/12/95
+ */
+
+#ifndef _LOCORE
+#include <sys/param.h>
+#endif
+
+/* If hydra is defined then we take into consideration the slave CPU's available */
+
+#ifdef HYDRA
+#define MAX_CPUS 6
+#define MAX_SLAVE_CPUS 4
+#define MAX_FOREIGN_CPUS 1
+#else
+#define MAX_CPUS 2
+#define MAX_SLAVE_CPUS 0
+#define MAX_FOREIGN_CPUS 1
+#endif
+
+#define CPU_MASTER 0
+#define CPU_486 1
+#define CPU_SLAVE 2
+
+#define CPU_CLASS_NONE 0 /* No CPU */
+#define CPU_CLASS_ARM 1 /* ARM 6/7/8 */
+#define CPU_CLASS_SARM 2 /* Guess */
+#define CPU_CLASS_I486 3 /* 486/586 */
+
+#define CPU_HOST_NONE 0 /* No host */
+#define CPU_HOST_MAINBUS 1 /* Hosted via motherboard */
+#define CPU_HOST_HYDRA 2 /* Hosted via hydra multiprocessor board */
+
+#define CPU_FLAG_PRESENT 0x01
+#define CPU_FLAG_HALTED 0x02
+
+#define FPU_CLASS_NONE 0 /* no Floating point support */
+#define FPU_CLASS_FPE 1 /* Floating point emulator installed */
+#define FPU_CLASS_FPA 2 /* Floating point accelerator installed */
+#define FPU_CLASS_FPU 3 /* Floating point unit installed */
+
+#define FPU_TYPE_SP_FPE 1 /* Single precision FPE */
+#define FPU_TYPE_ARMLTD_FPE 2 /* ARM Ltd FPE */
+#define FPU_TYPE_FPA11 0x81 /* ID of FPA11 */
+
+#ifndef _LOCORE
+
+/* Define the structure used to describe a cpu */
+
+typedef struct cpu_arm {
+ u_int cpu_id; /* The CPU id */
+ u_int cpu_ctrl; /* The CPU control register */
+
+ u_int cpu_svc_r13; /* local data */
+ u_int cpu_und_r13; /* local data */
+ u_int cpu_abt_r13; /* local data */
+ u_int cpu_irq_r13; /* local data */
+} cpu_arm_t;
+
+typedef struct cpu_sarm {
+ u_int cpu_id; /* The CPU id */
+ u_int cpu_ctrl; /* The CPU control register */
+} cpu_sarm_t;
+
+typedef struct cpu_i486 {
+ u_int cpu_id; /* The CPU id */
+ u_int cpu_ctrl; /* The CPU control register */
+} cpu_i486_t;
+
+
+typedef struct _cpu {
+/* These are generic CPU variables */
+
+ u_int cpu_class; /* The CPU class */
+ u_int cpu_type; /* The CPU type */
+ u_int cpu_host; /* The CPU host interface */
+ u_int cpu_flags; /* The CPU flags */
+ char cpu_model[256]; /* Text description of CPU */
+
+/* These are generic FPU variables */
+
+ u_int fpu_class; /* The FPU class */
+ u_int fpu_type; /* The FPU type */
+ u_int fpu_flags; /* The FPU flags */
+ char fpu_model[256]; /* Text description of FPU */
+
+/* These are ARM specific variables */
+
+ u_int cpu_id; /* The CPU id */
+ u_int cpu_ctrl; /* The CPU control register */
+
+ u_int cpu_svc_r13; /* local data */
+ u_int cpu_und_r13; /* local data */
+ u_int cpu_abt_r13; /* local data */
+ u_int cpu_irq_r13; /* local data */
+
+/* Not used yet */
+
+ union {
+ cpu_arm_t cpu_arm;
+ cpu_sarm_t cpu_sarm;
+ cpu_i486_t cpu_i486;
+ } cpu_local;
+} cpu_t;
+
+
+struct cpu_softc {
+ struct device sc_device;
+ int sc_open;
+};
+
+#ifdef _KERNEL
+
+/* Array of cpu structures, one per possible cpu */
+
+extern cpu_t cpus[MAX_CPUS];
+
+#endif /* _KERNEL */
+#endif /* _LOCORE */
+
+/* End of hydra.h */
--- /dev/null
+/* $NetBSD: db_machdep.h,v 1.2 1996/03/06 23:16:54 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Scott K Stevens
+ *
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef _ARM32_DB_MACHDEP_H_
+#define _ARM32_DB_MACHDEP_H_
+
+/*
+ * Machine-dependent defines for new kernel debugger.
+ */
+
+
+#include <vm/vm.h>
+#include <machine/frame.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+/* end of mangling */
+
+typedef vm_offset_t db_addr_t; /* address - unsigned */
+typedef int db_expr_t; /* expression - signed */
+
+typedef struct {
+ trapframe_t ddb_tf;
+} db_regs_t;
+
+db_regs_t ddb_regs; /* register state */
+#define DDB_REGS (&ddb_regs)
+#define DDB_TF (&ddb_regs.ddb_tf)
+
+#define PC_REGS(regs) ((db_addr_t)(regs)->ddb_tf.tf_pc)
+
+#define BKPT_INST (0xe7ffffff) /* breakpoint instruction */
+#define BKPT_SIZE (4) /* size of breakpoint inst */
+#define BKPT_SET(inst) (BKPT_INST)
+
+/*#define db_clear_single_step(regs) (0)
+#define db_set_single_step(regs) (0)*/
+
+#define T_BREAKPOINT (1)
+
+#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAKPOINT)
+#define IS_WATCHPOINT_TRAP(type, code) (0)
+
+#define inst_trap_return(ins) ((ins)&0)
+#define inst_return(ins) ((ins)&0)
+#define inst_call(ins) (((ins) & 0x0f000000) == 0x0b000000)
+#define inst_branch(ins) (((ins) & 0x0f000000) == 0x0a000000)
+#define inst_load(ins) 0
+#define inst_store(ins) 0
+
+#define getreg_val (0)
+#define next_instr_address(pc, bd) (pc + 4)
+
+#define DB_MACHINE_COMMANDS
+
+#define SOFTWARE_SSTEP
+
+#endif /* _ARM32_DB_MACHDEP_H_ */
--- /dev/null
+/* $NetBSD: disklabel.h,v 1.2 1996/03/06 23:17:51 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * disklabel.h
+ *
+ * machine specific disk label info
+ *
+ * Created : 04/10/94
+ */
+
+#ifndef _ARM32_DISKLABEL_H_
+#define _ARM32_DISKLABEL_H_
+
+#define LABELSECTOR 1 /* sector containing label */
+#define LABELOFFSET 0 /* offset of label in sector */
+#define MAXPARTITIONS 8 /* number of partitions */
+#define RAW_PART 2 /* raw partition: XX?c */
+
+#define NRISCBSD_PARTITIONS MAXPARTITIONS
+
+#define PARTITION_TYPE_UNUSED 0
+#define PARTITION_TYPE_ADFS 1
+#define PARTITION_TYPE_RISCIX 2
+
+#define PARTITION_FORMAT_RISCIX 2
+#define PARTITION_FORMAT_RISCBSD 0x42
+
+#define FILECORE_BOOT_SECTOR 6
+
+/* Stuff to deal with RISCiX partitions */
+
+#define NRISCIX_PARTITIONS 8
+#define RISCIX_PARTITION_OFFSET 8
+
+struct riscix_partition {
+ u_int rp_start;
+ u_int rp_length;
+ u_int rp_type;
+ char rp_name[16];
+};
+
+struct riscix_partition_table {
+ u_int pad0;
+ u_int pad1;
+ struct riscix_partition partitions[NRISCIX_PARTITIONS];
+};
+
+
+#include <sys/dkbad.h>
+
+struct riscbsd_partition {
+ u_int rp_start;
+ u_int rp_length;
+ u_int rp_type;
+ char rp_name[16];
+};
+
+struct cpu_disklabel {
+ u_int pad0;
+ u_int pad1;
+ struct riscbsd_partition partitions[NRISCBSD_PARTITIONS];
+ struct dkbad bad;
+};
+
+struct filecore_bootblock {
+ u_char padding0[0x1c0];
+ u_char log2secsize;
+ u_char secspertrack;
+ u_char heads;
+ u_char density;
+ u_char idlen;
+ u_char log2bpmb;
+ u_char skew;
+ u_char bootoption;
+ u_char lowsector;
+ u_char nzones;
+ u_short zone_spare;
+ u_int root;
+ u_int disc_size;
+ u_short disc_id;
+ u_char disc_name[10];
+ u_int disc_type;
+
+ u_char padding1[24];
+
+ u_char partition_type;
+ u_char partition_cyl_low;
+ u_char partition_cyl_high;
+ u_char checksum;
+};
+
+#ifdef _KERNEL
+struct disklabel;
+int bounds_check_with_label __P((struct buf *, struct disklabel *, int));
+#endif /* _KERNEL */
+
+#endif /* _ARM32_DISKLABEL_H_ */
+
+/* End of disklabel.h */
--- /dev/null
+/* $NetBSD: endian.h,v 1.2 1996/03/14 23:11:10 mark Exp $ */
+
+/*
+ * Copyright (c) 1987, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)endian.h 7.8 (Berkeley) 4/3/91
+ */
+
+#ifndef _MACHINE_ENDIAN_H_
+#define _MACHINE_ENDIAN_H_
+
+/*
+ * Define the order of 32-bit words in 64-bit words.
+ */
+#define _QUAD_HIGHWORD 1
+#define _QUAD_LOWWORD 0
+
+
+#ifndef _POSIX_SOURCE
+/*
+ * Definitions for byte order, according to byte significance from low
+ * address to high.
+ */
+#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */
+#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */
+#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */
+
+#define BYTE_ORDER LITTLE_ENDIAN
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+unsigned long htonl __P((unsigned long));
+unsigned short htons __P((unsigned short));
+unsigned long ntohl __P((unsigned long));
+unsigned short ntohs __P((unsigned short));
+__END_DECLS
+
+/*
+ * Macros for network/external number representation conversion.
+ */
+#define NTOHL(x) (x) = ntohl((unsigned long)(x))
+#define NTOHS(x) (x) = ntohs((unsigned short)(x))
+#define HTONL(x) (x) = htonl((unsigned long)(x))
+#define HTONS(x) (x) = htons((unsigned short)(x))
+
+#endif /* _POSIX_SOURCE */
+
+#endif /* _MACHINE_ENDIAN_H_ */
--- /dev/null
+/* $NetBSD: exec.h,v 1.2 1996/03/14 23:11:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM32_EXEC_H_
+#define _ARM32_EXEC_H_
+
+#define __LDPGSZ 4096
+
+/* Relocation format. */
+
+struct relocation_info_arm6 {
+ int r_address; /* offset in text or data segment */
+ unsigned int r_symbolnum : 24, /* ordinal number of add symbol */
+ r_pcrel : 1, /* 1 if value should be pc-relative */
+ r_length : 2, /* log base 2 of value's width */
+ r_extern : 1, /* 1 if need to add symbol to value */
+ r_baserel : 1, /* linkage table relative */
+ r_jmptable : 1, /* relocate to jump table */
+ r_relative : 1, /* load address relative */
+ r_copy : 1; /* run time copy */
+};
+
+#define relocation_info relocation_info_arm6
+
+/* No special executable format */
+#define cpu_exec_aout_makecmds(a, b) ENOEXEC
+
+#endif /* _ARM_EXEC_H_ */
--- /dev/null
+/* $NetBSD: float.h,v 1.2 1996/03/14 23:11:13 mark Exp $ */
+
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)float.h 7.1 (Berkeley) 5/8/90
+ */
+
+/*extern int __flt_rounds();*/
+#define FLT_RADIX 2 /* b */
+/*#define FLT_ROUNDS __flt_rounds()*/
+#define FLT_ROUNDS 1
+
+#define FLT_MANT_DIG 24 /* p */
+#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */
+#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */
+#define FLT_MIN_EXP (-125) /* emin */
+#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */
+#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */
+#define FLT_MAX_EXP 128 /* emax */
+#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */
+#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */
+
+#define DBL_MANT_DIG 53
+#define DBL_EPSILON 2.2204460492503131E-16
+#define DBL_DIG 15
+#define DBL_MIN_EXP (-1021)
+#define DBL_MIN 2.2250738585072014E-308
+#define DBL_MIN_10_EXP (-307)
+#define DBL_MAX_EXP 1024
+#define DBL_MAX 1.7976931348623157E+308
+#define DBL_MAX_10_EXP 308
+
+#define LDBL_MANT_DIG DBL_MANT_DIG
+#define LDBL_EPSILON DBL_EPSILON
+#define LDBL_DIG DBL_DIG
+#define LDBL_MIN_EXP DBL_MIN_EXP
+#define LDBL_MIN DBL_MIN
+#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+#define LDBL_MAX_EXP DBL_MAX_EXP
+#define LDBL_MAX DBL_MAX
+#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
--- /dev/null
+/* $NetBSD: fp.h,v 1.2 1996/03/14 23:11:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * fp.h
+ *
+ * FP info
+ *
+ * Created : 10/10/95
+ */
+
+#ifndef __ARM32_FP_H
+#define __ARM32_FP_H
+
+typedef struct {
+ u_int32_t fp_exp;
+ u_int32_t fp_man_hi;
+ u_int32_t fp_man_lo;
+} fp_reg_t;
+
+struct fp_state {
+ unsigned int fp_flags;
+ unsigned int fp_sr;
+ unsigned int fp_cr;
+ fp_reg_t fp_registers[16];
+};
+
+#endif
+
+/* End of fp.h */
--- /dev/null
+/* $NetBSD: frame.h,v 1.3 1996/03/13 21:06:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * frame.h
+ *
+ * Stack frames structures
+ *
+ * Created : 30/09/94
+ */
+
+#ifndef _ARM32_FRAME_H_
+#define _ARM32_FRAME_H_
+
+#include <sys/signal.h>
+
+/*
+ * System stack frames.
+ */
+
+typedef struct irqframe {
+ unsigned int if_spsr;
+ unsigned int if_r0;
+ unsigned int if_r1;
+ unsigned int if_r2;
+ unsigned int if_r3;
+ unsigned int if_r4;
+ unsigned int if_r5;
+ unsigned int if_r6;
+ unsigned int if_r7;
+ unsigned int if_r8;
+ unsigned int if_r9;
+ unsigned int if_r10;
+ unsigned int if_r11;
+ unsigned int if_r12;
+ unsigned int if_usr_sp;
+ unsigned int if_usr_lr;
+ unsigned int if_svc_lr;
+ unsigned int if_pc;
+} irqframe_t;
+
+#define clockframe irqframe
+
+typedef struct trapframe {
+ unsigned int tf_spsr;
+ unsigned int tf_r0;
+ unsigned int tf_r1;
+ unsigned int tf_r2;
+ unsigned int tf_r3;
+ unsigned int tf_r4;
+ unsigned int tf_r5;
+ unsigned int tf_r6;
+ unsigned int tf_r7;
+ unsigned int tf_r8;
+ unsigned int tf_r9;
+ unsigned int tf_r10;
+ unsigned int tf_r11;
+ unsigned int tf_r12;
+ unsigned int tf_usr_sp;
+ unsigned int tf_usr_lr;
+ unsigned int tf_svc_lr;
+ unsigned int tf_pc;
+} trapframe_t;
+
+/*
+ * Signal frame
+ */
+
+struct sigframe {
+ int sf_signum;
+ int sf_code;
+ struct sigcontext *sf_scp;
+ sig_t sf_handler;
+ struct sigcontext sf_sc;
+};
+
+/*
+ * Switch frame
+ */
+
+struct switchframe {
+ int sf_spl;
+ u_int sf_r4;
+ u_int sf_r5;
+ u_int sf_r6;
+ u_int sf_r7;
+ u_int sf_pc;
+};
+
+/*
+ * Stack frame. Used during stack traces (db_trace.c)
+ */
+struct frame {
+ u_int fr_fp;
+ u_int fr_sp;
+ u_int fr_lr;
+ u_int fr_pc;
+};
+
+#ifdef _KERNEL
+void validate_trapframe __P((trapframe_t *, int));
+#endif /* _KERNEL */
+
+#endif /* _ARM32_FRAME_H_ */
+
+/* End of frame.h */
--- /dev/null
+/* $NetBSD: iic.h,v 1.1 1996/04/19 19:52:46 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * iic.h
+ *
+ * header file for IIC
+ *
+ * Created : 15/04/96
+ */
+
+/*
+ * IIC bus driver attach arguments
+ */
+
+#ifdef _KERNEL
+
+struct iicbus_attach_args {
+ u_int ib_addr; /* i/o address */
+ void *ib_aux; /* driver specific */
+};
+
+#define iic_bitdelay 10
+
+#define IIC_WRITE 0x00
+#define IIC_READ 0x01
+
+/* Prototypes for assembly functions */
+
+void iic_set_state __P((int data, int clock));
+void iic_set_state_and_ack __P((int data, int clock));
+void iic_delay __P((int delay));
+
+/* Prototype for kernel interface to IIC bus */
+
+int iic_control __P((u_char address, u_char *buffer, int count));
+
+#endif /* _KERNEL */
+
+/* End of iic.h */
--- /dev/null
+/* $NetBSD: io.h,v 1.3 1996/03/28 21:28:21 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * io.h
+ *
+ * IO registers
+ *
+ * Created : 10/10/94
+ */
+
+/* Some of these addresses are frightening and need cleaning up */
+
+/*
+ * The podule addresses should be removed and localised for the podules.
+ * This is difficuly as the podule addresses are interleaved with the
+ * other IO devices thus making it difficult to separate them.
+ */
+
+#define IO_CONF_BASE 0xf6000000
+
+#define IO_HW_BASE 0x03000000
+
+#define IO_BASE 0xf6200000
+
+#define COMBO_BASE 0xf6210000
+
+#define IDE_CONTROLLER_BASE 0xf62107c0
+
+#define FLOPPY_CONTROLLER_BASE 0xf6210fc0
+
+#define FLOPPY_DACK 0x00002000
+
+#define SERIAL0_CONTROLLER_BASE 0xf6210fe0
+
+#define SERIAL1_CONTROLLER_BASE 0xf6210be0
+
+#define PARALLEL_CONTROLLER_BASE 0xf62109e0
+
+#define IO_MOUSE_BUTTONS 0xf6010000
+
+#ifdef RC7500
+
+#define IDE_CONTROLLER_BASE2 0xf622B000
+
+/*
+ * a bit low turns attached LED on
+ */
+#define LEDPORT (IO_BASE + 0x0002B060)
+#define LED0 0x01
+#define LED1 0x02
+#define LED2 0x04
+#define LED3 0x08
+#define LED4 0x10
+#define LED5 0x20
+#define LED6 0x40
+#define LED7 0x80
+#define LEDOFF 0x00
+#define LEDALL 0xFF
+#endif
+
+
+#define EASI_HW_BASE 0x08000000
+#define EASI_BASE 0xf8000000
+#define EASI_SIZE 0x01000000
+
+#define SIMPLE_PODULE_SIZE 0x00004000
+
+#define MOD_PODULE_BASE 0xf6200000
+#define SYNC_PODULE_BASE 0xf63c0000
+#define SYNC_PODULE_HW_BASE 0x033c0000
+#define FAST_PODULE_BASE 0xf6340000
+#define MEDIUM_PODULE_BASE 0xf60c0000
+#define SLOW_PODULE_BASE 0xf6040000
+
+#define PODULE_GAP 0x00020000
+#define MAX_PODULES 8
+
+#define NETSLOT_BASE 0xf622b000
+#define MAX_NETSLOTS 1
+
+#define MOUSE_BUTTON_RIGHT 0x10
+#define MOUSE_BUTTON_MIDDLE 0x20
+#define MOUSE_BUTTON_LEFT 0x40
+
+/* End of io.h */
--- /dev/null
+/* $NetBSD: iomd.h,v 1.3 1996/03/28 21:26:05 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * iomd.h
+ *
+ * IOMD registers
+ *
+ * Created : 18/09/94
+ *
+ * Based on kate/display/iomd.h
+ */
+
+#define IOMD_HW_BASE 0x03200000
+
+#define IOMD_BASE 0xf6000000
+
+#define IOMD_IOCR (IOMD_BASE + 0x00000000)
+#define IOMD_KBDDAT (IOMD_BASE + 0x00000004)
+#define IOMD_KBDCR (IOMD_BASE + 0x00000008)
+
+#define IOMD_IRQSTA (IOMD_BASE + 0x00000010)
+#define IOMD_IRQRQA (IOMD_BASE + 0x00000014)
+#define IOMD_IRQMSKA (IOMD_BASE + 0x00000018)
+#define IOMD_SUSPEND (IOMD_BASE + 0x0000001C) /* ARM7500 */
+
+#define IOMD_IRQSTB (IOMD_BASE + 0x00000020)
+#define IOMD_IRQRQB (IOMD_BASE + 0x00000024)
+#define IOMD_IRQMSKB (IOMD_BASE + 0x00000028)
+
+#define IOMD_FIQST (IOMD_BASE + 0x00000030)
+#define IOMD_FIQRQ (IOMD_BASE + 0x00000034)
+#define IOMD_FIQMSK (IOMD_BASE + 0x00000038)
+
+#define IOMD_T0LOW (IOMD_BASE + 0x00000040)
+#define IOMD_T0HIGH (IOMD_BASE + 0x00000044)
+#define IOMD_T0GO (IOMD_BASE + 0x00000048)
+#define IOMD_T0LATCH (IOMD_BASE + 0x0000004c)
+
+#define IOMD_T1LOW (IOMD_BASE + 0x00000050)
+#define IOMD_T1HIGH (IOMD_BASE + 0x00000054)
+#define IOMD_T1GO (IOMD_BASE + 0x00000058)
+#define IOMD_T1LATCH (IOMD_BASE + 0x0000005c)
+
+/*
+ * For RC7500, it's not really a IOMD device.
+ */
+#define IOMD_IRQSTC (IOMD_BASE + 0x00000060) /* ARM7500 */
+#define IOMD_IRQRQC (IOMD_BASE + 0x00000064) /* ARM7500 */
+#define IOMD_IRQMSKC (IOMD_BASE + 0x00000068) /* ARM7500 */
+#define IOMD_VIDMUX (IOMD_BASE + 0x0000006C) /* ARM7500 */
+
+#define IOMD_IRQSTD (IOMD_BASE + 0x00000070) /* ARM7500 */
+#define IOMD_IRQRQD (IOMD_BASE + 0x00000074) /* ARM7500 */
+#define IOMD_IRQMSKD (IOMD_BASE + 0x00000078) /* ARM7500 */
+
+#define IOMD_ROMCR0 (IOMD_BASE + 0x00000080)
+#define IOMD_ROMCR1 (IOMD_BASE + 0x00000084)
+#define IOMD_DRAMCR (IOMD_BASE + 0x00000088)
+#define IOMD_VREFCR (IOMD_BASE + 0x0000008c)
+#define IOMD_FSIZE (IOMD_BASE + 0x00000090)
+#define IOMD_ID0 (IOMD_BASE + 0x00000094)
+#define IOMD_ID1 (IOMD_BASE + 0x00000098)
+#define IOMD_VERSION (IOMD_BASE + 0x0000009c)
+
+#define IOMD_MOUSEX (IOMD_BASE + 0x000000a0)
+#define IOMD_MOUSEY (IOMD_BASE + 0x000000a4)
+
+#define IOMD_MSDATA (IOMD_BASE + 0x000000a8) /* ARM7500 */
+#define IOMD_MSCR (IOMD_BASE + 0x000000ac) /* ARM7500 */
+
+#define IOMD_IOTCR (IOMD_BASE + 0x000000C4) /* ARM7500 */
+#define IOMD_ECTCR (IOMD_BASE + 0x000000C8) /* ARM7500 */
+#define IOMD_ASTCR (IOMD_BASE + 0x000000CC) /* ARM7500 */
+
+#define IOMD_DRAMWID (IOMD_BASE + 0x000000D0) /* ARM7500 */
+#define IOMD_SELFREF (IOMD_BASE + 0x000000D4) /* ARM7500 */
+
+#define IOMD_ATODICR (IOMD_BASE + 0x000000E0) /* ARM7500 */
+#define IOMD_ATODSR (IOMD_BASE + 0x000000E4) /* ARM7500 */
+#define IOMD_ATODCR (IOMD_BASE + 0x000000E8) /* ARM7500 */
+#define IOMD_ATODCNT1 (IOMD_BASE + 0x000000EC) /* ARM7500 */
+#define IOMD_ATODCNT2 (IOMD_BASE + 0x000000F0) /* ARM7500 */
+#define IOMD_ATODCNT3 (IOMD_BASE + 0x000000F4) /* ARM7500 */
+#define IOMD_ATODCNT4 (IOMD_BASE + 0x000000F8) /* ARM7500 */
+
+#define IOMD_SD0CURA (IOMD_BASE + 0x00000180)
+#define IOMD_SD0ENDA (IOMD_BASE + 0x00000184)
+#define IOMD_SD0CURB (IOMD_BASE + 0x00000188)
+#define IOMD_SD0ENDB (IOMD_BASE + 0x0000018c)
+#define IOMD_SD0CR (IOMD_BASE + 0x00000190)
+#define IOMD_SD0ST (IOMD_BASE + 0x00000194)
+
+#define IOMD_SD1CURA (IOMD_BASE + 0x000001a0)
+#define IOMD_SD1ENDA (IOMD_BASE + 0x000001a4)
+#define IOMD_SD1CURB (IOMD_BASE + 0x000001a8)
+#define IOMD_SD1ENDB (IOMD_BASE + 0x000001ac)
+#define IOMD_SD1CR (IOMD_BASE + 0x000001b0)
+#define IOMD_SD1ST (IOMD_BASE + 0x000001b4)
+
+#define IOMD_CURSCUR (IOMD_BASE + 0x000001c0)
+#define IOMD_CURSINIT (IOMD_BASE + 0x000001c4)
+
+#define IOMD_VIDCUR (IOMD_BASE + 0x000001d0)
+#define IOMD_VIDEND (IOMD_BASE + 0x000001d4)
+#define IOMD_VIDSTART (IOMD_BASE + 0x000001d8)
+#define IOMD_VIDINIT (IOMD_BASE + 0x000001dc)
+#define IOMD_VIDCR (IOMD_BASE + 0x000001e0)
+
+#define IOMD_DMAST (IOMD_BASE + 0x000001f0)
+#define IOMD_DMARQ (IOMD_BASE + 0x000001f4)
+#define IOMD_DMAMSK (IOMD_BASE + 0x000001f8)
+
+#define IO_MOUSE_BUTTONS 0xf6010000
+
+#define MOUSE_BUTTON_RIGHT 0x10
+#define MOUSE_BUTTON_MIDDLE 0x20
+#define MOUSE_BUTTON_LEFT 0x40
+
+#define RPC600_IOMD_ID 0xd4e7
+#define RC7500_IOC_ID 0x5B98
+
+#define FREQCON (IOMD_BASE + 0x40000)
+
+/* End of iomd.h */
--- /dev/null
+/* $NetBSD: irqhandler.h,v 1.4 1996/03/28 21:29:32 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * irq.h
+ *
+ * IRQ related stuff
+ *
+ * Created : 30/09/94
+ */
+
+#include <sys/types.h>
+
+typedef struct irqhandler {
+ int (*ih_func)(); /* handler function */
+ void *ih_arg; /* Argument to handler */
+ int ih_level; /* Interrupt level */
+ int ih_num; /* Interrupt number (for accounting) */
+ char *ih_name; /* Name of interrupt (for vmstat -i) */
+ unsigned int ih_flags; /* Interrupt flags */
+ unsigned int *ih_irqmask; /* mask location for expansion cards */
+ unsigned int ih_irqbit; /* interrupt bit for expansion cards */
+ struct irqhandler *ih_next; /* next handler */
+} irqhandler_t;
+
+#define IRQ_FLAG_ACTIVE 0x00000001 /* This is the active handler in list */
+
+/* Define the IRQ bits */
+
+
+
+#ifdef RC7500
+
+/*#define IRQ_PRINTER 0x00*/
+#define IRQ_RESERVED0 0x01
+#define IRQ_BUTTON 0x02
+#define IRQ_FLYBACK 0x03
+#define IRQ_POR 0x04
+#define IRQ_TIMER0 0x05
+#define IRQ_TIMER1 0x06
+#define IRQ_FIQDOWN 0x07
+
+#define IRQ_DREQ3 0x08
+/*#define IRQ_HD1 0x09*/
+/*#define IRQ_HD IRQ_HD1*/
+#define IRQ_DREQ2 0x0A
+#define IRQ_ETHERNET 0x0B
+/*#define IRQ_FLOPPY 0x0C*/
+/*#define IRQ_SERIAL 0x0D*/
+#define IRQ_KBDTX 0x0E
+#define IRQ_KBDRX 0x0F
+
+#define IRQ_IRQ3 0x10
+#define IRQ_IRQ4 0x11
+#define IRQ_IRQ5 0x12
+#define IRQ_IRQ6 0x13
+#define IRQ_IRQ7 0x14
+#define IRQ_IRQ9 0x15
+#define IRQ_IRQ10 0x16
+#define IRQ_HD2 0x17
+
+#define IRQ_MSDRX 0x18
+#define IRQ_MSDTX 0x19
+#define IRQ_ATOD 0x1A
+#define IRQ_CLOCK 0x1B
+#define IRQ_PANIC 0x1C
+#define IRQ_RESERVED2 0x1D
+#define IRQ_RESERVED3 0x1E
+#define IRQ_RESERVED1 IRQ_RESERVED2
+
+/*
+ * Note that Sound DMA IRQ is on the 31st vector.
+ * It's not part of the IRQD.
+ */
+#define IRQ_SDMA 0x1F
+
+#else /* RC7500 */
+
+
+
+
+/*#define IRQ_PRINTER 0x00*/
+#define IRQ_RESERVED0 0x01
+/*#define IRQ_FLOPPYIDX 0x02*/
+#define IRQ_FLYBACK 0x03
+#define IRQ_POR 0x04
+#define IRQ_TIMER0 0x05
+#define IRQ_TIMER1 0x06
+#define IRQ_RESERVED1 0x07
+
+#define IRQ_RESERVED2 0x08
+/*#define IRQ_HD 0x09*/
+/*#define IRQ_SERIAL 0x0A*/
+#define IRQ_EXTENDED 0x0B
+/*#define IRQ_FLOPPY 0x0C*/
+#define IRQ_PODULE 0x0D
+#define IRQ_KBDTX 0x0E
+#define IRQ_KBDRX 0x0F
+
+#define IRQ_DMACH0 0x10
+#define IRQ_DMACH1 0x11
+#define IRQ_DMACH2 0x12
+#define IRQ_DMACH3 0x13
+#define IRQ_DMASCH0 0x14
+#define IRQ_DMASCH1 0x15
+#define IRQ_RESERVED3 0x16
+#define IRQ_RESERVED4 0x17
+
+#define IRQ_EXPCARD0 0x18
+#define IRQ_EXPCARD1 0x19
+#define IRQ_EXPCARD2 0x1A
+#define IRQ_EXPCARD3 0x1B
+#define IRQ_EXPCARD4 0x1C
+#define IRQ_EXPCARD5 0x1D
+#define IRQ_EXPCARD6 0x1E
+#define IRQ_EXPCARD7 0x1F
+
+#endif /* RC7500 */
+
+#define IRQ_VSYNC IRQ_FLYBACK /* Aliased */
+#define IRQ_NETSLOT IRQ_EXTENDED
+
+#define IRQ_SOFTNET IRQ_RESERVED0 /* Emulated */
+#define IRQMASK_SOFTNET (1 << IRQ_SOFTNET)
+#define IRQ_SOFTCLOCK IRQ_RESERVED1 /* Emulated */
+#define IRQMASK_SOFTCLOCK (1 << IRQ_SOFTCLOCK)
+
+#define IRQ_INSTRUCT -1
+#define NIRQS 0x20
+
+/* Define the various Interrupt Priority Levels */
+
+/* Interrupt Priority Levels are not mutually exclusive. */
+
+#define IPL_NONE -1
+#define IPL_BIO 0 /* block I/O */
+#define IPL_NET 1 /* network */
+#define IPL_TTY 2 /* terminal */
+#define IPL_CLOCK 3 /* clock */
+#define IPL_IMP 4 /* memory allocation */
+
+#define IRQ_LEVELS 5
+
+#ifdef _KERNEL
+extern u_int irqmasks[IRQ_LEVELS];
+
+void irq_init __P(());
+int irq_claim __P((int, irqhandler_t *));
+int irq_release __P((int, irqhandler_t *));
+void irq_setmasks __P((void));
+void disable_irq __P((int));
+void enable_irq __P((int));
+u_int enable_interrupts __P((u_int));
+u_int disable_interrupts __P((u_int));
+u_int restore_interrupts __P((u_int));
+#endif
+
+typedef struct fiqhandler {
+ void (*fh_func)(); /* handler function */
+ u_int fh_size; /* Size of handler function */
+ u_int fh_mask; /* FIQ mask */
+ u_int fh_r8; /* FIQ mode r8 */
+ u_int fh_r9; /* FIQ mode r9 */
+ u_int fh_r10; /* FIQ mode r10 */
+ u_int fh_r11; /* FIQ mode r11 */
+ u_int fh_r12; /* FIQ mode r12 */
+ u_int fh_r13; /* FIQ mode r13 */
+} fiqhandler_t;
+
+#ifdef RC7500
+int fiq_claim __P((int, fiqhandler_t *));
+int fiq_release __P((int, fiqhandler_t *));
+#else
+int fiq_claim __P((fiqhandler_t *));
+int fiq_release __P((fiqhandler_t *));
+#endif
+
+/* End of irqhandler.h */
--- /dev/null
+/* $NetBSD: katelib.h,v 1.5 1996/03/28 21:35:51 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * katelib.h
+ *
+ * Prototypes for machine specific functions. Most of these
+ * could be inlined.
+ *
+ * This should not really be a separate header file. Eventually I will merge
+ * this into other header files once I have decided where the declarations
+ * should go.
+ *
+ * Created : 18/09/94
+ *
+ * Based on kate/katelib/prototypes.h
+ */
+
+#include <sys/types.h>
+
+#ifdef _KERNEL
+
+/* Assembly modules */
+
+/* In setcpsr.S */
+
+u_int SetCPSR __P((u_int, u_int));
+u_int GetCPSR __P((void));
+
+/* In coproc15.S */
+
+void tlbflush __P((void));
+void tlbpurge __P((u_int));
+void idcflush __P((void));
+void cpu_control __P((u_int));
+void cpu_domains __P((u_int));
+void setttb __P((u_int));
+
+u_int cpu_id __P((void));
+u_int cpu_faultstatus __P((void));
+u_int cpu_faultaddress __P((void));
+
+/* In setstack.S */
+
+void set_stackptr __P((u_int, u_int));
+u_int get_stackptr __P((u_int));
+
+/* In blockio.S */
+
+void insw __P((u_int /*io*/, u_int /*dest*/, u_int /*size*/));
+void outsw __P((u_int /*io*/, u_int /*src*/, u_int /*size*/));
+void insw16 __P((u_int /*io*/, u_int /*dest*/, u_int /*size*/));
+void outsw16 __P((u_int /*io*/, u_int /*src*/, u_int /*size*/));
+
+/* Macros for reading and writing words, shorts, bytes */
+
+#define WriteWord(a, b) \
+*((volatile unsigned int *)(a)) = (b)
+
+#define ReadWord(a) \
+(*((volatile unsigned int *)(a)))
+
+#define WriteShort(a, b) \
+*((volatile unsigned int *)(a)) = ((b) | ((b) << 16))
+
+#define ReadShort(a) \
+((*((volatile unsigned int *)(a))) & 0xffff)
+
+#define WriteByte(a, b) \
+*((volatile unsigned char *)(a)) = (b)
+
+#define ReadByte(a) \
+(*((volatile unsigned char *)(a)))
+
+/* Define in/out macros */
+
+#define inb(port) ReadByte((port))
+#define outb(port, byte) WriteByte((port), (byte))
+#define inw(port) ReadShort((port))
+#define outw(port, word) WriteShort((port), (word))
+#define inl(port) ReadWord((port))
+#define outl(port, lword) WriteWord((port), (lword))
+
+/* Prototypes that are wandering the streets */
+
+#ifdef _ARM32_FRAME_H
+void postmortem __P((trapframe_t */*frame*/));
+#endif
+u_int traceback __P(());
+u_int simpletraceback __P(());
+u_int irqtraceback __P((u_int, u_int));
+int shell __P(());
+void kstack_stuff __P((struct proc */*p*/));
+void boot0 __P(());
+void bootsync __P((void));
+#endif
+
+/* End of katelib.h */
--- /dev/null
+/* $NetBSD: kbd.h,v 1.2 1996/03/14 23:11:21 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * kbd.h
+ *
+ * Keyboard ioctls
+ *
+ * Created : 21/07/95
+ */
+
+struct kbd_data {
+ int keycode;
+ struct timeval event_time;
+};
+
+struct kbd_autorepeat {
+ int ka_delay;
+ int ka_rate;
+};
+
+#define KBD_GETAUTOREPEAT _IOR( 'k', 100, struct kbd_autorepeat)
+#define KBD_SETAUTOREPEAT _IOW( 'k', 101, struct kbd_autorepeat)
+#define KBD_SETLEDS _IOW( 'k', 102, int)
+#define KBD_XXX _IOW( 'k', 103, int)
+
+#define KBD_LED_SCROLL_LOCK 0x01
+#define KBD_LED_NUM_LOCK 0x02
+#define KBD_LED_CAPS_LOCK 0x04
+
+#ifdef _KERNEL
+void kbdsetstate __P((int /*state*/));
+int kbdgetstate __P(());
+#endif
+
+/* End of kbd.h */
--- /dev/null
+/* $NetBSD: kgdb.h,v 1.2 1996/03/14 23:11:23 mark Exp $ */
+
+/*
+ * Copyright (C) 1993, 1994 Wolfgang Solfrank.
+ * Copyright (C) 1993, 1994 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* define certain registers */
+#define SP 13
+#define LR 14
+#define PC 15
+#define PSR 16
+#define SPSR 17
+#define NREG 18
+
+extern int kgdbregs[NREG];
+
+extern int *kgdb_find_stack();
+extern void kgdb_free_stack __P((int *));
--- /dev/null
+/* $NetBSD: limits.h,v 1.2 1996/03/14 23:11:25 mark Exp $ */
+
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)limits.h 7.2 (Berkeley) 6/28/90
+ */
+
+#ifndef _ARM32_LIMITS_H_
+#define _ARM32_LIMITS_H_
+
+#define CHAR_BIT 8 /* number of bits in a char */
+#define MB_LEN_MAX 1 /* no multibyte characters */
+
+#define SCHAR_MIN (-0x7f-1) /* max value for a signed char */
+#define SCHAR_MAX 0x7f /* min value for a signed char */
+
+#define UCHAR_MAX 0xff /* max value for an unsigned char */
+#define CHAR_MAX 0x7f /* max value for a char */
+#define CHAR_MIN (-0x7f-1) /* min value for a char */
+
+#define USHRT_MAX 0xffff /* max value for an unsigned short */
+#define SHRT_MAX 0x7fff /* max value for a short */
+#define SHRT_MIN (-0x7fff-1) /* min value for a short */
+
+#define UINT_MAX 0xffffffff /* max value for an unsigned int */
+#define INT_MAX 0x7fffffff /* max value for an int */
+#define INT_MIN (-0x7fffffff-1) /* min value for an int */
+
+#define ULONG_MAX 0xffffffff /* max value for an unsigned long */
+#define LONG_MAX 0x7fffffff /* max value for a long */
+#define LONG_MIN (-0x7fffffff-1) /* min value for a long */
+
+#if !defined(_ANSI_SOURCE)
+#define SSIZE_MAX INT_MAX /* max value for a ssize_t */
+
+#if !defined(_POSIX_SOURCE)
+#define SIZE_T_MAX UINT_MAX /* max value for a size_t */
+
+#define UQUAD_MAX 0xffffffffffffffffLL /* max unsigned quad */
+#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */
+#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */
+
+#endif /* !_POSIX_SOURCE */
+#endif /* !_ANSI_SOURCE */
+#endif /* _ARM_LIMITS_H_ */
--- /dev/null
+/* $NetBSD: mouse.h,v 1.1 1996/03/27 20:57:18 mark Exp $ */
+
+/*
+ * Copyright (c) Mark Brinicombe 1996 All rights reserved
+ * Copyright (c) Scott Stevens 1995 All rights reserved
+ * Copyright (c) Melvin Tang-Richardson 1995 All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+#define MOUSE_BUTTON_RIGHT 0x10
+#define MOUSE_BUTTON_MIDDLE 0x20
+#define MOUSE_BUTTON_LEFT 0x40
+*/
+
+/* Used in pms.c */
+
+#define BUTSTATMASK 0x07 /* Any mouse button down if any bit set */
+#define BUTCHNGMASK 0x38 /* Any mouse button changed if any bit set */
+
+#define BUT3STAT 0x01 /* Button 3 down if set */
+#define BUT2STAT 0x02 /* Button 2 down if set */
+#define BUT1STAT 0x04 /* Button 1 down if set */
+#define BUT3CHNG 0x08 /* Button 3 changed if set */
+#define BUT2CHNG 0x10 /* Button 2 changed if set */
+#define BUT1CHNG 0x20 /* Button 1 changed if set */
+#define MOVEMENT 0x40 /* Mouse movement detected */
+
+/* Define user visible mouse structures */
+
+struct mouseinfo {
+ u_int status;
+ int xmotion, ymotion;
+};
+
+struct mousebufrec {
+ int status;
+ int x,y;
+ struct timeval event_time;
+};
+
+struct mouse_state {
+ signed short x, y;
+ int buttons;
+};
+
+struct mouse_boundingbox {
+ int x, y, a, b;
+};
+
+struct mouse_origin {
+ int x, y;
+};
+
+/* Define mouse ioctls */
+
+#define MOUSEIOC_WRITEX _IO ( 'M', 100 )
+#define MOUSEIOC_WRITEY _IO ( 'M', 101 )
+
+#define MOUSEIOC_SETSTATE _IOW ( 'M', 102, struct mouse_state )
+#define MOUSEIOC_SETBOUNDS _IOW ( 'M', 103, struct mouse_boundingbox )
+#define MOUSEIOC_SETORIGIN _IOW ( 'M', 104, struct mouse_origin )
+
+#define MOUSEIOC_GETSTATE _IOR ( 'M', 105, struct mouse_state )
+#define MOUSEIOC_READ MOUSEIOC_GETSTATE
+#define MOUSEIOC_GETBOUNDS _IOR ( 'M', 106, struct mouse_boundingbox )
+#define MOUSEIOC_GETORIGIN _IOR ( 'M', 107, struct mouse_origin )
+
+/*
+ * For backwards compatibility with the current Xserver.
+ * Eventually these will be removed.
+ */
+
+#define QUADMOUSE_WRITEX MOUSEIOC_WRITEX
+#define QUADMOUSE_WRITEY MOUSEIOC_WRITEY
+
+#define QUADMOUSE_SETSTATE MOUSEIOC_SETSTATE
+#define QUADMOUSE_SETBOUNDS MOUSEIOC_SETBOUNDS
+#define QUADMOUSE_SETORIGIN MOUSEIOC_SETORIGIN
+
+#define QUADMOUSE_GETSTATE MOUSEIOC_GETSTATE
+#define QUADMOUSE_GETBOUNDS MOUSEIOC_GETBOUNDS
+#define QUADMOUSE_GETORIGIN MOUSEIOC_GETORIGIN
+
+#define QUADMOUSE_SETFORMAT _IOW ( 'M', 108, char[20] )
+
+/* End of mouse.h */
--- /dev/null
+/* $NetBSD: param.h,v 1.6 1996/03/14 23:11:27 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM32_PARAM_H_
+#define _ARM32_PARAM_H_
+
+#ifdef _KERNEL
+# include <machine/cpu.h>
+#endif
+
+/*
+ * Machine dependent constants for ARM6+ processors
+ */
+/*#define ovbcopy bcopy */ /* XXX should probably have long gone by now */
+
+#define _MACHINE arm32
+#define MACHINE "arm32"
+#define _MACHINE_ARCH arm32
+#define MACHINE_ARCH "arm32"
+#define MID_MACHINE MID_ARM6
+
+/*
+ * Round p (pointer or byte index) up to a correctly-aligned value
+ * for all data types (int, long, ...). The result is u_int and
+ * must be cast to any desired pointer type.
+ */
+#define ALIGNBYTES (sizeof(int) - 1)
+#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+
+#define PGSHIFT 12 /* LOG2(NBPG) */
+#define NBPG (1 << PGSHIFT) /* bytes/page */
+#define PGOFSET (NBPG-1) /* byte offset into page */
+#define NPTEPG (NBPG/(sizeof (pt_entry_t)))
+
+
+#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
+#define DEV_BSIZE (1 << DEV_BSHIFT)
+#define BLKDEV_IOSIZE 2048
+#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */
+
+#define CLSIZELOG2 0
+#define CLSIZE (1 << CLSIZELOG2)
+
+/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */
+#define SSIZE 1 /* initial stack size/NBPG */
+#define SINCR 1 /* increment of stack/NBPG */
+#define UPAGES 2 /* pages of u-area */
+#define USPACE (UPAGES * NBPG) /* total size of u-area */
+
+/*
+ * Constants related to network buffer management.
+ * MCLBYTES must be no larger than CLBYTES (the software page size), and,
+ * on machines that exchange pages of input or output buffers with mbuf
+ * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple
+ * of the hardware page size.
+ */
+#define MSIZE 128 /* size of an mbuf */
+#define MCLSHIFT 11 /* convert bytes to m_buf clusters */
+#define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */
+#define MCLOFSET (MCLBYTES - 1) /* offset within a m_buf cluster */
+
+#ifndef NMBCLUSTERS
+#ifdef GATEWAY
+#define NMBCLUSTERS 512 /* map size, max cluster allocation */
+#else
+#define NMBCLUSTERS 256 /* map size, max cluster allocation */
+#endif
+#endif
+
+/*
+ * Size of kernel malloc arena in CLBYTES-sized logical pages
+ */
+#ifndef NKMEMCLUSTERS
+#define NKMEMCLUSTERS (6 * 1024 * 1024 / CLBYTES)
+#endif
+
+/* pages ("clicks") (4096 bytes) to disk blocks */
+#define ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT))
+#define dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT))
+/*#define dtob(x) ((x) << DEV_BSHIFT)*/
+
+#define ctob(x) ((x) << PGSHIFT)
+
+/* bytes to pages */
+#define btoc(x) (((unsigned)(x) + PGOFSET) >> PGSHIFT)
+
+#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \
+ ((unsigned)(bytes) >> DEV_BSHIFT)
+#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \
+ ((unsigned)(db) << DEV_BSHIFT)
+
+/*
+ * Map a ``block device block'' to a file system block.
+ * This should be device dependent, and should use the bsize
+ * field from the disk label.
+ * For now though just use DEV_BSIZE.
+ */
+#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE / DEV_BSIZE))
+
+/* Define various base addresses */
+
+#define KERNEL_BASE 0xf0000000
+#define KERNEL_VM_BASE 0xf1000000
+#define PAGE_DIRS_BASE 0xf3000000
+#define ALT_PAGE_TBLS_BASE 0xf3c00000
+#define CURRENT_PAGEDIR_BASE 0xeffd4000
+#define PROCESS_PAGE_TBLS_BASE 0xefc00000
+
+#define KERNBASE KERNEL_BASE
+
+/* Constants used to divide the USPACE area */
+
+/*
+ * The USPACE area contains :
+ * 1. the user structure for the process
+ * 2. the fp context for FP emulation
+ * 3. the kernel (svc) stack
+ * 4. the undefined instruction stack
+ *
+ * The layout of the area looks like this
+ *
+ * | user area | FP context | undefined stack | kernel stack |
+ *
+ * The size of the user area is known.
+ * The size of the FP context is variable depending of the FP emulator
+ * in use and whether there is hardware FP support. However we can put
+ * an upper limit on it.
+ * The undefined stack needs to be at least 512 bytes. This is a requirement
+ * if the FP emulators
+ * The kernel stack should be at least 4K is size.
+ *
+ * The stack top addresses are used to set the stack pointers. The stack bottom
+ * addresses at the addresses monitored by the diagnostic code for stack overflows
+ *
+ */
+
+#define FPCONTEXTSIZE (0x100)
+#define USPACE_SVC_STACK_TOP (USPACE)
+#define USPACE_SVC_STACK_BOTTOM (USPACE_SVC_STACK_TOP - 0x1000)
+#define USPACE_UNDEF_STACK_TOP (USPACE_SVC_STACK_BOTTOM - 0x10)
+#define USPACE_UNDEF_STACK_BOTTOM (sizeof(struct user) + FPCONTEXTSIZE + 10)
+
+#define arm_byte_to_page(x) (x >> PGSHIFT)
+#define arm_page_to_byte(x) (x << PGSHIFT)
+
+#ifdef _KERNEL
+#ifndef _LOCORE
+void delay __P((unsigned));
+#define DELAY(x) delay(x)
+#endif
+#endif
+
+#endif /* _ARM_PARAM_H_ */
--- /dev/null
+/* $NetBSD: pcb.h,v 1.2 1996/03/13 21:08:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM32_PCB_H_
+#define _ARM32_PCB_H_
+
+#include <machine/pte.h>
+#include <machine/fp.h>
+
+struct pcb {
+ pd_entry_t *pcb_pagedir; /* PT hooks */
+ u_int pcb_flags; /* Flags */
+ u_int pcb_spsr;
+ u_int pcb_r0; /* Space for register dump */
+ u_int pcb_r1;
+ u_int pcb_r2;
+ u_int pcb_r3;
+ u_int pcb_r4;
+ u_int pcb_r5;
+ u_int pcb_r6;
+ u_int pcb_r7;
+ u_int pcb_r8; /* used */
+ u_int pcb_r9; /* used */
+ u_int pcb_r10; /* used */
+ u_int pcb_r11; /* used */
+ u_int pcb_r12; /* used */
+ u_int pcb_sp; /* used */
+ u_int pcb_lr;
+ u_int pcb_pc;
+ u_int pcb_und_sp;
+ caddr_t pcb_onfault; /* On fault handler */
+ struct fp_state pcb_fpstate; /* Floating Point state */
+};
+
+/*
+ * No additional data for core dumps.
+ */
+struct md_coredump {
+ int md_empty;
+};
+
+#ifdef _KERNEL
+extern struct pcb *curpcb;
+#endif /* _KERNEL */
+
+#endif /* _ARM32_PCB_H_ */
+
+/* End of pcb.h */
--- /dev/null
+/* $NetBSD: pmap.h,v 1.3 1996/03/14 23:11:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM32_PMAP_H_
+#define _ARM32_PMAP_H_
+
+#include <machine/pte.h>
+
+/*
+ * virtual address to page table entry and
+ * to physical address.
+ */
+
+#define vtopte(va) \
+ ((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + (arm_byte_to_page((unsigned int)(va)) << 2)))
+
+
+#define vtophys(va) \
+ ((*vtopte(va) & PG_FRAME) | ((unsigned int)(va) & ~PG_FRAME))
+
+/*
+ * Pmap stuff
+ */
+struct pmap {
+ pd_entry_t *pm_pdir; /* KVA of page directory */
+ vm_offset_t pm_pptpt; /* PA of pt's page table */
+ vm_offset_t pm_vptpt; /* VA of pt's page table */
+ boolean_t pm_pdchanged; /* pdir changed */
+ short pm_dref; /* page directory ref count */
+ short pm_count; /* pmap reference count */
+ simple_lock_data_t pm_lock; /* lock on pmap */
+ struct pmap_statistics pm_stats; /* pmap statistics */
+};
+
+typedef struct pmap *pmap_t;
+
+/*
+ * For speed we store the both the virtual address and the page table
+ * entry address for each page hook.
+ */
+
+typedef struct {
+ vm_offset_t va;
+ pt_entry_t *pte;
+} pagehook_t;
+
+/*
+ * For each vm_page_t, there is a list of all currently valid virtual
+ * mappings of that page. An entry is a pv_entry_t, the list is pv_table.
+ */
+
+typedef struct pv_entry {
+ struct pv_entry *pv_next; /* next pv_entry */
+ pmap_t pv_pmap; /* pmap where mapping lies */
+ vm_offset_t pv_va; /* virtual address for mapping */
+ int pv_flags; /* flags */
+} *pv_entry_t;
+
+struct pv_page;
+
+struct pv_page_info {
+ TAILQ_ENTRY(pv_page) pgi_list;
+ struct pv_entry *pgi_freelist;
+ int pgi_nfree;
+};
+
+/*
+ * This is basically:
+ * ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry))
+ */
+
+#define NPVPPG ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry))
+
+struct pv_page {
+ struct pv_page_info pvp_pgi;
+ struct pv_entry pvp_pv[NPVPPG];
+};
+
+#ifdef _KERNEL
+pv_entry_t pv_table; /* array of entries, one per page */
+extern pmap_t kernel_pmap;
+extern struct pmap kernel_pmap_store;
+
+#define pmap_kernel() (&kernel_pmap_store)
+#define pmap_update() tlbflush()
+#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
+
+boolean_t pmap_testbit __P((vm_offset_t, int));
+void pmap_changebit __P((vm_offset_t, int, int));
+
+static __inline vm_offset_t
+pmap_phys_address(int ppn)
+{
+ return(arm_page_to_byte(ppn));
+}
+
+#endif
+
+#endif
+
+/* End of pmap.h */
--- /dev/null
+/* $NetBSD: podule.h,v 1.2 1996/03/14 23:11:31 mark Exp $ */
+
+/*
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ARM32_PODULE_H_
+#define _ARM32_PODULE_H_
+
+/*
+ * Generic defines for Acorn Podules
+ */
+#define IO_SPACE_PHYS 0x03000000 /* physical I/O space location */
+#define IO_SPACE_VIRT 0xf8000000 /* virtual I/O space location */
+#define IO_SPACE_SIZE 0x01000000 /* size of I/O space */
+
+#define PODULE_SLOW_MEM ((volatile void *)(IO_SPACE_VIRT + 0x240000))
+#define PODULE_MED_MEM ((volatile void *)(IO_SPACE_VIRT + 0x2c0000))
+#define PODULE_FAST_MEM ((volatile void *)(IO_SPACE_VIRT + 0x340000))
+#define PODULE_SYNC_MEM ((volatile void *)(IO_SPACE_VIRT + 0x3c0000))
+
+#define PODULE_SLOT2MEM(slot,mem) ((slot)*0x4000 + (mem))
+
+/*
+ * Access 8 bit wide memory on podule
+ */
+#define PODULE_GET_BYTE(sp,off) (((volatile u_char *)(sp))[(off) * 4])
+#define PODULE_SET_BYTE(sp,off,byte) (((volatile u_int *)(sp))[(off)] \
+ = ((u_char)(byte) << 24) \
+ | ((u_char)(byte) << 16) \
+ | ((u_char)(byte) << 8) \
+ | (u_char)(byte))
+/*
+ * Access 16 bit wide memory on podule
+ */
+#define PODULE_GET_SHORT(sp,off) (((volatile u_short *)(sp))[(off)])
+#define PODULE_SET_SHORT(sp,off,word) (((volatile u_int *)(sp))[(off) / 2] \
+ = ((u_short)(word) << 16) \
+ | (u_short)(word))
+
+/*
+ * Known offsets in any podule
+ */
+#define PODULE_IRQ_BYTE 0
+#define PODULE_IRQ_PEND 1
+#define PODULE_FIQ_PEND 2
+
+#define PODULE_ID_BYTE 3
+#define PODULE_ID_SCSI 2
+#define PODULE_ID_ETHER 3
+
+extern void podule_get_bytes __P((volatile void *sp, void *dp, int cnt));
+extern void podule_set_bytes __P((void *sp, volatile void *dp, int cnt));
+
+extern void podule_get_shorts __P((volatile void *sp, void *dp, int cnt));
+extern void podule_set_shorts __P((void *sp, volatile void *dp, int cnt));
+
+/* XXX Shouldn't this be somewhere else? */
+#define offsetof(type, member) ((size_t)&((type *)0)->member)
+
+#endif /* _ARM_PODULE_H_ */
--- /dev/null
+/* $NetBSD: proc.h,v 1.2 1996/03/14 23:11:33 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM32_PROC_H_
+#define _ARM32_PROC_H_
+
+/*
+ * Machine-dependent part of the proc structure for arm.
+ */
+struct mdproc {
+ struct trapframe *md_regs; /* registers on current frame */
+ int __spare;
+};
+#endif
--- /dev/null
+/* $NetBSD: profile.h,v 1.3 1996/03/14 23:11:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1995-1996 Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define _MCOUNT_DECL static inline void _mcount
+
+/* Cannot implement mcount in C as GCC uses the ip register to pass the
+ * frompcindex variable. GCC also uses ip during the register pushing
+ * at the beginning of any C function.
+ */
+#define MCOUNT \
+extern void mcount() asm("mcount"); \
+void \
+mcount() \
+{ \
+ register int selfpc, frompcindex; \
+ /* \
+ * find the return address for mcount, \
+ * and the return address for mcount's caller. \
+ * \
+ * selfpc = pc pushed by mcount call \
+ */ \
+ asm("mov %0, lr" : "=r" (selfpc)); \
+ /* \
+ * frompcindex = pc pushed by call into self. \
+ */ \
+ asm("mov %0, ip" : "=r" (frompcindex)); \
+ _mcount(frompcindex, selfpc); \
+}
+
+#ifdef _KERNEL
+/*
+ * Note that we assume splhigh() and splx() cannot call mcount()
+ * recursively.
+ */
+#define MCOUNT_ENTER s = splhigh()
+#define MCOUNT_EXIT splx(s)
+#endif /* _KERNEL */
--- /dev/null
+/* $NetBSD: psl.h,v 1.2 1996/03/08 16:35:17 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * psl.h
+ *
+ * spl prototypes.
+ * Eventually this will become a set of defines.
+ *
+ * Created : 21/07/95
+ */
+
+/*
+ * These are the different SPL states
+ *
+ * Each state has an interrupt mask associated with it which
+ * indicate which interrupts are allowed.
+ */
+
+#define SPL_0 0
+#define SPL_SOFT 1
+#define SPL_BIO 2
+#define SPL_NET 3
+#define SPL_TTY 4
+#define SPL_CLOCK 5
+#define SPL_IMP 6
+#define SPL_HIGH 7
+#define SPL_LEVELS 8
+
+#define spl0() splx(SPL_0)
+#define splhigh() splx(SPL_HIGH)
+#define splbio() raisespl(SPL_BIO)
+#define splnet() raisespl(SPL_NET)
+#define spltty() raisespl(SPL_TTY)
+#define splimp() raisespl(SPL_IMP)
+#define splclock() raisespl(SPL_CLOCK)
+#define splstatclock() raisespl(SPL_CLOCK)
+#define splsoftnet() raisespl(SPL_SOFT)
+
+#ifndef _LOCORE
+int raisespl __P((int));
+int lowerspl __P((int));
+int splx __P((int));
+int splsoftclock __P(());
+
+#ifdef _KERNEL
+extern int current_spl_level;
+
+extern u_int spl_masks[SPL_LEVELS];
+#endif /* _KERNEL */
+#endif /* _LOCORE */
+
+/* End of psl.h */
--- /dev/null
+/* $NetBSD: pte.h,v 1.3 1996/03/14 23:11:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name "RiscBSD" nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM32_PTE_H_
+#define _ARM32_PTE_H_
+
+#define PDSHIFT 20 /* LOG2(NBPDR) */
+#define NBPD (1 << PDSHIFT) /* bytes/page dir */
+/*# define PDOFSET (NBPD-1)*/ /* byte offset into page dir */
+#define NPTEPD (NBPD / NBPG)
+
+#ifndef _LOCORE
+typedef int pd_entry_t; /* page directory entry */
+typedef int pt_entry_t; /* page table entry */
+#endif
+
+#define PD_MASK 0xfff00000 /* page directory address bits */
+#define PT_MASK 0x000ff000 /* page table address bits */
+
+#define PG_FRAME 0xfffff000
+
+/* The PT_SIZE definition is misleading... A page table is only 0x400
+ * bytes long. But since VM mapping can only be done to 0x1000 a single
+ * 1KB blocks cannot be steered to a va by itself. Therefore the
+ * pages tables are allocated in blocks of 4. i.e. if a 1 KB block
+ * was allocated for a PT then the other 3KB would also get mapped
+ * whenever the 1KB was mapped.
+ */
+
+#define PT_SIZE 0x1000
+#define PD_SIZE 0x4000
+
+#define AP_KR 0x00
+#define AP_KRW 0x01
+#define AP_KRWUR 0x02
+#define AP_KRWURW 0x03
+
+#define AP_W 0x01
+#define AP_U 0x02
+
+#define PT_B 0x04 /* Phys - Buffered (write) */
+#define PT_C 0x08 /* Phys - Cacheable */
+#define PT_U 0x10 /* Phys - Updateable */
+
+#define PT_M 0x01 /* Virt - Modified */
+#define PT_H 0x02 /* Virt - Handled (Used) */
+#define PT_W 0x40 /* Virt - Wired */
+#define PT_Wr 0x10 /* Virt / Phys Write */
+#define PT_Us 0x20 /* Virt / Phys User */
+
+#define PT_AP(x) ((x << 10) | (x << 8) | (x << 6) | (x << 4))
+
+#define AP_SECTION_SHIFT 10
+
+#define L1_PAGE 0x01
+#define L1_SECTION 0x02
+#define L2_LPAGE 0x01
+#define L2_SPAGE 0x02
+#define L2_MASK 0x03
+#define L2_INVAL 0x00
+
+#define L2_PTE(p, a) ((p) | PT_AP(a) | L2_SPAGE | PT_C | PT_B)
+#define L2_PTE_NC(p, a) ((p) | PT_AP(a) | L2_SPAGE | PT_B)
+
+#define L1_PTE(p) ((p) | 0x00 | PT_U | L1_PAGE)
+
+#define L1_SEC(p) ((p) | (AP_KRW << AP_SECTION_SHIFT) | PT_U | L1_SECTION)
+
+#define DOMAIN_FAULT 0x00
+#define DOMAIN_CLIENT 0x01
+#define DOMAIN_RESERVED 0x02
+#define DOMAIN_MANAGER 0x03
+
+#endif
+
+/* End of pte.h */
--- /dev/null
+/* $NetBSD: ptrace.h,v 1.2 1996/03/14 23:11:38 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank Lancaster
+ * Copyright (c) 1995 Tools GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * arm-dependent ptrace definitions
+ */
+#define PT_STEP (PT_FIRSTMACH + 0)
+#define PT_GETREGS (PT_FIRSTMACH + 1)
+#define PT_SETREGS (PT_FIRSTMACH + 2)
+#define PT_GETFPREGS (PT_FIRSTMACH + 3)
+#define PT_SETFPREGS (PT_FIRSTMACH + 4)
--- /dev/null
+/* $NetBSD: qmouse.h,v 1.2 1996/03/14 23:11:40 mark Exp $ */
+
+/*
+ * Copyright (c) Scott Stevens 1995 All rights reserved
+ * Copyright (c) Melvin Tang-Richardson 1995 All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define MOVEEVENT 0x40
+#define B1TRANS 0x20
+#define B2TRANS 0x10
+#define B3TRANS 0x08
+#define BTRANSMASK 0x38
+#define B1VAL 0x04
+#define B2VAL 0x02
+#define B3VAL 0x01
+#define BVALMASK 0x07
+
+struct mousebufrec {
+ int status;
+ int x,y;
+ struct timeval event_time;
+};
+
+struct mouse_state {
+ signed short x, y;
+ int buttons;
+};
+
+struct mouse_boundingbox {
+ int x, y, a, b;
+};
+
+struct mouse_origin {
+ int x, y;
+};
+
+#define QUADMOUSE_WRITEX _IO ( 'M', 100 )
+#define QUADMOUSE_WRITEY _IO ( 'M', 101 )
+
+#define QUADMOUSE_SETSTATE _IOW ( 'M', 102, struct mouse_state )
+#define QUADMOUSE_SETBOUNDS _IOW ( 'M', 103, struct mouse_boundingbox )
+#define QUADMOUSE_SETORIGIN _IOW ( 'M', 104, struct mouse_origin )
+
+#define QUADMOUSE_GETSTATE _IOR ( 'M', 105, struct mouse_state )
+#define QUADMOUSE_GETBOUNDS _IOR ( 'M', 106, struct mouse_boundingbox )
+#define QUADMOUSE_GETORIGIN _IOR ( 'M', 107, struct mouse_origin )
+
+#define QUADMOUSE_SETFORMAT _IOW ( 'M', 108, char[20] )
+
+/* End of qmouse.h */
--- /dev/null
+/* $NetBSD: reg.h,v 1.2 1996/03/14 23:11:41 mark Exp $ */
+
+/*
+ * Copyright (C) 1994, 1995 Frank Lancaster
+ * Copyright (C) 1994, 1995 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#)reg.h 5.5 (Berkeley) 1/18/91
+ */
+
+#ifndef _ARM32_REG_H_
+#define _ARM32_REG_H_
+
+#include <machine/fp.h>
+
+struct reg {
+ unsigned int r[13];
+ unsigned int r_sp;
+ unsigned int r_lr;
+ unsigned int r_pc;
+ unsigned int r_cpsr;
+};
+
+/* this is identical to fp_state */
+struct fpreg {
+ unsigned int fpr_flags;
+ unsigned int fpr_sr;
+ unsigned int fpr_cr;
+ fp_reg_t fpr[16];
+};
+
+#endif /* !_ARM32_REG_H_ */
+
--- /dev/null
+/* $NetBSD: rtc.h,v 1.3 1996/04/19 19:51:48 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * rtc.h
+ *
+ * Header file for RTC / CMOS stuff
+ *
+ * Created : 13/10/94
+ *
+ * Based of kate/display/iiccontrol.c
+ */
+
+/*
+ * IIC addresses for RTC chip
+ * Two PCF8583 chips are supported on the IIC bus
+ */
+
+#define IIC_PCF8583_MASK 0xfc
+#define IIC_PCF8583_ADDR 0xa0
+
+#define RTC_Write (IIC_PCF8583_ADDR | IIC_WRITE)
+#define RTC_Read (IIC_PCF8583_ADDR | IIC_READ)
+
+typedef struct {
+ u_char rtc_micro;
+ u_char rtc_centi;
+ u_char rtc_sec;
+ u_char rtc_min;
+ u_char rtc_hour;
+ u_char rtc_day;
+ u_char rtc_mon;
+ u_char rtc_year;
+ u_char rtc_cen;
+} rtc_t;
+
+#define RTC_ADDR_BOOTOPTS 0x90
+#define RTC_ADDR_REBOOTCNT 0x91
+#define RTC_ADDR_YEAR 0xc0
+#define RTC_ADDR_CENT 0xc1
+
+#ifdef _KERNEL
+int cmos_read __P((int));
+int cmos_write __P((int, int));
+int rtc_read __P((rtc_t *));
+int rtc_write __P((rtc_t *));
+#endif /* _KERNEL */
+
+/* End of rtc.h */
--- /dev/null
+/* $NetBSD: setjmp.h,v 1.2 1996/03/14 23:11:45 mark Exp $ */
+
+/*
+ * machine/setjmp.h: machine dependent setjmp-related information.
+ */
+
+#define _JBLEN 26 /* size, in longs, of a jmp_buf */
--- /dev/null
+/* $NetBSD: signal.h,v 1.3 1996/03/14 23:11:47 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * signal.h
+ *
+ * Architecture dependant signal types and structures
+ *
+ * Created : 30/09/94
+ */
+
+#ifndef _ARM32_SIGNAL_H_
+#define _ARM32_SIGNAL_H_
+
+#ifndef _LOCORE
+
+typedef int sig_atomic_t;
+
+/*
+ * Information pushed on stack when a signal is delivered.
+ * This is used by the kernel to restore state following
+ * execution of the signal handler. It is also made available
+ * to the handler to allow it to restore state properly if
+ * a non-standard exit is performed.
+ */
+
+struct sigcontext {
+ int sc_onstack; /* sigstack state to restore */
+ int sc_mask; /* signal mask to restore */
+
+ unsigned int sc_spsr;
+ unsigned int sc_r0;
+ unsigned int sc_r1;
+ unsigned int sc_r2;
+ unsigned int sc_r3;
+ unsigned int sc_r4;
+ unsigned int sc_r5;
+ unsigned int sc_r6;
+ unsigned int sc_r7;
+ unsigned int sc_r8;
+ unsigned int sc_r9;
+ unsigned int sc_r10;
+ unsigned int sc_r11;
+ unsigned int sc_r12;
+ unsigned int sc_usr_sp;
+ unsigned int sc_usr_lr;
+ unsigned int sc_svc_lr;
+ unsigned int sc_pc;
+};
+
+#endif
+
+#endif /* _ARM_SIGNAL_H_ */
+
+/* End of signal.h */
--- /dev/null
+/* $NetBSD: stdarg.h,v 1.2 1996/03/14 23:11:49 mark Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)stdarg.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _STDARG_H_
+#define _STDARG_H_
+
+typedef char *va_list;
+
+#define __va_promote(type) \
+ (((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+#define va_start(ap, last) \
+ (ap = ((char *)&(last) + __va_promote(last)))
+
+#ifdef _KERNEL
+#define va_arg(ap, type) \
+ ((type *)(ap += sizeof(type)))[-1]
+#else
+#define va_arg(ap, type) \
+ ((type *)(ap += sizeof(type) < sizeof(int) ? \
+ (abort(), 0) : sizeof(type)))[-1]
+#endif
+
+#define va_end(ap)
+
+#endif /* !_STDARG_H_ */
--- /dev/null
+/* $NetBSD: types.h,v 1.2 1996/03/06 23:04:04 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)types.h 7.5 (Berkeley) 3/9/91
+ */
+
+#ifndef _ARM32_TYPES_H_
+#define _ARM32_TYPES_H_
+
+#include <sys/cdefs.h>
+
+typedef struct _physadr {
+ int r[1];
+} *physadr;
+
+typedef struct label_t { /* Used by setjmp & longjmp */
+ int val[11];
+} label_t;
+
+typedef unsigned long vm_offset_t;
+typedef unsigned long vm_size_t;
+
+/*
+ * Basic integral types. Omit the typedef if
+ * not possible for a machine/compiler combination.
+ */
+#define __BIT_TYPES_DEFINED__
+typedef __signed char int8_t;
+typedef unsigned char u_int8_t;
+typedef short int16_t;
+typedef unsigned short u_int16_t;
+typedef int int32_t;
+typedef unsigned int u_int32_t;
+typedef long long int64_t;
+typedef unsigned long long u_int64_t;
+
+typedef int32_t register_t;
+
+#endif /* _ARM32_TYPES_H_ */
--- /dev/null
+/* $NetBSD: undefined.h,v 1.2 1996/03/14 23:11:51 mark Exp $ */
+
+/*
+ * Copyright (c) 1995-1996 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * undefined.h
+ *
+ * Undefined instruction types, symbols and prototypes
+ *
+ * Created : 08/02/95
+ */
+
+#ifdef _KERNEL
+
+typedef int (*undef_handler_t) __P((unsigned int, unsigned int, trapframe_t *));
+
+#define FP_COPROC 1
+#define FP_COPROC2 2
+#define MAX_COPROCS 16
+
+extern undef_handler_t undefined_handlers[MAX_COPROCS];
+
+/* Prototypes for undefined.c */
+
+int install_coproc_handler __P((int, undef_handler_t));
+void undefined_init __P((void));
+
+#endif
+
+/* End of undefined.h */
--- /dev/null
+/* $NetBSD: varargs.h,v 1.2 1996/03/14 23:11:53 mark Exp $ */
+
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)varargs.h 8.2 (Berkeley) 3/22/94
+ */
+
+#ifndef _MACHINE_VARARGS_H_
+#define _MACHINE_VARARGS_H_
+
+typedef char *va_list;
+
+#define va_dcl int va_alist; ...
+
+#define va_start(ap) \
+ ap = (char *)&va_alist
+
+#ifdef _KERNEL
+#define va_arg(ap, type) \
+ ((type *)(ap += sizeof(type)))[-1]
+#else
+#define va_arg(ap, type) \
+ ((type *)(ap += sizeof(type) < sizeof(int) ? \
+ (abort(), 0) : sizeof(type)))[-1]
+#endif
+
+#define va_end(ap)
+
+#endif /* !_MACHINE_VARARGS_H_ */
--- /dev/null
+/* $NetBSD: vconsole.h,v 1.1 1996/01/31 23:23:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Melvyn Tang-Richardson
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * vconsole.h
+ *
+ * Virtual console header
+ *
+ * Created : 18/09/94
+ * Last updated : 10/01/96
+ *
+ * $Id: vconsole.h,v 1.1.1.1 1996/04/24 11:08:46 deraadt Exp $
+ */
+
+#ifdef _KERNEL
+#define LOSSY 1
+#define FIXEDRES 2
+
+#define BOLD (1<<15)
+#define UNDERLINE (1<<16)
+#define REVERSE (1<<17)
+#define BLINKING (1<<18)
+
+#include <machine/vidc.h>
+
+struct vconsole;
+
+/*
+ * Render routines and terminal drivers which conform to version 1.00
+ * of the spec should always be present. This is the lowest common
+ * denominator, which enables the driver to always find something that
+ * will work.
+ *
+ * Prefered drivers can be added required in the tables.
+ */
+
+struct render_engine {
+ char * name;
+ int ( *init ) __P(( struct vconsole *vc ));
+ void ( *putchar ) __P(( dev_t dev, char c, struct vconsole *vc ));
+ int ( *spawn ) __P(( struct vconsole *vc ));
+ int ( *swapin ) __P(( struct vconsole *vc ));
+ int ( *mmap ) __P(( struct vconsole *vc, int offset, int nprot ));
+ void ( *render ) __P(( struct vconsole *vc, char c));
+ void ( *scrollup ) __P(( struct vconsole *vc, int low, int high ));
+ void ( *scrolldown ) __P(( struct vconsole *vc, int low, int high ));
+ void ( *cls ) __P(( struct vconsole *vc ));
+ void ( *update ) __P(( struct vconsole *vc ));
+ int ( *scrollback ) __P(( struct vconsole *vc ));
+ int ( *scrollforward ) __P(( struct vconsole *vc ));
+ int ( *scrollbackend ) __P(( struct vconsole *vc ));
+ int ( *clreos ) __P(( struct vconsole *vc, int code ));
+ int ( *debugprint ) __P(( struct vconsole *vc ));
+ int ( *cursorupdate ) __P(( struct vconsole *vc ));
+ int ( *cursorflashrate ) __P(( struct vconsole *vc, int rate ));
+ int ( *setfgcol ) __P(( struct vconsole *vc, int col ));
+ int ( *setbgcol ) __P(( struct vconsole *vc, int col ));
+ int ( *textpalette ) __P(( struct vconsole *vc ));
+ int ( *sgr ) __P(( struct vconsole *vc, int type ));
+ int ( *blank ) __P(( struct vconsole *vc, int type ));
+ int ( *ioctl ) __P(( struct vconsole *vc, dev_t dev, int cmd,
+ caddr_t data, int flag, struct proc *p));
+ int ( *redraw ) __P(( struct vconsole *vc, int x, int y, int a, int b ));
+ int ( *attach ) __P(( struct vconsole *vc, struct device *dev, struct device *dev1, void * arg));
+ int ( *flash ) __P(( struct vconsole *vc, int flash ));
+ int ( *cursor_flash ) __P(( struct vconsole *vc, int flash ));
+};
+
+/* Blank types. VESA defined */
+
+/* Blank type 3 is suported by default */
+
+#define BLANK_NONE 0 /* Not really blanked */
+#define BLANK_IDLE 1 /* Vsync dropped for fast reactivation */
+#define BLANK_UNUSED 2 /* Hsync dropped for semi fast reactivation */
+#define BLANK_OFF 3 /* All signals removed slowest reactivation */
+
+#define R_NAME render_engine->name
+#define SPAWN render_engine->spawn
+#define SCROLLUP render_engine->scrollup
+#define SCROLLDOWN render_engine->scrolldown
+#define RENDER render_engine->render
+#define R_SWAPIN render_engine->swapin
+#define CLS render_engine->cls
+#define R_INIT render_engine->init
+#define PUTCHAR render_engine->putchar
+#define R_SWAPIN render_engine->swapin
+#define MMAP render_engine->mmap
+#define R_SCROLLBACK render_engine->scrollback
+#define R_SCROLLFORWARD render_engine->scrollforward
+#define R_SCROLLBACKEND render_engine->scrollbackend
+#define R_CLREOS render_engine->clreos
+#define R_DEBUGPRINT render_engine->debugprint
+#define CURSORUPDATE render_engine->cursorupdate
+#define CURSORFLASHRATE render_engine->cursorflashrate
+#define SETFGCOL render_engine->setfgcol
+#define SETBGCOL render_engine->setbgcol
+#define TEXTPALETTE render_engine->textpalette
+#define SGR render_engine->sgr
+#define BLANK render_engine->blank
+#define IOCTL render_engine->ioctl
+#define REDRAW render_engine->redraw
+#define R_ATTACH render_engine->attach
+#define FLASH render_engine->flash
+#define CURSOR_FLASH render_engine->cursor_flash
+
+/*
+ * The terminal emulator's scroll back is only used as a last resort for
+ * cases when a render engine can't scrollback. In most cases though, the
+ * terminal emulator won't allocate enough chapmap to perform scrollback.
+ */
+
+struct terminal_emulator {
+ char *name;
+ /* Terminal emulation routines */
+ int (*term_init) __P((struct vconsole *vc));
+ int (*putstring) __P((char *string, int length, struct vconsole *vc));
+ int (*swapin) __P((struct vconsole *vc));
+ int (*swapout) __P((struct vconsole *vc));
+ int (*sleep) __P((struct vconsole *vc));
+ int (*wake) __P((struct vconsole *vc));
+ int ( *scrollback) __P(( struct vconsole *vc ));
+ int ( *scrollforward) __P(( struct vconsole *vc ));
+ int ( *scrollbackend) __P(( struct vconsole *vc ));
+ int ( *debugprint) __P(( struct vconsole *vc ));
+ int ( *modechange) __P(( struct vconsole *vc ));
+ int ( *attach ) __P(( struct vconsole *vc, struct device *dev, struct device *dev1, void *arg ));
+};
+
+#define T_NAME terminal_emulator->name
+#define TERM_INIT terminal_emulator->term_init
+#define T_SWAPIN terminal_emulator->swapin
+#define PUTSTRING terminal_emulator->putstring
+#define SLEEP terminal_emulator->sleep
+#define WAKE terminal_emulator->wake
+#define T_SCROLLBACK terminal_emulator->scrollback
+#define T_SCROLLFORWARD terminal_emulator->scrollforward
+#define T_SCROLLBACKEND terminal_emulator->scrollbackend
+#define T_DEBUGPRINT terminal_emulator->debugprint
+#define MODECHANGE terminal_emulator->modechange
+#define T_ATTACH terminal_emulator->attach
+
+struct vconsole {
+ /* Management of consoles */
+
+ struct vconsole *next;
+ int number;
+ int opened;
+ struct tty *tp;
+ struct proc *proc;
+ int flags;
+
+ /* Data structures */
+ char *data;
+ char *r_data;
+
+ /* Structures required for the generic character map */
+ int xchars, ychars;
+ int *charmap;
+ int xcur, ycur;
+
+ /* This is the end of the old stuff */
+
+ struct render_engine *render_engine;
+ struct terminal_emulator *terminal_emulator;
+
+ int t_scrolledback;
+ int r_scrolledback;
+
+ int blanked;
+
+ int vtty;
+};
+
+extern int vconsole_pending;
+extern int vconsole_blankinit;
+extern int vconsole_blankcounter;
+
+extern struct vconsole *vconsole_current;
+
+extern struct render_engine *render_engine_tab[];
+extern struct terminal_emulator *terminal_emulator_tab[];
+
+#endif
+
+/* ioctls for switching between vconsoles */
+
+#define CONSOLE_SWITCHUP _IO( 'n', 0 )
+#define CONSOLE_SWITCHDOWN _IO( 'n', 1 )
+#define CONSOLE_SWITCHTO _IOW( 'n', 2, int )
+#define CONSOLE_SWITCHPREV _IO( 'n', 3 )
+
+/* ioctls for creating new virtual consoles */
+
+#define CONSOLE_CREATE _IOW( 'n', 10, int )
+#define CONSOLE_RENDERTYPE _IOR( 'n', 11, 20 )
+#define CONSOLE_TERMTYPE _IOR( 'n', 12, 20 )
+
+/* ioctls for locking in the current console. Kinky eh ? */
+
+#define CONSOLE_LOCK _IO( 'n', 20 )
+#define CONSOLE_UNLOCK _IO( 'n', 21 )
+
+/* ioctls for animation, multimedia and games */
+
+#define CONSOLE_SWOP _IO( 'n', 30 ) /* Screen Banking */
+
+#ifdef CONSOLEGFX
+struct console_line {
+ int len;
+ char data[128];
+};
+
+struct console_coords {
+ int x, y;
+};
+
+#define CONSOLE_DRAWGFX _IOW( 'n', 31, struct console_line ) /* Screen Banking */
+#define CONSOLE_MOVE _IOW( 'n', 32, struct console_coords )
+#endif
+
+/* ioctls for configuration and control */
+
+#define CONSOLE_CURSORFLASHRATE _IOW ( 'n', 40, int )
+#define CONSOLE_MODE _IOW ( 'n', 41, struct vidc_mode )
+#define CONSOLE_MODE_ALL _IOW ( 'n', 42, struct vidc_mode )
+
+#define CONSOLE_BLANKTIME _IOW ( 'n', 44, int )
+
+/* ioctls for developers *DO NOT USE * */
+
+#define CONSOLE_SPAWN_VIDC _IOW( 'n', 100, int )
+#define CONSOLE_DEBUGPRINT _IOW( 'n', 101, int )
+
+
+/* structures and ioctls added by mark for the Xserver development */
+
+struct console_info {
+ videomemory_t videomemory;
+ int width;
+ int height;
+ int bpp;
+};
+
+struct console_palette {
+ int entry;
+ int red;
+ int green;
+ int blue;
+};
+
+#define CONSOLE_RESETSCREEN _IO( 'n', 102)
+#define CONSOLE_RESTORESCREEN _IO( 'n', 103)
+#define CONSOLE_GETINFO _IOR( 'n', 104, struct console_info )
+#define CONSOLE_PALETTE _IOW( 'n', 105, struct console_palette )
+#define CONSOLE_GETVC _IOR( 'n', 106, int )
+
+#define CONSOLE_IOCTL_COMPAT_N _IO( 'n', 107 )
+#define CONSOLE_IOCTL_COMPAT_T _IO( 't', 107 )
+
+/* End of vconsole.h */
--- /dev/null
+/* $NetBSD: vidc.h,v 1.2 1996/03/28 21:22:24 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994,1995 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * vidc.h
+ *
+ * VIDC20 registers
+ *
+ * Created : 18/09/94
+ * Last updated : 08/03/95
+ *
+ * Based on kate/display/vidc.h
+ *
+ * $Id: vidc.h,v 1.1.1.1 1996/04/24 11:08:46 deraadt Exp $
+ */
+
+#ifndef __vidc_h
+#define __vidc_h
+
+/* VIDC20 Base addresses */
+
+#define VIDC_HW_BASE 0x03400000
+
+#define VIDC_BASE 0xf6100000
+
+/* Video registers */
+
+#define VIDC_PALETTE 0x00000000
+#define VIDC_PALREG 0x10000000
+
+#define VIDC_BCOL 0x40000000
+#define VIDC_CP0 0x40000000
+#define VIDC_CP1 0x50000000
+#define VIDC_CP2 0x60000000
+#define VIDC_CP3 0x70000000
+
+#define VIDC_HCR 0x80000000
+#define VIDC_HSWR 0x81000000
+#define VIDC_HBSR 0x82000000
+#define VIDC_HDSR 0x83000000
+#define VIDC_HDER 0x84000000
+#define VIDC_HBER 0x85000000
+#define VIDC_HCSR 0x86000000
+#define VIDC_HIR 0x87000000
+
+#define VIDC_VCR 0x90000000
+#define VIDC_VSWR 0x91000000
+#define VIDC_VBSR 0x92000000
+#define VIDC_VDSR 0x93000000
+#define VIDC_VDER 0x94000000
+#define VIDC_VBER 0x95000000
+#define VIDC_VCSR 0x96000000
+#define VIDC_VCER 0x97000000
+
+#define VIDC_EREG 0xc0000000
+#define VIDC_FSYNREG 0xd0000000
+#define VIDC_CONREG 0xe0000000
+#define VIDC_DCTL 0xf0000000
+
+/* VIDC palette macros */
+
+#define VIDC_RED(r) (r)
+#define VIDC_GREEN(g) (g << 8)
+#define VIDC_BLUE(b) (b << 16)
+#define VIDC_COL(r, g, b) (VIDC_RED(r) | VIDC_GREEN(g) | VIDC_BLUE(b))
+
+#ifdef RC7500
+/*
+ * Video frequency definitions
+ */
+#define VIDFREQ_25_18 0x00
+#define VIDFREQ_28_32 0x01
+#define VIDFREQ_40_00 0x02
+#define VIDFREQ_72_00 0x03
+#define VIDFREQ_50_00 0x04
+#define VIDFREQ_77_00 0x05
+#define VIDFREQ_36_00 0x06
+#define VIDFREQ_44_90 0x07
+#define VIDFREQ_130_0 0x08
+#define VIDFREQ_120_0 0x09
+#define VIDFREQ_80_00 0x0A
+#define VIDFREQ_31_50 0x0B
+#define VIDFREQ_110_0 0x0C
+#define VIDFREQ_65_00 0x0D
+#define VIDFREQ_75_00 0x0E
+#define VIDFREQ_94_50 0x0F
+#endif
+
+
+/* Sound registers */
+
+#define VIDC_SIR0 0xa0000000
+#define VIDC_SIR1 0xa1000000
+#define VIDC_SIR2 0xa2000000
+#define VIDC_SIR3 0xa3000000
+#define VIDC_SIR4 0xa4000000
+#define VIDC_SIR5 0xa5000000
+#define VIDC_SIR6 0xa6000000
+#define VIDC_SIR7 0xa7000000
+
+#define VIDC_SFR 0xb0000000
+#define VIDC_SCR 0xb1000000
+
+#define SIR_LEFT_100 0x01
+#define SIR_LEFT_83 0x02
+#define SIR_LEFT_67 0x03
+#define SIR_CENTRE 0x04
+#define SIR_RIGHT_67 0x05
+#define SIR_RIGHT_83 0x06
+#define SIR_RIGHT_100 0x07
+
+/* Video display addresses */
+
+/* Where the display memory is mapped */
+
+#define VMEM_VBASE 0xf4000000
+
+/* Where the VRAM will be found */
+
+#define VRAM_BASE 0x02000000
+
+/* Video memory descriptor */
+
+typedef struct
+ {
+ u_int vidm_vbase; /* virtual base of video memory */
+ u_int vidm_pbase; /* physical base of video memory */
+ u_int vidm_size; /* video memory size */
+ int vidm_type; /* video memory type */
+ } videomemory_t;
+
+#define VIDEOMEM_TYPE_VRAM 0x01
+#define VIDEOMEM_TYPE_DRAM 0x02
+
+/* Structures and prototypes for vidc handling functions */
+
+struct vidc_state {
+ int palette[256];
+ int palreg;
+ int bcol;
+ int cp1;
+ int cp2;
+ int cp3;
+ int hcr, hswr, hbsr, hdsr, hder, hber, hcsr;
+ int hir;
+ int vcr, vswr, vbsr, vdsr, vder, vber, vcsr, vcer;
+ int ereg;
+ int fsynreg;
+ int conreg;
+ int dctl;
+};
+
+#define VIDC_FREF 24000000
+
+#ifdef _KERNEL
+extern int vidc_write __P((u_int /*reg*/, int /*value*/));
+extern void vidc_setstate __P((struct vidc_state */*vidc*/));
+extern void vidc_setpalette __P((struct vidc_state */*vidc*/));
+extern void vidc_stdpalette __P(());
+extern int vidc_col __P((int /*red*/, int /*green*/, int /*blue*/));
+extern struct vidc_state vidc_current[];
+#endif
+
+struct vidc_mode {
+ int pixel_rate;
+ int hswr, hbsr, hdsr, hder, hber, hcr;
+ int vswr, vbsr, vdsr, vder, vber, vcr;
+ int bitsperpixel;
+ int sync_pol;
+ int frame_rate;
+};
+
+typedef struct
+ {
+ int chars; /* Number of characters defined in font */
+ int width; /* Defined width of characters in bytes */
+ int height; /* Defined height of characters in lines */
+ int pixel_width; /* Width of characters in pixels */
+ int pixel_height; /* Height of characters in pixels */
+ int x_spacing; /* Spacing in pixels between chars */
+ int y_spacing; /* Spacing in pixels between lines */
+ int data_size; /* Allocated data size */
+ unsigned char *data; /* Font data */
+ } font_struct;
+
+#define XRES mode.hder
+#define YRES mode.vder
+#define BITSPERPIXEL mode.bitsperpixel
+
+struct vidc_info
+ {
+ struct vidc_mode mode;
+ struct vidc_state vidc;
+ font_struct *font; /* pointer to current font_struct */
+ font_struct *normalfont; /* pointer to normal font struct */
+ font_struct *italicfont; /* pointer to italic font struct */
+ font_struct *boldfont; /* pointer to bold font struct */
+ int xfontsize, yfontsize;
+ int text_width, text_height;
+ int bytes_per_line;
+ int bytes_per_scroll;
+ int pixelsperbyte;
+ int screensize;
+ int fast_render;
+ int forecolour, forefillcolour;
+ int backcolour, backfillcolour;
+ int text_colours;
+ int frontporch;
+ int topporch; /* ;) */
+ int bold;
+ int reverse;
+ int n_forecolour;
+ int n_backcolour;
+ int blanked;
+ int scrollback_end;
+ int flash;
+ int cursor_flash;
+ };
+
+#define COLOUR_BLACK_1 0x00
+#define COLOUR_WHITE_1 0x01
+
+#define COLOUR_BLACK_2 0x00
+#define COLOUR_WHITE_2 0x03
+
+#define COLOUR_BLACK_4 0x00
+#define COLOUR_WHITE_4 0x07
+
+#define COLOUR_BLACK_8 0x00
+#define COLOUR_WHITE_8 0x07
+
+#endif
+
+/* End of vidc.h */
+
--- /dev/null
+/* $NetBSD: vmparam.h,v 1.1 1996/01/31 23:23:37 mark Exp $ */
+
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: vmparam.h,v 1.1.1.1 1996/04/24 11:08:46 deraadt Exp $
+ */
+
+#ifndef _ARM32_VMPARAM_H_
+#define _ARM32_VMPARAM_H_
+
+#define USRTEXT VM_MIN_ADDRESS
+#define USRSTACK VM_MAXUSER_ADDRESS
+
+/*
+ * Note that MAXTSIZ mustn't be greater than 32M. Otherwise you'd have
+ * to change the compiler to not generate bl instructions
+ */
+#define MAXTSIZ (8*1024*1024) /* max text size */
+#ifndef DFLDSIZ
+#define DFLDSIZ (16*1024*1024) /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define MAXDSIZ (256*1024*1024) /* max data size */
+#endif
+#ifndef DFLSSIZ
+#define DFLSSIZ (512*1024) /* initial stack size limit */
+#endif
+#ifndef MAXSSIZ
+#define MAXSSIZ (8*1024*1024) /* max stack size */
+#endif
+
+/*
+ * Default sizes of swap allocation chunks (see dmap.h).
+ * The actual values may be changed in vminit() based on MAXDSIZ.
+ * With MAXDSIZ of 16Mb and NDMAP of 38, dmmax will be 1024.
+ */
+#define DMMIN 32 /* smallest swap allocation */
+#define DMMAX 4096 /* largest potential swap allocation */
+#define DMTEXT 1024 /* swap allocation for text */
+
+/*
+ * Size of shared memory map
+ */
+#ifndef SHMMAXPGS
+#define SHMMAXPGS 1024
+#endif
+
+/*
+ * The time for a process to be blocked before being very swappable.
+ * This is a number of seconds which the system takes as being a non-trivial
+ * amount of real time. You probably shouldn't change this;
+ * it is used in subtle ways (fractions and multiples of it are, that is, like
+ * half of a `long time'', almost a long time, etc.)
+ * It is related to human patience and other factors which don't really
+ * change over time.
+ */
+#define MAXSLP 20
+
+/*
+ * Mach derived constants
+ */
+
+/*#define VM_MIN_ADDRESS ((vm_offset_t)0x00400000)*/
+#define VM_MIN_ADDRESS ((vm_offset_t)0x00001000)
+#define VM_MAXUSER_ADDRESS ((vm_offset_t)0xefc00000 - UPAGES * NBPG)
+#define VM_MAX_ADDRESS ((vm_offset_t)0xeffc0000)
+
+#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xf0000000)
+#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xffffffff)
+
+/*
+ * Size of User Raw I/O map
+ */
+
+#define USRIOSIZE 300
+
+/* virtual sizes (bytes) for various kernel submaps */
+
+#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES)
+#define VM_KMEM_SIZE (NKMEMCLUSTERS*CLBYTES)
+#define VM_PHYS_SIZE (USRIOSIZE*CLBYTES)
+
+#endif
+
+/* End of vmparam.h */
+
--- /dev/null
+/* $NetBSD: dumphex.c,v 1.2 1996/03/18 20:32:31 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * dumphex.c
+ *
+ * Hex memory dump routines
+ *
+ * Created : 17/09/94
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/* dumpb - dumps memory in bytes*/
+
+void
+dumpb(addr, count)
+ u_char *addr;
+ int count;
+{
+ u_int byte;
+ int loop;
+
+ for (; count > 0; count -= 16) {
+ printf("%08x: ", (int)addr);
+
+ for (loop = 0; loop < 16; ++loop) {
+ byte = addr[loop];
+ printf("%02x ", byte);
+ }
+
+ printf(" ");
+
+ for (loop = 0; loop < 16; ++loop) {
+ byte = addr[loop];
+ if (byte < 0x20)
+ printf("\x1b[31m%c\x1b[0m", byte + '@');
+ else if (byte == 0x7f)
+ printf("\x1b[31m?\x1b[0m");
+ else if (byte < 0x80)
+ printf("%c", byte);
+ else if (byte < 0xa0)
+ printf("\x1b[32m%c\x1b[0m", byte - '@');
+ else if (byte == 0xff)
+ printf("\x1b[32m?\x1b[0m");
+ else
+ printf("%c", byte & 0x7f);
+ }
+
+ printf("\r\n");
+ addr += 16;
+ }
+}
+
+
+/* dumpw - dumps memory in bytes*/
+
+void
+dumpw(addr, count)
+ u_char *addr;
+ int count;
+{
+ u_int byte;
+ int loop;
+
+ for (; count > 0; count -= 32) {
+ printf("%08x: ", (int)addr);
+
+ for (loop = 0; loop < 8; ++loop) {
+ byte = ((u_int *)addr)[loop];
+ printf("%08x ", byte);
+ }
+
+ printf(" ");
+
+ for (loop = 0; loop < 32; ++loop) {
+ byte = addr[loop];
+ if (byte < 0x20)
+ printf("\x1b[31m%c\x1b[0m", byte + '@');
+ else if (byte == 0x7f)
+ printf("\x1b[31m?\x1b[0m");
+ else if (byte < 0x80)
+ printf("%c", byte);
+ else if (byte < 0xa0)
+ printf("\x1b[32m%c\x1b[0m", byte - '@');
+ else if (byte == 0xff)
+ printf("\x1b[32m?\x1b[0m");
+ else
+ printf("%c", byte & 0x7f);
+ }
+
+ printf("\r\n");
+ addr += 32;
+ }
+}
+
+/* End of dumphex.c */
--- /dev/null
+/* $NetBSD: shell_disassem.c,v 1.2 1996/03/06 23:52:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * shell_disassem.c
+ *
+ * Debug / Monitor shell disassembler
+ *
+ * Created : 09/10/94
+ */
+
+/* Include standard header files */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/* Local header files */
+
+#include <machine/katelib.h>
+
+/* Declare external variables */
+
+/* Local function prototypes */
+
+u_int disassemble __P((u_char *));
+u_int do_disassemble __P((u_char *));
+
+/* Now for the main code */
+
+/* dis - disassembles memory */
+
+void
+shell_disassem(argc, argv)
+ int argc;
+ char *argv[];
+{
+ u_char *addr;
+
+ if (argc < 2) {
+ printf("Syntax: dis <addr>\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ addr = (u_char *)readhex(argv[1]);
+
+ printf("Interactive disassembly\n\r");
+
+ do_disassemble(addr);
+}
+
+
+u_int
+do_disassemble(addr)
+ u_char *addr;
+{
+ u_int result;
+ int quit = 0;
+ int key;
+ int count = 1;
+
+ do {
+ result = disassemble(addr);
+
+ --count;
+
+ if (count == 0) {
+ count = 1;
+
+ key = cngetc();
+
+ switch (key) {
+ case 'Q' :
+ case 'q' :
+ case 0x1b :
+ case 0x03 :
+ case 0x04 :
+ case 0x10b :
+ quit = 1;
+ break;
+ case 0x09 :
+ case 'r' :
+ case 'R' :
+ case 0x103 :
+ count = 16;
+ addr += 4;
+ break;
+
+ case 0x102 :
+ count = 16;
+ addr -= 124;
+ break;
+
+ case 0x0d :
+ case 0x101 :
+ addr = addr + 4;
+ break;
+
+ case 'B' :
+ case 'b' :
+ case 0x100:
+ addr = addr - 4;
+ break;
+
+ case '+' :
+ case '=' :
+ case 0x104 :
+ addr = addr + 0x80;
+ break;
+
+ case '-' :
+ case '_' :
+ case 0x105 :
+ addr = addr - 0x80;
+ break;
+
+ case ' ' :
+ quit = do_disassemble((u_char *)result);
+ break;
+
+ case 'J' :
+ case 'j' :
+ addr = (u_char *)result;
+ break;
+
+ case '/' :
+ case '?' :
+ printf("\'\xe3\' - Backwards 1 word\n\r");
+ printf("\'\xe4\' - Forwards 1 word\n\r");
+ printf("\'\xe5\' - Backwords 16 words\n\r");
+ printf("\'\xe6\' - Forwards 16 words\n\r");
+ printf("\'Q\' - Quit\n\r");
+ printf("\'B\' - Back a word\n\r");
+ printf("\'R\' - Disassemble 16 words\n\r");
+ printf("\'J\' - Jump to address\n\r");
+ printf("\' \' - Branch to address\n\r");
+ printf("<BS> - Return from branch\n\r");
+ printf("\'-\' - Skip backwards 128 words\n\r");
+ printf("\'+\' - Skip forwards 128 words\n\r");
+ break;
+
+ }
+ } else {
+ addr += 4;
+ }
+ } while (!quit && key != 0x08);
+
+ return(quit);
+}
+
+/* End of shell_disassem.c */
--- /dev/null
+/* $NetBSD: shell_input.c,v 1.2 1996/03/06 23:44:07 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * shell_input.c
+ *
+ * string input functions
+ *
+ * Created : 09/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+/*#define SOFT_CURSOR*/
+
+/* Declare global variables */
+
+/* Prototype declarations */
+
+char *strchr __P((const char *, int));
+
+void deleteline __P((int, int));
+
+/*
+ * Reads a line from the keyboard into an input buffer allowing
+ * cursor editing and input history.
+ */
+
+int
+readstring(string, length, valid_string, insert)
+ char *string;
+ int length;
+ char *valid_string;
+ char *insert;
+{
+ int key;
+ int loop;
+ int entered;
+ int insert_mode = 1;
+
+/*
+ * If we have text to preinsert into the buffer enter it and echo it
+ * to the display.
+ */
+
+ if (insert && insert[0] != 0) {
+ strcpy(string, insert);
+ loop = strlen(insert);
+ printf("%s", insert);
+ } else
+ loop = 0;
+
+ entered = loop;
+
+/*
+ * The main loop.
+ * Keep looping until return or CTRL-D is pressed.
+ */
+
+ do {
+#ifdef SOFT_CURSOR
+/*
+ * Display the cursor depending on what mode we are in
+ */
+ if (!insert_mode)
+ printf("\xe2");
+ else
+ printf("\xe1");
+#endif
+
+/*
+ * Read the keyboard
+ */
+
+ key = cngetc();
+
+#ifdef SOFT_CURSOR
+/*
+ * Remove the cursor, restoring the text under it if necessary.
+ */
+
+ if (loop == entered || entered == 0)
+ printf("\x7f");
+ else
+ printf("\x08%c\x08", string[loop]);
+#endif
+
+/*
+ * Decode the key
+ */
+
+ switch (key) {
+/*
+ * DELETE
+ */
+
+ case 0x109 :
+ case 0x7f :
+ {
+ int loop1;
+
+ if (loop == entered) break;
+ for (loop1 = loop; loop1 < (entered - 1); ++loop1) {
+ string[loop1] = string[loop1+1];
+ }
+ --entered;
+ string[entered] = 0;
+/* printf("\x1b[s%s \x1b[u", &string[loop]);*/
+ printf("\r%s \r", string);
+ for (loop1 = 0; loop1 <= loop; ++loop1)
+ printf("\x09");
+ }
+ break;
+
+/*
+ * BACKSPACE
+ */
+
+ case 0x08 :
+ {
+ int loop1;
+
+ if (loop == 0) {
+ printf("\x07");
+ break;
+ }
+ for (loop1 = loop-1; loop1 < (entered - 1); ++loop1) {
+ string[loop1] = string[loop1+1];
+ }
+ --loop;
+ --entered;
+ string[entered] = 0;
+/* printf("\x1b[D\x1b[s%s \x1b[u", &string[loop]);*/
+ printf("\r%s \r", string);
+ for (loop1 = 0; loop1 < loop; ++loop1)
+ printf("\x09");
+ }
+ break;
+
+/*
+ * CTRL-U
+ */
+ case 0x15 :
+ deleteline(loop, entered);
+ loop = 0;
+ entered = 0;
+ break;
+
+/*
+ * CTRL-A
+ */
+ case 0x01 :
+ insert_mode = !insert_mode;
+ break;
+
+/*
+ * CTRL-D
+ */
+ case 0x04 :
+ return(-1);
+ break;
+
+/*
+ * CURSOR LEFT
+ */
+
+ case 0x102 :
+ --loop;
+ if (loop < 0)
+ loop = 0;
+ else
+ printf("\x1b[D");
+ break;
+
+/*
+ * CURSOR RIGHT
+ */
+
+ case 0x103 :
+ ++loop;
+ if (loop > entered)
+ loop = entered;
+ else
+ printf("\x1b[C");
+ break;
+
+/*
+ * RETURN
+ */
+
+ case 0x0d :
+ case 0x0a :
+ break;
+
+/*
+ * Another key
+ */
+
+ default :
+
+/*
+ * Check for a valid key to enter
+ */
+
+ if (key < 0x100 && key > 0x1f
+ && (valid_string == NULL || strchr(valid_string, key))) {
+ if (!insert_mode && loop < length) {
+ string[loop] = key;
+ printf("%c", key);
+ ++loop;
+ if (loop > entered) entered = loop;
+ }
+ else if (entered < length) {
+ int loop1;
+
+ for (loop1 = entered; loop1 >= loop; --loop1) {
+ string[loop1+1] = string[loop1];
+ }
+ string[loop] = key;
+ ++loop;
+ ++entered;
+ string[entered] = 0;
+ if (loop != entered) printf("\x1b[s");
+ printf("%s", &string[loop-1]);
+ if (loop != entered) printf("\x1b[u\x1b[C");
+ } else {
+ printf("\x07");
+ }
+ }
+ break;
+ }
+ } while (key != 0x0d && key != 0x0a);
+
+ printf("\n\r");
+
+ string[entered] = 0;
+
+ return(entered);
+}
+
+
+/* This erases a line of text */
+
+void
+deleteline(loop, entered)
+ int loop;
+ int entered;
+{
+ while (loop < entered) {
+ ++loop;
+ printf("\x1b[C");
+ }
+
+ while (loop > 0) {
+ --loop;
+ --entered;
+ printf("\x7f");
+ }
+}
+
+/* End of shell_input.c */
--- /dev/null
+/* $NetBSD: shell_shell.c,v 1.5 1996/04/19 20:15:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * shell_shell.c
+ *
+ * Debug / Monitor shell entry and commands
+ *
+ * Created : 09/10/94
+ */
+
+/* Include standard header files */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/vnode.h>
+#include <vm/vm.h>
+
+/* Local header files */
+
+#include <machine/pmap.h>
+#include <machine/katelib.h>
+#include <machine/vidc.h>
+#include <machine/rtc.h>
+
+/* Declare global variables */
+
+/* Local function prototypes */
+
+char *strchr __P((const char *, int));
+
+void dumpb __P((u_char */*addr*/, int /*count*/));
+void dumpw __P((u_char */*addr*/, int /*count*/));
+
+int readstring __P((char *, int, char *, char *));
+
+void debug_show_q_details __P((void));
+void shell_disassem __P((int argc, char *argv[]));
+void shell_devices __P((int argc, char *argv[]));
+void shell_vmmap __P((int argc, char *argv[]));
+void shell_flush __P((int argc, char *argv[]));
+void shell_pextract __P((int argc, char *argv[]));
+void shell_vnode __P((int argc, char *argv[]));
+void debug_show_all_procs __P((int argc, char *argv[]));
+void debug_show_callout __P((int argc, char *argv[]));
+void debug_show_fs __P((int argc, char *argv[]));
+void debug_show_vm_map __P((vm_map_t map, char *text));
+void debug_show_pmap __P((pmap_t pmap));
+void pmap_dump_pvs __P((void));
+void bootsync __P((void));
+
+/* Now for the main code */
+
+/* readhex
+ *
+ * This routine interprets the input string as a sequence of hex characters
+ * and returns it as an integer.
+ */
+
+int
+readhex(buf)
+ char *buf;
+{
+ int value;
+ int nibble;
+
+ if (buf == NULL)
+ return(0);
+
+/* skip any spaces */
+
+ while (*buf == ' ')
+ ++buf;
+
+/* return 0 if a zero length string is passed */
+
+ if (*buf == 0)
+ return(0);
+
+/* Convert the characters */
+
+ value = 0;
+
+ while (*buf != 0 && strchr("0123456789abcdefABCDEF", *buf) != 0) {
+ nibble = (*buf - '0');
+ if (nibble > 9) nibble -= 7;
+ if (nibble > 15) nibble -= 32;
+ value = (value << 4) | nibble;
+ ++buf;
+ }
+
+ return(value);
+}
+
+
+/* poke - writes a byte/word to memory */
+
+void
+shell_poke(argc, argv)
+ int argc;
+ char *argv[];
+{
+ u_int addr;
+ u_int data;
+
+ if (argc < 3) {
+ printf("Syntax: poke[bw] <addr> <data>\n\r");
+ return;
+ }
+
+/* Decode the two arguments */
+
+ addr = readhex(argv[1]);
+ data = readhex(argv[2]);
+
+ if (argv[0][4] == 'b')
+ WriteByte(addr, data);
+ if (argv[0][4] == 'w')
+ WriteWord(addr, data);
+}
+
+
+/* peek - reads a byte/word from memory*/
+
+void
+shell_peek(argc, argv)
+ int argc;
+ char *argv[];
+{
+ u_int addr;
+ u_int data;
+
+ if (argc < 2) {
+ printf("Syntax: peek[bw] <addr>\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ addr = readhex(argv[1]);
+
+ if (argv[0][4] == 'b')
+ data = ReadByte(addr);
+ if (argv[0][4] == 'w')
+ data = ReadWord(addr);
+
+ printf("%08x : %08x\n\r", addr, data);
+}
+
+
+/* dumpb - dumps memory in bytes*/
+
+void
+shell_dumpb(argc, argv)
+ int argc;
+ char *argv[];
+{
+ u_char *addr;
+ int count;
+
+ if (argc < 2) {
+ printf("Syntax: dumpb <addr> [<bytes>]\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ addr = (u_char *)readhex(argv[1]);
+
+ if (argc > 2)
+ count = readhex(argv[2]);
+ else
+ count = 0x80;
+
+ dumpb(addr, count);
+}
+
+
+/* dumpw - dumps memory in bytes*/
+
+void
+shell_dumpw(argc, argv)
+ int argc;
+ char *argv[];
+{
+ u_char *addr;
+ int count;
+
+ if (argc < 2) {
+ printf("Syntax: dumpw <addr> [<bytes>]\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ addr = (u_char *)readhex(argv[1]);
+
+ if (argc > 2)
+ count = readhex(argv[2]);
+ else
+ count = 0x80;
+
+ dumpw(addr, count);
+}
+
+
+/* vmmap - dumps the vmmap */
+
+void
+shell_vmmap(argc, argv)
+ int argc;
+ char *argv[];
+{
+ u_char *addr;
+
+ if (argc < 2) {
+ printf("Syntax: vmmap <map addr>\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ addr = (u_char *)readhex(argv[1]);
+
+ debug_show_vm_map((vm_map_t)addr, argv[1]);
+}
+
+
+/* pmap - dumps the pmap */
+
+void
+shell_pmap(argc, argv)
+ int argc;
+ char *argv[];
+{
+ u_char *addr;
+
+ if (argc < 2) {
+ printf("Syntax: pmap <pmap addr>\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ addr = (u_char *)readhex(argv[1]);
+
+ debug_show_pmap((pmap_t)addr);
+}
+
+
+/*
+ * void shell_devices(int argc, char *argv[])
+ *
+ * Display all the devices
+ */
+
+extern struct cfdata cfdata[];
+
+void
+shell_devices(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct cfdata *cf;
+ struct cfdriver *cd;
+ struct device *dv;
+ int loop;
+ char *state;
+
+ printf(" driver unit state name\n");
+ for (cf = cfdata; cf->cf_driver; ++cf) {
+ cd = cf->cf_driver;
+ if (cf->cf_fstate & FSTATE_FOUND)
+ state = "FOUND ";
+ else
+ state = "NOT FOUND";
+
+ printf("%08x %2d %s %s\n", (u_int)cd, (u_int)cf->cf_unit,
+ state, cd->cd_name);
+
+ if (cf->cf_fstate & FSTATE_FOUND) {
+ for (loop = 0; loop < cd->cd_ndevs; ++loop) {
+ dv = (struct device *)cd->cd_devs[loop];
+ if (dv != 0)
+ printf(" %s (%08x)\n",
+ dv->dv_xname, (u_int) dv);
+ }
+ }
+ printf("\n");
+ }
+}
+
+
+void
+shell_reboot(argc, argv)
+ int argc;
+ char *argv[];
+{
+ printf("Running shutdown hooks ...\n");
+ doshutdownhooks();
+
+ IRQdisable;
+ boot0();
+}
+
+void
+forceboot(argc, argv)
+ int argc;
+ char *argv[];
+{
+ cmos_write(0x90, cmos_read(0x90) | 0x02);
+ shell_reboot(0, NULL);
+}
+
+
+void
+shell_flush(argc, argv)
+ int argc;
+ char *argv[];
+{
+ idcflush();
+ tlbflush();
+}
+
+
+void
+shell_vmstat(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct vmmeter sum;
+
+ sum = cnt;
+ (void)printf("%9u cpu context switches\n", sum.v_swtch);
+ (void)printf("%9u device interrupts\n", sum.v_intr);
+ (void)printf("%9u software interrupts\n", sum.v_soft);
+ (void)printf("%9u traps\n", sum.v_trap);
+ (void)printf("%9u system calls\n", sum.v_syscall);
+ (void)printf("%9u total faults taken\n", sum.v_faults);
+ (void)printf("%9u swap ins\n", sum.v_swpin);
+ (void)printf("%9u swap outs\n", sum.v_swpout);
+ (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
+ (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
+ (void)printf("%9u page ins\n", sum.v_pageins);
+ (void)printf("%9u page outs\n", sum.v_pageouts);
+ (void)printf("%9u pages paged in\n", sum.v_pgpgin);
+ (void)printf("%9u pages paged out\n", sum.v_pgpgout);
+ (void)printf("%9u pages reactivated\n", sum.v_reactivated);
+ (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
+ (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
+ (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
+ (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan);
+ (void)printf("%9u revolutions of the clock hand\n", sum.v_rev);
+ (void)printf("%9u VM object cache lookups\n", sum.v_lookups);
+ (void)printf("%9u VM object hits\n", sum.v_hits);
+ (void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
+ (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
+ (void)printf("%9u pages freed by daemon\n", sum.v_dfree);
+ (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
+ (void)printf("%9u pages free\n", sum.v_free_count);
+ (void)printf("%9u pages wired down\n", sum.v_wire_count);
+ (void)printf("%9u pages active\n", sum.v_active_count);
+ (void)printf("%9u pages inactive\n", sum.v_inactive_count);
+ (void)printf("%9u bytes per page\n", sum.v_page_size);
+}
+
+
+void
+shell_pextract(argc, argv)
+ int argc;
+ char *argv[];
+{
+ u_char *addr;
+ vm_offset_t pa;
+ int pind;
+
+ if (argc < 2) {
+ printf("Syntax: pextract <addr>\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ addr = (u_char *)readhex(argv[1]);
+
+ pa = pmap_extract(kernel_pmap, (vm_offset_t)addr);
+ pind = pmap_page_index(pa);
+
+ printf("va=%08x pa=%08x pind=%d\n", (u_int)addr, (u_int)pa, pind);
+}
+
+
+void
+shell_vnode(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct vnode *vp;
+
+ if (argc < 2) {
+ printf("Syntax: vnode <vp>\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ vp = (struct vnode *)readhex(argv[1]);
+
+ printf("vp = %08x\n", (u_int)vp);
+ printf("vp->v_type = %d\n", vp->v_type);
+ printf("vp->v_flag = %ld\n", vp->v_flag);
+ printf("vp->v_usecount = %d\n", vp->v_usecount);
+ printf("vp->v_writecount = %d\n", vp->v_writecount);
+ printf("vp->v_numoutput = %ld\n", vp->v_numoutput);
+
+ vprint("vnode:", vp);
+}
+
+#if 0
+void
+shell_vndbuf(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct vnode *vp;
+
+ if (argc < 2) {
+ printf("Syntax: vndbuf <vp>\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ vp = (struct vnode *)readhex(argv[1]);
+
+ dumpvndbuf(vp);
+}
+
+
+void
+shell_vncbuf(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct vnode *vp;
+
+ if (argc < 2) {
+ printf("Syntax: vndbuf <vp>\n\r");
+ return;
+ }
+
+/* Decode the one argument */
+
+ vp = (struct vnode *)readhex(argv[1]);
+
+ dumpvncbuf(vp);
+}
+#endif
+
+/* shell - a crude shell */
+
+int
+shell()
+{
+ int quit = 0;
+ char buffer[200];
+ char *ptr;
+ char *ptr1;
+ int args;
+ char *argv[20];
+
+ printf("\nRiscBSD debug/monitor shell\n");
+ printf("CTRL-D, exit or reboot to terminate\n\n");
+
+ do {
+/* print prompt */
+
+ printf("kshell> ");
+
+/* Read line from keyboard */
+
+ if (readstring(buffer, 200, NULL, NULL) == -1)
+ return(0);
+
+ ptr = buffer;
+
+/* Slice leading spaces */
+
+ while (*ptr == ' ')
+ ++ptr;
+
+/* Loop back if zero length string */
+
+ if (*ptr == 0)
+ continue;
+
+/* Count the number of space separated args */
+
+ args = 0;
+ ptr1 = ptr;
+
+ while (*ptr1 != 0) {
+ if (*ptr1 == ' ') {
+ ++args;
+ while (*ptr1 == ' ')
+ ++ptr1;
+ } else
+ ++ptr1;
+ }
+
+/*
+ * Construct the array of pointers to the args and terminate
+ * each argument with 0x00
+ */
+
+ args = 0;
+ ptr1 = ptr;
+
+ while (*ptr1 != 0) {
+ argv[args] = ptr1;
+ ++args;
+ while (*ptr1 != ' ' && *ptr1 != 0)
+ ++ptr1;
+
+ while (*ptr1 == ' ') {
+ *ptr1 = 0;
+ ++ptr1;
+ }
+ }
+
+ argv[args] = NULL;
+
+/* Interpret commands */
+
+ if (strcmp(argv[0], "exit") == 0)
+ quit = 1;
+#ifdef DDB
+ else if (strcmp(argv[0], "deb") == 0)
+ Debugger();
+#endif
+ else if (strcmp(argv[0], "peekb") == 0)
+ shell_peek(args, argv);
+ else if (strcmp(argv[0], "pokeb") == 0)
+ shell_poke(args, argv);
+ else if (strcmp(argv[0], "peekw") == 0)
+ shell_peek(args, argv);
+ else if (strcmp(argv[0], "pokew") == 0)
+ shell_poke(args, argv);
+ else if (strcmp(argv[0], "dumpb") == 0)
+ shell_dumpb(args, argv);
+ else if (strcmp(argv[0], "reboot") == 0)
+ shell_reboot(args, argv);
+ else if (strcmp(argv[0], "dumpw") == 0)
+ shell_dumpw(args, argv);
+ else if (strcmp(argv[0], "dump") == 0)
+ shell_dumpw(args, argv);
+ else if (strcmp(argv[0], "dis") == 0)
+ shell_disassem(args, argv);
+ else if (strcmp(argv[0], "qs") == 0)
+ debug_show_q_details();
+ else if (strcmp(argv[0], "ps") == 0)
+ debug_show_all_procs(args, argv);
+ else if (strcmp(argv[0], "callouts") == 0)
+ debug_show_callout(args, argv);
+ else if (strcmp(argv[0], "devices") == 0)
+ shell_devices(args, argv);
+ else if (strcmp(argv[0], "listfs") == 0)
+ debug_show_fs(args, argv);
+ else if (strcmp(argv[0], "vmmap") == 0)
+ shell_vmmap(args, argv);
+ else if (strcmp(argv[0], "pmap") == 0)
+ shell_pmap(args, argv);
+ else if (strcmp(argv[0], "flush") == 0)
+ shell_flush(args, argv);
+ else if (strcmp(argv[0], "vmstat") == 0)
+ shell_vmstat(args, argv);
+ else if (strcmp(argv[0], "pdstat") == 0)
+ pmap_pagedir_dump();
+ else if (strcmp(argv[0], "traceback") == 0)
+ traceback();
+ else if (strcmp(argv[0], "forceboot") == 0)
+ forceboot(args, argv);
+ else if (strcmp(argv[0], "dumppvs") == 0)
+ pmap_dump_pvs();
+ else if (strcmp(argv[0], "pextract") == 0)
+ shell_pextract(args, argv);
+ else if (strcmp(argv[0], "vnode") == 0)
+ shell_vnode(args, argv);
+ else if (strcmp(argv[0], "ascdump") == 0)
+ asc_dump();
+ else if (strcmp(argv[0], "help") == 0
+ || strcmp(argv[0], "?") == 0) {
+ printf("peekb <hexaddr>\r\n");
+ printf("pokeb <hexaddr> <data>\r\n");
+ printf("peekw <hexaddr>\r\n");
+ printf("pokew <hexaddr <data>\r\n");
+ printf("dis <hexaddr>\r\n");
+ printf("dumpb <hexaddr> [length]\r\n");
+ printf("dumpw <hexaddr> [length]\r\n");
+ printf("dump <hexaddr> [length]\r\n");
+ printf("reboot\r\n");
+ printf("qs\r\n");
+ printf("ps [m]\r\n");
+ printf("vmstat\n");
+ printf("listfs\n");
+ printf("devices\n");
+ printf("callouts\n");
+ printf("prompt\r\n");
+ printf("vmmap <vmmap addr>\r\n");
+ printf("pmap <pmap addr>\r\n");
+ printf("pdstat\r\n");
+ printf("flush\r\n");
+ printf("exit\r\n");
+ printf("forceboot\r\n");
+ printf("dumppvs\r\n");
+ printf("pextract <phys addr>\r\n");
+ printf("vnode <vp>\r\n");
+ printf("ascdump\r\n");
+ }
+ } while (!quit);
+
+ return(0);
+}
+
+/* End of shell_shell.c */
--- /dev/null
+/* $NetBSD: strchr.c,v 1.2 1996/03/18 20:32:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD kernel team.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/param.h>
+
+char *
+strchr(s, c)
+ register char *s;
+ int c;
+{
+ do {
+ if (*s == c) {
+ return (s);
+ }
+ } while (*s++);
+ return (0);
+}
+
+/* End of strchr.c */
--- /dev/null
+/* $NetBSD: beep.c,v 1.4 1996/03/27 22:08:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Simple beep sounds using VIDC
+ */
+
+/*
+ * To use the driver, open /dev/beep and write lines.
+ * Each write will generate a beep
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <dev/cons.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <machine/iomd.h>
+#include <machine/vidc.h>
+#include <machine/pmap.h>
+#include <machine/beep.h>
+#include <arm32/mainbus/mainbus.h>
+#include <arm32/mainbus/waveform.h>
+
+#include "beep.h"
+
+struct beep_softc {
+ struct device sc_device;
+ irqhandler_t sc_ih;
+ int sc_iobase;
+ int sc_open;
+ int sc_count;
+ u_int sc_sound_cur0;
+ u_int sc_sound_end0;
+ u_int sc_sound_cur1;
+ u_int sc_sound_end1;
+ vm_offset_t sc_buffer0;
+ vm_offset_t sc_buffer1;
+};
+
+int beepprobe __P((struct device *parent, void *match, void *aux));
+void beepattach __P((struct device *parent, struct device *self, void *aux));
+int beepopen __P((dev_t, int, int, struct proc *));
+int beepclose __P((dev_t, int, int, struct proc *));
+int beepintr __P((struct beep_softc *sc));
+void beepdma __P((struct beep_softc *sc, int buf));
+
+struct cfattach beep_ca = {
+ sizeof(struct beep_softc), beepprobe, beepattach
+};
+
+struct cfdriver beep_cd = {
+ NULL, "beep", DV_TTY
+};
+
+
+int
+beepprobe(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+/* struct mainbus_attach_args *mb = aux;*/
+ int id;
+
+/* Make sure we have an IOMD we understand */
+
+ id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+ switch (id) {
+ case RPC600_IOMD_ID:
+ return(1);
+ break;
+ default:
+ printf("beep: Unknown IOMD id=%04x", id);
+ break;
+ }
+ return(0);
+}
+
+
+void
+beepattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct beep_softc *sc = (void *)self;
+ struct mainbus_attach_args *mb = aux;
+
+ sc->sc_iobase = mb->mb_iobase;
+ sc->sc_open = 0;
+ sc->sc_count = 0;
+
+ sc->sc_buffer0 = kmem_alloc(kernel_map, NBPG);
+ if (sc->sc_buffer0 == 0)
+ panic("beep: Cannot allocate buffer memory\n");
+ if ((sc->sc_buffer0 & (NBPG -1)) != 0)
+ panic("beep: Cannot allocate page aligned buffer\n");
+ sc->sc_buffer1 = sc->sc_buffer0;
+
+ sc->sc_sound_cur0 = pmap_extract(kernel_pmap,
+ (vm_offset_t)sc->sc_buffer0 & PG_FRAME);
+ sc->sc_sound_end0 = (sc->sc_sound_cur0 + NBPG - 16) | 0x00000000;
+ sc->sc_sound_cur1 = pmap_extract(kernel_pmap,
+ (vm_offset_t)sc->sc_buffer1 & PG_FRAME);
+ sc->sc_sound_end1 = (sc->sc_sound_cur1 + NBPG - 16) | 0x00000000;
+
+ bcopy(beep_waveform, (void *)sc->sc_buffer0, sizeof(beep_waveform));
+
+/* Reset the sound DMA channel */
+
+ WriteWord(IOMD_SD0CURA, sc->sc_sound_cur0);
+ WriteWord(IOMD_SD0ENDA, sc->sc_sound_end0 | 0xc0000000);
+ WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1);
+ WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | 0xc0000000);
+
+ WriteByte(IOMD_SD0CR, 0x90);
+
+/* Install an IRQ handler */
+
+ sc->sc_ih.ih_func = beepintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_NONE;
+ sc->sc_ih.ih_name = "dma snd ch 0";
+
+ if (irq_claim(IRQ_DMASCH0, &sc->sc_ih))
+ panic("Cannot claim DMASCH0 IRQ for beep%d\n", parent->dv_unit);
+
+ disable_irq(IRQ_DMASCH0);
+
+/*
+ printf(" [ buf0=%08x:%08x->%08x buf1=%08x:%08x->%08x ]",
+ (u_int)sc->sc_buffer0, sc->sc_sound_cur0, sc->sc_sound_end0,
+ (u_int)sc->sc_buffer1, sc->sc_sound_cur1, sc->sc_sound_end1);
+*/
+ printf("\n");
+
+/* Set sample rate to 32us */
+
+ WriteWord(VIDC_BASE, VIDC_SFR | 32);
+
+/* Set the stereo postions to centred for all channels */
+
+ WriteWord(VIDC_BASE, VIDC_SIR0 | SIR_CENTRE);
+ WriteWord(VIDC_BASE, VIDC_SIR1 | SIR_CENTRE);
+ WriteWord(VIDC_BASE, VIDC_SIR2 | SIR_CENTRE);
+ WriteWord(VIDC_BASE, VIDC_SIR3 | SIR_CENTRE);
+ WriteWord(VIDC_BASE, VIDC_SIR4 | SIR_CENTRE);
+ WriteWord(VIDC_BASE, VIDC_SIR5 | SIR_CENTRE);
+ WriteWord(VIDC_BASE, VIDC_SIR6 | SIR_CENTRE);
+ WriteWord(VIDC_BASE, VIDC_SIR7 | SIR_CENTRE);
+}
+
+
+int
+beepopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct beep_softc *sc;
+ int unit = minor(dev);
+ int s;
+
+ if (unit >= beep_cd.cd_ndevs)
+ return(ENXIO);
+
+ sc = beep_cd.cd_devs[unit];
+ if (!sc) return(ENXIO);
+
+/* HACK hack hack */
+
+ s = splhigh();
+ if (sc->sc_open) {
+ (void)splx(s);
+ return(EBUSY);
+ }
+
+ ++sc->sc_open;
+ (void)splx(s);
+
+ return(0);
+}
+
+
+int
+beepclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ int unit = minor(dev);
+ struct beep_softc *sc = beep_cd.cd_devs[unit];
+ int s;
+
+ if (sc->sc_open == 0) return(ENXIO);
+
+/* HACK hack hack */
+
+ s = splhigh();
+ --sc->sc_open;
+ (void)splx(s);
+
+ return(0);
+}
+
+
+void
+beep_generate(void)
+{
+ struct beep_softc *sc = beep_cd.cd_devs[0];
+/* int status;*/
+
+ if (sc->sc_count > 0) {
+/* printf("beep: active\n");*/
+ return;
+ }
+/* printf("beep: generate ");*/
+ ++sc->sc_count;
+
+/* status = ReadByte(IOMD_SD0ST);
+ printf("st=%02x\n", status);*/
+ WriteByte(IOMD_SD0CR, 0x90);
+ WriteByte(IOMD_SD0CR, 0x30);
+ beepdma(sc, 0);
+}
+
+
+int
+beepioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct beep_softc *sc = beep_cd.cd_devs[minor(dev)];
+ int rate;
+ struct wavebuffer *wave = (struct wavebuffer *)data;
+
+ switch (cmd) {
+ case BEEP_GENERATE:
+ beep_generate();
+ break;
+
+ case BEEP_SETRATE:
+ rate = *(int *)data;
+
+ if (rate < 3 || rate > 255)
+ return(EINVAL);
+
+ WriteWord(VIDC_BASE, VIDC_SFR | rate);
+ break;
+
+ case BEEP_SET:
+ printf("set %08x\n", (u_int)data);
+ printf("set %08x %08x\n", (u_int)wave->addr, wave->size);
+ if (wave->size < 16 || wave->size > NBPG)
+ return(ENXIO);
+ copyin(wave->addr, (char *)sc->sc_buffer0, wave->size);
+ sc->sc_sound_end0 = (sc->sc_sound_cur0 + wave->size - 16);
+ sc->sc_sound_end1 = (sc->sc_sound_cur1 + wave->size - 16);
+ break;
+
+ default:
+ return(ENXIO);
+ break;
+ }
+
+ return(0);
+}
+
+
+int
+beepintr(sc)
+ struct beep_softc *sc;
+{
+/* printf("beepintr: %02x,%02x,%02x,%d\n", ReadByte(IOMD_DMARQ),
+ ReadByte(IOMD_SD0CR), ReadByte(IOMD_SD0ST), sc->sc_count);*/
+ WriteByte(IOMD_DMARQ, 0x10);
+ --sc->sc_count;
+ if (sc->sc_count <= 0) {
+ WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1);
+ WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | (1 << 30));
+ disable_irq(IRQ_DMASCH0);
+/* printf("stop:st=%02x\n", ReadByte(IOMD_SD0ST));*/
+ return(1);
+ }
+
+ beepdma(sc, sc->sc_count & 1);
+ return(1);
+}
+
+
+void
+beepdma(sc, buf)
+ struct beep_softc *sc;
+ int buf;
+{
+ int status;
+/* printf("beep:dma %d", buf); */
+ status = ReadByte(IOMD_SD0ST);
+/* printf("st=%02x\n", status);*/
+
+ if (buf == 0) {
+ WriteWord(IOMD_SD0CURA, sc->sc_sound_cur0);
+ WriteWord(IOMD_SD0ENDA, sc->sc_sound_end0);
+ WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1);
+ WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | (1 << 30));
+ }
+
+ if (buf == 1) {
+ WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1);
+ WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | (1 << 30));
+ }
+
+/* status = ReadByte(IOMD_SD0ST);
+ printf("st=%02x\n", status);*/
+
+ enable_irq(IRQ_DMASCH0);
+}
+
+/* End of beep.c */
--- /dev/null
+/* $NetBSD: com.c,v 1.5 1996/03/28 21:52:32 mark Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)com.c 7.5 (Berkeley) 5/16/91
+ */
+
+/*
+ * COM driver, based on HP dca driver
+ * uses National Semiconductor NS16450/NS16550AF UART
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/types.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/irqhandler.h>
+#include <machine/io.h>
+#include <arm32/mainbus/comreg.h>
+#include <arm32/mainbus/mainbus.h>
+
+#define com_lcr com_cfcr
+
+#define COM_IBUFSIZE (2 * 256)
+#define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4)
+
+struct com_softc {
+ struct device sc_dev;
+ irqhandler_t sc_ih;
+ struct tty *sc_tty;
+
+ int sc_overflows;
+ int sc_floods;
+ int sc_errors;
+
+ int sc_iobase;
+ u_char sc_hwflags;
+#define COM_HW_NOIEN 0x01
+#define COM_HW_FIFO 0x02
+#define COM_HW_CONSOLE 0x40
+ u_char sc_swflags;
+#define COM_SW_SOFTCAR 0x01
+#define COM_SW_CLOCAL 0x02
+#define COM_SW_CRTSCTS 0x04
+#define COM_SW_MDMBUF 0x08
+ u_char sc_msr, sc_mcr, sc_lcr;
+ u_char sc_dtr;
+
+ u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend;
+ u_char sc_ibufs[2][COM_IBUFSIZE];
+};
+
+int comprobe __P((struct device *, void *, void *));
+void comattach __P((struct device *, struct device *, void *));
+int comopen __P((dev_t, int, int, struct proc *));
+int comclose __P((dev_t, int, int, struct proc *));
+void comdiag __P((void *));
+int comintr __P((void *));
+void compoll __P((void *));
+int comparam __P((struct tty *, struct termios *));
+void comstart __P((struct tty *));
+
+struct cfattach com_ca = {
+ sizeof(struct com_softc), comprobe, comattach
+};
+
+struct cfdriver com_cd = {
+ NULL, "com", DV_TTY
+};
+
+int comdefaultrate = TTYDEF_SPEED;
+#ifdef COMCONSOLE
+int comconsole = COMCONSOLE;
+#else
+int comconsole = -1;
+#endif
+int comconsinit;
+int commajor;
+int comsopen = 0;
+int comevents = 0;
+
+#ifdef KGDB
+#include <machine/remote-sl.h>
+extern int kgdb_dev;
+extern int kgdb_rate;
+extern int kgdb_debug_init;
+#endif
+
+#define COMUNIT(x) (minor(x))
+
+/* Macros to clear/set/test flags. */
+#define SET(t, f) (t) |= (f)
+#define CLR(t, f) (t) &= ~(f)
+#define ISSET(t, f) ((t) & (f))
+
+int
+comspeed(speed)
+ long speed;
+{
+#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
+
+ int x, err;
+
+ if (speed == 0)
+ return 0;
+ if (speed < 0)
+ return -1;
+ x = divrnd((COM_FREQ / 16), speed);
+ if (x <= 0)
+ return -1;
+ err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
+ if (err < 0)
+ err = -err;
+ if (err > COM_TOLERANCE)
+ return -1;
+ return x;
+
+#undef divrnd(n, q)
+}
+
+int
+comprobe1(iobase)
+ int iobase;
+{
+
+ /* force access to id reg */
+ outb(iobase + com_lcr, 0);
+ outb(iobase + com_iir, 0);
+ if (inb(iobase + com_iir) & 0x38)
+ return 0;
+
+ return 1;
+}
+
+int
+comprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct mainbus_attach_args *mb = aux;
+ int iobase = mb->mb_iobase;
+
+ if (!comprobe1(iobase))
+ return 0;
+
+ mb->mb_iosize = COM_NPORTS;
+ return 1;
+}
+
+void
+comattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct com_softc *sc = (void *)self;
+ struct mainbus_attach_args *mb = aux;
+ struct cfdata *cf = sc->sc_dev.dv_cfdata;
+ int iobase = mb->mb_iobase;
+ struct tty *tp;
+
+ sc->sc_iobase = iobase;
+ sc->sc_hwflags = ISSET(cf->cf_flags, COM_HW_NOIEN);
+ sc->sc_swflags = 0;
+
+ if (sc->sc_dev.dv_unit == comconsole)
+ delay(1000);
+
+ /* look for a NS 16550AF UART with FIFOs */
+ outb(iobase + com_fifo,
+ FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
+ delay(100);
+ if (ISSET(inb(iobase + com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK)
+ if (ISSET(inb(iobase + com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
+ SET(sc->sc_hwflags, COM_HW_FIFO);
+ printf(": ns16550a, working fifo\n");
+ } else
+ printf(": ns16550, broken fifo\n");
+ else
+ printf(": ns8250 or ns16450, no fifo\n");
+ outb(iobase + com_fifo, 0);
+
+ /* disable interrupts */
+ outb(iobase + com_ier, 0);
+ outb(iobase + com_mcr, 0);
+
+ sc->sc_ih.ih_func = comintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_TTY;
+ sc->sc_ih.ih_name = "serial";
+ if (mb->mb_irq != IRQUNK)
+ if (irq_claim(mb->mb_irq, &sc->sc_ih))
+ panic("Cannot claim IRQ %d for com%d\n", mb->mb_irq, sc->sc_dev.dv_unit);
+
+#ifdef KGDB
+ if (kgdb_dev == makedev(commajor, unit)) {
+ if (comconsole == unit)
+ kgdb_dev = -1; /* can't debug over console port */
+ else {
+ (void) cominit(unit, kgdb_rate);
+ if (kgdb_debug_init) {
+ /*
+ * Print prefix of device name,
+ * let kgdb_connect print the rest.
+ */
+ printf("%s: ", sc->sc_dev.dv_xname);
+ kgdb_connect(1);
+ } else
+ printf("%s: kgdb enabled\n",
+ sc->sc_dev.dv_xname);
+ }
+ }
+#endif
+
+ if (sc->sc_dev.dv_unit == comconsole) {
+ /*
+ * Need to reset baud rate, etc. of next print so reset
+ * comconsinit. Also make sure console is always "hardwired".
+ */
+ comconsinit = 0;
+ SET(sc->sc_hwflags, COM_HW_CONSOLE);
+ SET(sc->sc_swflags, COM_SW_SOFTCAR);
+ }
+}
+
+int
+comopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ int unit = COMUNIT(dev);
+ struct com_softc *sc;
+ int iobase;
+ struct tty *tp;
+ int s;
+ int error = 0;
+
+ if (unit >= com_cd.cd_ndevs)
+ return ENXIO;
+ sc = com_cd.cd_devs[unit];
+ if (!sc)
+ return ENXIO;
+
+ if (!sc->sc_tty)
+ tp = sc->sc_tty = ttymalloc();
+ else
+ tp = sc->sc_tty;
+
+ tp->t_oproc = comstart;
+ tp->t_param = comparam;
+ tp->t_dev = dev;
+ if (!ISSET(tp->t_state, TS_ISOPEN)) {
+ SET(tp->t_state, TS_WOPEN);
+ ttychars(tp);
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG;
+ if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
+ SET(tp->t_cflag, CLOCAL);
+ if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
+ SET(tp->t_cflag, CRTSCTS);
+ if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
+ SET(tp->t_cflag, MDMBUF);
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = comdefaultrate;
+
+ s = spltty();
+
+ comparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+
+ if (comsopen++ == 0)
+ timeout(compoll, NULL, 1);
+
+ sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
+ sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
+ sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
+
+ iobase = sc->sc_iobase;
+ /* Set the FIFO threshold based on the receive speed. */
+ if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
+ outb(iobase + com_fifo,
+ FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
+ (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+ /* flush any pending I/O */
+ while (ISSET(inb(iobase + com_lsr), LSR_RXRDY))
+ (void) inb(iobase + com_data);
+ /* you turn me on, baby */
+ sc->sc_mcr = MCR_DTR | MCR_RTS;
+ if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
+ SET(sc->sc_mcr, MCR_IENABLE);
+ outb(iobase + com_mcr, sc->sc_mcr);
+ outb(iobase + com_ier,
+ IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC);
+
+ sc->sc_msr = inb(iobase + com_msr);
+ if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) ||
+ ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
+ SET(tp->t_state, TS_CARR_ON);
+ else
+ CLR(tp->t_state, TS_CARR_ON);
+ } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
+ return EBUSY;
+ else
+ s = spltty();
+
+ /* wait for carrier if necessary */
+ if (!ISSET(flag, O_NONBLOCK))
+ while (!ISSET(tp->t_cflag, CLOCAL) &&
+ !ISSET(tp->t_state, TS_CARR_ON)) {
+ SET(tp->t_state, TS_WOPEN);
+ error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
+ ttopen, 0);
+ if (error) {
+ /* XXX should turn off chip if we're the
+ only waiter */
+ splx(s);
+ return error;
+ }
+ }
+ splx(s);
+
+ return (*linesw[tp->t_line].l_open)(dev, tp);
+}
+
+int
+comclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ int unit = COMUNIT(dev);
+ struct com_softc *sc = com_cd.cd_devs[unit];
+ struct tty *tp = sc->sc_tty;
+ int iobase = sc->sc_iobase;
+ int s;
+
+ /* XXX This is for cons.c. */
+ if (!ISSET(tp->t_state, TS_ISOPEN))
+ return 0;
+
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ s = spltty();
+ CLR(sc->sc_lcr, LCR_SBREAK);
+ outb(iobase + com_lcr, sc->sc_lcr);
+ outb(iobase + com_ier, 0);
+ if (ISSET(tp->t_cflag, HUPCL) &&
+ !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
+ /* XXX perhaps only clear DTR */
+ outb(iobase + com_mcr, 0);
+ }
+ CLR(tp->t_state, TS_BUSY | TS_FLUSH);
+ if (--comsopen == 0)
+ untimeout(compoll, NULL);
+ splx(s);
+ ttyclose(tp);
+#ifdef notyet /* XXXX */
+ if (unit != comconsole) {
+ ttyfree(tp);
+ sc->sc_tty = 0;
+ }
+#endif
+ return 0;
+}
+
+int
+comread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
+ struct tty *tp = sc->sc_tty;
+
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+comwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
+ struct tty *tp = sc->sc_tty;
+
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+struct tty *
+comtty(dev)
+ dev_t dev;
+{
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
+ struct tty *tp = sc->sc_tty;
+
+ return (tp);
+}
+
+static u_char
+tiocm_xxx2mcr(data)
+ int data;
+{
+ u_char m = 0;
+
+ if (ISSET(data, TIOCM_DTR))
+ SET(m, MCR_DTR);
+ if (ISSET(data, TIOCM_RTS))
+ SET(m, MCR_RTS);
+ return m;
+}
+
+int
+comioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ int unit = COMUNIT(dev);
+ struct com_softc *sc = com_cd.cd_devs[unit];
+ struct tty *tp = sc->sc_tty;
+ int iobase = sc->sc_iobase;
+ int error;
+
+ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return error;
+ error = ttioctl(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return error;
+
+ switch (cmd) {
+ case TIOCSBRK:
+ SET(sc->sc_lcr, LCR_SBREAK);
+ outb(iobase + com_lcr, sc->sc_lcr);
+ break;
+ case TIOCCBRK:
+ CLR(sc->sc_lcr, LCR_SBREAK);
+ outb(iobase + com_lcr, sc->sc_lcr);
+ break;
+ case TIOCSDTR:
+ SET(sc->sc_mcr, sc->sc_dtr);
+ outb(iobase + com_mcr, sc->sc_mcr);
+ break;
+ case TIOCCDTR:
+ CLR(sc->sc_mcr, sc->sc_dtr);
+ outb(iobase + com_mcr, sc->sc_mcr);
+ break;
+ case TIOCMSET:
+ CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
+ case TIOCMBIS:
+ SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
+ outb(iobase + com_mcr, sc->sc_mcr);
+ break;
+ case TIOCMBIC:
+ CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
+ outb(iobase + com_mcr, sc->sc_mcr);
+ break;
+ case TIOCMGET: {
+ u_char m;
+ int bits = 0;
+
+ m = sc->sc_mcr;
+ if (ISSET(m, MCR_DTR))
+ SET(bits, TIOCM_DTR);
+ if (ISSET(m, MCR_RTS))
+ SET(bits, TIOCM_RTS);
+ m = sc->sc_msr;
+ if (ISSET(m, MSR_DCD))
+ SET(bits, TIOCM_CD);
+ if (ISSET(m, MSR_CTS))
+ SET(bits, TIOCM_CTS);
+ if (ISSET(m, MSR_DSR))
+ SET(bits, TIOCM_DSR);
+ if (ISSET(m, MSR_RI | MSR_TERI))
+ SET(bits, TIOCM_RI);
+ if (inb(iobase + com_ier))
+ SET(bits, TIOCM_LE);
+ *(int *)data = bits;
+ break;
+ }
+ case TIOCGFLAGS: {
+ int driverbits, userbits = 0;
+
+ driverbits = sc->sc_swflags;
+ if (ISSET(driverbits, COM_SW_SOFTCAR))
+ SET(userbits, TIOCFLAG_SOFTCAR);
+ if (ISSET(driverbits, COM_SW_CLOCAL))
+ SET(userbits, TIOCFLAG_CLOCAL);
+ if (ISSET(driverbits, COM_SW_CRTSCTS))
+ SET(userbits, TIOCFLAG_CRTSCTS);
+ if (ISSET(driverbits, COM_SW_MDMBUF))
+ SET(userbits, TIOCFLAG_MDMBUF);
+
+ *(int *)data = userbits;
+ break;
+ }
+ case TIOCSFLAGS: {
+ int userbits, driverbits = 0;
+
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error != 0)
+ return(EPERM);
+
+ userbits = *(int *)data;
+ if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
+ ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+ SET(driverbits, COM_SW_SOFTCAR);
+ if (ISSET(userbits, TIOCFLAG_CLOCAL))
+ SET(driverbits, COM_SW_CLOCAL);
+ if (ISSET(userbits, TIOCFLAG_CRTSCTS))
+ SET(driverbits, COM_SW_CRTSCTS);
+ if (ISSET(userbits, TIOCFLAG_MDMBUF))
+ SET(driverbits, COM_SW_MDMBUF);
+
+ sc->sc_swflags = driverbits;
+ break;
+ }
+ default:
+ return ENOTTY;
+ }
+
+ return 0;
+}
+
+int
+comparam(tp, t)
+ struct tty *tp;
+ struct termios *t;
+{
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
+ int iobase = sc->sc_iobase;
+ int ospeed = comspeed(t->c_ospeed);
+ u_char lcr;
+ tcflag_t oldcflag;
+ int s;
+
+ /* check requested parameters */
+ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
+ return EINVAL;
+
+ lcr = sc->sc_lcr & LCR_SBREAK;
+
+ switch (ISSET(t->c_cflag, CSIZE)) {
+ case CS5:
+ SET(lcr, LCR_5BITS);
+ break;
+ case CS6:
+ SET(lcr, LCR_6BITS);
+ break;
+ case CS7:
+ SET(lcr, LCR_7BITS);
+ break;
+ case CS8:
+ SET(lcr, LCR_8BITS);
+ break;
+ }
+ if (ISSET(t->c_cflag, PARENB)) {
+ SET(lcr, LCR_PENAB);
+ if (!ISSET(t->c_cflag, PARODD))
+ SET(lcr, LCR_PEVEN);
+ }
+ if (ISSET(t->c_cflag, CSTOPB))
+ SET(lcr, LCR_STOPB);
+
+ sc->sc_lcr = lcr;
+
+ s = spltty();
+
+ if (ospeed == 0) {
+ CLR(sc->sc_mcr, MCR_DTR);
+ outb(iobase + com_mcr, sc->sc_mcr);
+ }
+
+ /*
+ * Set the FIFO threshold based on the receive speed, if we are
+ * changing it.
+ */
+ if (tp->t_ispeed != t->c_ispeed) {
+ if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
+ outb(iobase + com_fifo,
+ FIFO_ENABLE |
+ (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+ }
+
+ if (ospeed != 0) {
+ outb(iobase + com_lcr, lcr | LCR_DLAB);
+ outb(iobase + com_dlbl, ospeed);
+ outb(iobase + com_dlbh, ospeed >> 8);
+ outb(iobase + com_lcr, lcr);
+ SET(sc->sc_mcr, MCR_DTR);
+ outb(iobase + com_mcr, sc->sc_mcr);
+ } else
+ outb(iobase + com_lcr, lcr);
+
+ /* When not using CRTSCTS, RTS follows DTR. */
+ if (!ISSET(t->c_cflag, CRTSCTS)) {
+ if (ISSET(sc->sc_mcr, MCR_DTR)) {
+ if (!ISSET(sc->sc_mcr, MCR_RTS)) {
+ SET(sc->sc_mcr, MCR_RTS);
+ outb(iobase + com_mcr, sc->sc_mcr);
+ }
+ } else {
+ if (ISSET(sc->sc_mcr, MCR_RTS)) {
+ CLR(sc->sc_mcr, MCR_RTS);
+ outb(iobase + com_mcr, sc->sc_mcr);
+ }
+ }
+ sc->sc_dtr = MCR_DTR | MCR_RTS;
+ } else
+ sc->sc_dtr = MCR_DTR;
+
+ /* and copy to tty */
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ oldcflag = tp->t_cflag;
+ tp->t_cflag = t->c_cflag;
+
+ /*
+ * If DCD is off and MDMBUF is changed, ask the tty layer if we should
+ * stop the device.
+ */
+ if (!ISSET(sc->sc_msr, MSR_DCD) &&
+ !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
+ ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
+ (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
+ CLR(sc->sc_mcr, sc->sc_dtr);
+ outb(iobase + com_mcr, sc->sc_mcr);
+ }
+
+ splx(s);
+ return 0;
+}
+
+void
+comstart(tp)
+ struct tty *tp;
+{
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
+ int iobase = sc->sc_iobase;
+ int s;
+
+ s = spltty();
+ if (ISSET(tp->t_state, TS_TTSTOP | TS_BUSY))
+ goto out;
+ if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
+ goto out;
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (ISSET(tp->t_state, TS_ASLEEP)) {
+ CLR(tp->t_state, TS_ASLEEP);
+ wakeup(&tp->t_outq);
+ }
+ if (tp->t_outq.c_cc == 0)
+ goto out;
+ selwakeup(&tp->t_wsel);
+ }
+ SET(tp->t_state, TS_BUSY);
+ if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
+ u_char buffer[16], *cp = buffer;
+ int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
+ do {
+ outb(iobase + com_data, *cp++);
+ } while (--n);
+ } else
+ outb(iobase + com_data, getc(&tp->t_outq));
+out:
+ splx(s);
+}
+
+/*
+ * Stop output on a line.
+ */
+void
+comstop(tp, flag)
+ struct tty *tp;
+{
+ int s;
+
+ s = spltty();
+ if (ISSET(tp->t_state, TS_BUSY))
+ if (!ISSET(tp->t_state, TS_TTSTOP))
+ SET(tp->t_state, TS_FLUSH);
+ splx(s);
+}
+
+void
+comdiag(arg)
+ void *arg;
+{
+ struct com_softc *sc = arg;
+ int overflows, floods;
+ int s;
+
+ s = spltty();
+ sc->sc_errors = 0;
+ overflows = sc->sc_overflows;
+ sc->sc_overflows = 0;
+ floods = sc->sc_floods;
+ sc->sc_floods = 0;
+ splx(s);
+
+ log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
+ sc->sc_dev.dv_xname,
+ overflows, overflows == 1 ? "" : "s",
+ floods, floods == 1 ? "" : "s");
+}
+
+void
+compoll(arg)
+ void *arg;
+{
+ int unit;
+ struct com_softc *sc;
+ struct tty *tp;
+ register u_char *ibufp;
+ u_char *ibufend;
+ register int c;
+ int s;
+ static int lsrmap[8] = {
+ 0, TTY_PE,
+ TTY_FE, TTY_PE|TTY_FE,
+ TTY_FE, TTY_PE|TTY_FE,
+ TTY_FE, TTY_PE|TTY_FE
+ };
+
+ s = spltty();
+ if (comevents == 0) {
+ splx(s);
+ goto out;
+ }
+ comevents = 0;
+ splx(s);
+
+ for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
+ sc = com_cd.cd_devs[unit];
+ if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf)
+ continue;
+
+ tp = sc->sc_tty;
+
+ s = spltty();
+
+ ibufp = sc->sc_ibuf;
+ ibufend = sc->sc_ibufp;
+
+ if (ibufp == ibufend) {
+ splx(s);
+ continue;
+ }
+
+ sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
+ sc->sc_ibufs[1] : sc->sc_ibufs[0];
+ sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
+ sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
+
+ if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) {
+ splx(s);
+ continue;
+ }
+
+ if (ISSET(tp->t_cflag, CRTSCTS) &&
+ !ISSET(sc->sc_mcr, MCR_RTS)) {
+ /* XXX */
+ SET(sc->sc_mcr, MCR_RTS);
+ outb(sc->sc_iobase + com_mcr, sc->sc_mcr);
+ }
+
+ splx(s);
+
+ while (ibufp < ibufend) {
+ c = *ibufp++;
+ if (*ibufp & LSR_OE) {
+ sc->sc_overflows++;
+ if (sc->sc_errors++ == 0)
+ timeout(comdiag, sc, 60 * hz);
+ }
+ /* This is ugly, but fast. */
+ c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
+ (*linesw[tp->t_line].l_rint)(c, tp);
+ }
+ }
+
+out:
+ timeout(compoll, NULL, 1);
+}
+
+int
+comintr(arg)
+ void *arg;
+{
+ struct com_softc *sc = arg;
+ int iobase = sc->sc_iobase;
+ struct tty *tp;
+ u_char lsr, data, msr, delta;
+
+ if (ISSET(inb(iobase + com_iir), IIR_NOPEND))
+ return (0);
+
+ tp = sc->sc_tty;
+
+ for (;;) {
+ lsr = inb(iobase + com_lsr);
+
+ if (ISSET(lsr, LSR_RCV_MASK)) {
+ register u_char *p = sc->sc_ibufp;
+
+ comevents = 1;
+ do {
+ data = ISSET(lsr, LSR_RXRDY) ?
+ inb(iobase + com_data) : 0;
+ if (ISSET(lsr, LSR_BI)) {
+#ifdef DDB
+ if (sc->sc_dev.dv_unit == comconsole) {
+ Debugger();
+ goto next;
+ }
+#endif
+ data = '\0';
+ }
+ if (p >= sc->sc_ibufend) {
+ sc->sc_floods++;
+ if (sc->sc_errors++ == 0)
+ timeout(comdiag, sc, 60 * hz);
+ } else {
+ *p++ = data;
+ *p++ = lsr;
+ if (p == sc->sc_ibufhigh &&
+ ISSET(tp->t_cflag, CRTSCTS)) {
+ /* XXX */
+ CLR(sc->sc_mcr, MCR_RTS);
+ outb(iobase + com_mcr,
+ sc->sc_mcr);
+ }
+ }
+ next:
+ lsr = inb(iobase + com_lsr);
+ } while (ISSET(lsr, LSR_RCV_MASK));
+
+ sc->sc_ibufp = p;
+ }
+#if 0
+ else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
+ printf("weird lsr %02x\n", lsr);
+#endif
+
+ msr = inb(iobase + com_msr);
+
+ if (msr != sc->sc_msr) {
+ delta = msr ^ sc->sc_msr;
+ sc->sc_msr = msr;
+ if (ISSET(delta, MSR_DCD) &&
+ !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
+ (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
+ CLR(sc->sc_mcr, sc->sc_dtr);
+ outb(iobase + com_mcr, sc->sc_mcr);
+ }
+ if (ISSET(delta & msr, MSR_CTS) &&
+ ISSET(tp->t_cflag, CRTSCTS)) {
+ /* the line is up and we want to do rts/cts flow control */
+ (*linesw[tp->t_line].l_start)(tp);
+ }
+ }
+
+ if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
+ CLR(tp->t_state, TS_BUSY);
+ if (ISSET(tp->t_state, TS_FLUSH))
+ CLR(tp->t_state, TS_FLUSH);
+ else
+ (*linesw[tp->t_line].l_start)(tp);
+ }
+
+ if (ISSET(inb(iobase + com_iir), IIR_NOPEND))
+ return (1);
+ }
+}
+
+/*
+ * Following are all routines needed for COM to act as console
+ */
+#include <dev/cons.h>
+
+void
+comcnprobe(cp)
+ struct consdev *cp;
+{
+
+ if (!comprobe1(CONADDR)) {
+ cp->cn_pri = CN_DEAD;
+ return;
+ }
+
+ /* locate the major number */
+ for (commajor = 0; commajor < nchrdev; commajor++)
+ if (cdevsw[commajor].d_open == comopen)
+ break;
+
+ /* initialize required fields */
+ cp->cn_dev = makedev(commajor, CONUNIT);
+#ifdef COMCONSOLE
+ cp->cn_pri = CN_REMOTE; /* Force a serial port console */
+#else
+ cp->cn_pri = CN_NORMAL;
+#endif
+}
+
+void
+comcninit(cp)
+ struct consdev *cp;
+{
+
+ cominit(CONUNIT, comdefaultrate);
+ comconsole = CONUNIT;
+ comconsinit = 0;
+}
+
+cominit(unit, rate)
+ int unit, rate;
+{
+ int s = splhigh();
+ int iobase = CONADDR;
+ u_char stat;
+
+ outb(iobase + com_lcr, LCR_DLAB);
+ rate = comspeed(comdefaultrate);
+ outb(iobase + com_dlbl, rate);
+ outb(iobase + com_dlbh, rate >> 8);
+ outb(iobase + com_lcr, LCR_8BITS);
+ outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY);
+ outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
+ stat = inb(iobase + com_iir);
+ splx(s);
+}
+
+comcngetc(dev)
+ dev_t dev;
+{
+ int s = splhigh();
+ int iobase = CONADDR;
+ u_char stat, c;
+
+ while (!ISSET(stat = inb(iobase + com_lsr), LSR_RXRDY))
+ ;
+ c = inb(iobase + com_data);
+ stat = inb(iobase + com_iir);
+ splx(s);
+ return c;
+}
+
+/*
+ * Console kernel output character routine.
+ */
+void
+comcnputc(dev, c)
+ dev_t dev;
+ int c;
+{
+ int s = splhigh();
+ int iobase = CONADDR;
+ u_char stat;
+ register int timo;
+
+#ifdef KGDB
+ if (dev != kgdb_dev)
+#endif
+ if (comconsinit == 0) {
+ (void) cominit(COMUNIT(dev), comdefaultrate);
+ comconsinit = 1;
+ }
+ /* wait for any pending transmission to finish */
+ timo = 50000;
+ while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo)
+ ;
+ outb(iobase + com_data, c);
+ /* wait for this transmission to complete */
+ timo = 1500000;
+ while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo)
+ ;
+ /* clear any interrupts generated by this transmission */
+ stat = inb(iobase + com_iir);
+ splx(s);
+}
+
+void
+comcnpollc(dev, on)
+ dev_t dev;
+ int on;
+{
+
+}
--- /dev/null
+/* $NetBSD: comreg.h,v 1.1 1996/01/31 23:24:29 mark Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)comreg.h 7.2 (Berkeley) 5/9/91
+ */
+
+/*
+ * NS16550 UART registers
+ */
+
+#define com_data 0 /* data register (R/W) */
+#define com_dlbl 0 /* divisor latch low (W) */
+#define com_dlbh 4 /* divisor latch high (W) */
+#define com_ier 4 /* interrupt enable (W) */
+#define com_iir 8 /* interrupt identification (R) */
+#define com_fifo 8 /* FIFO control (W) */
+#define com_lctl 12 /* line control register (R/W) */
+#define com_cfcr 12 /* line control register (R/W) */
+#define com_mcr 16 /* modem control register (R/W) */
+#define com_lsr 20 /* line status register (R/W) */
+#define com_msr 24 /* modem status register (R/W) */
+#define com_scratch 28 /* scratch register (R/W) */
+
+#define COM_FREQ 1843200 /* 16-bit baud rate divisor */
+#define COM_TOLERANCE 30 /* baud rate tolerance, in 0.1% units */
+
+/* interrupt enable register */
+#define IER_ERXRDY 0x1
+#define IER_ETXRDY 0x2
+#define IER_ERLS 0x4
+#define IER_EMSC 0x8
+
+/* interrupt identification register */
+#define IIR_IMASK 0xf
+#define IIR_RXTOUT 0xc
+#define IIR_RLS 0x6
+#define IIR_RXRDY 0x4
+#define IIR_TXRDY 0x2
+#define IIR_NOPEND 0x1
+#define IIR_MLSC 0x0
+#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
+
+/* fifo control register */
+#define FIFO_ENABLE 0x01
+#define FIFO_RCV_RST 0x02
+#define FIFO_XMT_RST 0x04
+#define FIFO_DMA_MODE 0x08
+#define FIFO_TRIGGER_1 0x00
+#define FIFO_TRIGGER_4 0x40
+#define FIFO_TRIGGER_8 0x80
+#define FIFO_TRIGGER_14 0xc0
+
+/* line control register */
+#define LCR_DLAB 0x80
+#define LCR_SBREAK 0x40
+#define LCR_PZERO 0x30
+#define LCR_PONE 0x20
+#define LCR_PEVEN 0x10
+#define LCR_PODD 0x00
+#define LCR_PENAB 0x08
+#define LCR_STOPB 0x04
+#define LCR_8BITS 0x03
+#define LCR_7BITS 0x02
+#define LCR_6BITS 0x01
+#define LCR_5BITS 0x00
+
+/* modem control register */
+#define MCR_LOOPBACK 0x10
+#define MCR_IENABLE 0x08
+#define MCR_DRS 0x04
+#define MCR_RTS 0x02
+#define MCR_DTR 0x01
+
+/* line status register */
+#define LSR_RCV_FIFO 0x80
+#define LSR_TSRE 0x40
+#define LSR_TXRDY 0x20
+#define LSR_BI 0x10
+#define LSR_FE 0x08
+#define LSR_PE 0x04
+#define LSR_OE 0x02
+#define LSR_RXRDY 0x01
+#define LSR_RCV_MASK 0x1f
+
+/* modem status register */
+#define MSR_DCD 0x80
+#define MSR_RI 0x40
+#define MSR_DSR 0x20
+#define MSR_CTS 0x10
+#define MSR_DDCD 0x08
+#define MSR_TERI 0x04
+#define MSR_DDSR 0x02
+#define MSR_DCTS 0x01
+
+#define COM_NPORTS 32
+
+/*
+ * WARNING: Serial console is assumed to be at COM1 address
+ * and CONUNIT must be 0.
+ */
+#define CONADDR (SERIAL0_CONTROLLER_BASE)
+#define CONUNIT (0)
--- /dev/null
+/* $NetBSD: cpu.c,v 1.4 1996/03/18 20:50:00 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * cpu.c
+ *
+ * Probing and configuration for the master cpu
+ *
+ * Created : 10/10/95
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <vm/vm_kern.h>
+#include <machine/io.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#include <machine/undefined.h>
+#include <machine/cpus.h>
+
+#include "cpu.h"
+#if NCPU < 1
+#error Need at least 1 CPU configured
+#endif
+
+/* Array of cpu structures, one per possible cpu */
+
+cpu_t cpus[MAX_CPUS];
+
+char cpu_model[48];
+extern int cpu_ctrl; /* Control bits for boot CPU */
+volatile int undefined_test; /* Used for FPA test */
+
+extern char *boot_args;
+
+/* Declare prototypes */
+
+/* Prototypes */
+
+void identify_master_cpu __P((int /*cpu_number*/));
+void identify_arm_cpu __P((int /*cpu_number*/));
+void identify_arm_fpu __P((int /*cpu_number*/));
+char *strstr __P((char */*s1*/, char */*s2*/));
+
+
+/*
+ * int cpumatch(struct device *parent, void *match, void *aux)
+ *
+ * Probe for the main cpu. Currently all this does is return 1 to
+ * indicate that the cpu was found.
+ */
+
+int
+cpumatch(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ struct device *dev = match;
+
+ if (dev->dv_unit == 0)
+ return(1);
+ return(0);
+}
+
+
+/*
+ * void cpusattach(struct device *parent, struct device *dev, void *aux)
+ *
+ * Attach the main cpu
+ */
+
+void
+cpuattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ int loop;
+
+ for (loop = 0; loop < MAX_CPUS; ++loop)
+ bzero(&cpus[loop], sizeof(cpu_t));
+
+ identify_master_cpu(CPU_MASTER);
+}
+
+struct cfattach cpu_ca = {
+ sizeof(struct cpu_softc), cpumatch, cpuattach
+};
+
+struct cfdriver cpu_cd = {
+ NULL, "cpu", DV_DULL, 1
+};
+
+
+/*
+ * Used to test for an FPA. The following function is installed as a coproc1 handler
+ * on the undefined instruction vector and then we issue a FPA instruction.
+ * If undefined_test is non zero then the FPA did not handle the instruction so
+ * must be absent.
+ */
+
+int
+fpa_test(address, instruction, frame)
+ u_int address;
+ u_int instruction;
+ trapframe_t *frame;
+{
+ ++undefined_test;
+ return(0);
+}
+
+/*
+ * If an FPA was found then this function is installed as the coproc1 handler
+ * on the undefined instruction vector. Currently we don't support FPA's
+ * so this just triggers an exception.
+ */
+
+int
+fpa_handler(address, instruction, frame)
+ u_int address;
+ u_int instruction;
+ trapframe_t *frame;
+{
+ u_int fpsr;
+
+ __asm __volatile("stmfd sp!, {r0}; .word 0xee300110; mov %0, r0; ldmfd sp!, {r0}" : "=r" (fpsr));
+
+ printf("FPA exception: fpsr = %08x\n", fpsr);
+
+ return(1);
+}
+
+
+/*
+ * Identify the master (boot) CPU
+ * This also probes for an FPU and will install an FPE if necessary
+ */
+
+void
+identify_master_cpu(cpu_number)
+ int cpu_number;
+{
+ u_int fpsr;
+
+ cpus[cpu_number].cpu_class = CPU_CLASS_ARM;
+ cpus[cpu_number].cpu_host = CPU_HOST_MAINBUS;
+ cpus[cpu_number].cpu_flags = CPU_FLAG_PRESENT;
+ cpus[cpu_number].cpu_ctrl = cpu_ctrl;
+
+/* Get the cpu ID from coprocessor 15 */
+
+ cpus[cpu_number].cpu_id = cpu_id();
+
+ identify_arm_cpu(cpu_number);
+ strcpy(cpu_model, cpus[cpu_number].cpu_model);
+
+/*
+ * Ok now we test for an FPA
+ * At this point no floating point emulator has been installed.
+ * This means any FP instruction will cause undefined exception.
+ * We install a temporay coproc 1 handler which will modify undefined_test
+ * if it is called.
+ * We then try to read the FP status register. If undefined_test has been
+ * decremented then the instruction was not handled by an FPA so we know
+ * the FPA is missing. If undefined_test is still 1 then we know the
+ * instruction was handled by an FPA.
+ * We then remove our test handler and look at the
+ * FP status register for identification.
+ */
+
+ install_coproc_handler(FP_COPROC, fpa_test);
+
+ undefined_test = 0;
+
+ __asm __volatile("stmfd sp!, {r0}; .word 0xee300110; mov %0, r0; ldmfd sp!, {r0}" : "=r" (fpsr));
+
+ if (undefined_test == 0) {
+ cpus[cpu_number].fpu_type = (fpsr >> 24);
+ switch (fpsr >> 24) {
+ case 0x81 :
+ cpus[cpu_number].fpu_class = FPU_CLASS_FPA;
+
+#if 0
+/* Experimental stuff used when playing with an ARM700+FPA11 */
+ printf("FPA11: FPSR=%08x\n", fpsr);
+ fpsr=0x00070400;
+ __asm __volatile("wfs %0" : "=r" (fpsr));
+ __asm __volatile("rfc %0" : "=r" (fpsr));
+ printf("FPA11: FPCR=%08x", fpsr);
+ __asm __volatile("stmfd sp!, {r0}; mov r0, #0x00000e00 ; wfc r0; ldmfd sp!, {r0}");
+ __asm __volatile("rfc %0" : "=r" (fpsr));
+ printf("FPA11: FPCR=%08x", fpsr);
+#endif
+ break;
+
+ default :
+ cpus[cpu_number].fpu_class = FPU_CLASS_FPU;
+ break;
+ }
+ cpus[cpu_number].fpu_flags = 0;
+ install_coproc_handler(FP_COPROC, fpa_handler);
+ } else {
+ cpus[cpu_number].fpu_class = FPU_CLASS_NONE;
+ cpus[cpu_number].fpu_flags = 0;
+
+/* Ok if ARMFPE is defined and the boot options request the ARM FPE then it will
+ * be installed as the FPE. If the installation fails the existing FPE is used as
+ * a fall back.
+ * If either ARMFPE is not defined or the boot args did not request it the old FPE
+ * is installed.
+ * This is just while I work on integrating the new FPE.
+ * It means the new FPE gets installed if compiled int (ARMFPE defined)
+ * and also gives me a on/off option when I boot in case the new FPE is
+ * causing panics.
+ * In all cases it falls back on the existing FPE is the ARMFPE was not successfully
+ * installed.
+ */
+
+#ifdef ARMFPE
+ if (boot_args) {
+ char *ptr;
+
+ ptr = strstr(boot_args, "noarmfpe");
+ if (!ptr) {
+ if (initialise_arm_fpe(&cpus[cpu_number]) != 0) {
+ identify_arm_fpu(cpu_number);
+#ifdef FPE
+ initialise_fpe(&cpus[cpu_number]);
+#endif
+ }
+#ifdef FPE
+ } else
+ initialise_fpe(&cpus[cpu_number]);
+
+ } else
+ initialise_fpe(&cpus[cpu_number]);
+#else
+ }
+ }
+#endif
+
+#else
+#ifdef FPE
+ initialise_fpe(&cpus[cpu_number]);
+#else
+#error No FPE built in
+#endif
+#endif
+ }
+
+ identify_arm_fpu(cpu_number);
+}
+
+
+
+/*
+ * Report the type of the specifed arm processor. This uses the generic and arm specific
+ * information in the cpu structure to identify the processor. The remaining fields
+ * in the cpu structure are filled in appropriately.
+ */
+
+void
+identify_arm_cpu(cpu_number)
+ int cpu_number;
+{
+ cpu_t *cpu;
+ u_int cpuid;
+
+ cpu = &cpus[cpu_number];
+ if (cpu->cpu_host == CPU_HOST_NONE || cpu->cpu_class == CPU_CLASS_NONE) {
+ printf("No installed processor\n");
+ return;
+ }
+ if (cpu->cpu_class != CPU_CLASS_ARM) {
+ printf("identify_arm_cpu: Can only identify ARM CPU's\n");
+ return;
+ }
+ cpuid = cpu->cpu_id;
+
+ if (cpuid == 0) {
+ printf("Processor failed probe - no CPU ID\n");
+ return;
+ }
+
+ if ((cpuid & CPU_ID_DESIGNER_MASK) != CPU_ID_ARM_LTD)
+ printf("Unrecognised designer ID = %08x\n", cpuid);
+
+ switch (cpuid & CPU_ID_CPU_MASK) {
+ case ID_ARM610:
+ cpu->cpu_type = cpuid & CPU_ID_CPU_MASK;
+ break;
+
+ case ID_ARM710 :
+ case ID_ARM700 :
+ cpu->cpu_type = (cpuid & CPU_ID_CPU_MASK) >> 4;
+ break;
+
+ default :
+ printf("Unrecognised processor ID = %08x\n", cpuid);
+ cpu->cpu_type = cpuid & CPU_ID_CPU_MASK;
+ break;
+ }
+
+ sprintf(cpu->cpu_model, "ARM%x rev %d", cpu->cpu_type, cpuid & CPU_ID_REVISION_MASK);
+
+ if ((cpu->cpu_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
+ strcat(cpu->cpu_model, " IDC disabled");
+ else
+ strcat(cpu->cpu_model, " IDC enabled");
+
+ if ((cpu->cpu_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
+ strcat(cpu->cpu_model, " WB disabled");
+ else
+ strcat(cpu->cpu_model, " WB enabled");
+
+ if (cpu->cpu_ctrl & CPU_CONTROL_LABT_ENABLE)
+ strcat(cpu->cpu_model, " LABT");
+ else
+ strcat(cpu->cpu_model, " EABT");
+
+/* Print the info */
+
+ printf(": %s\n", cpu->cpu_model);
+}
+
+
+/*
+ * Report the type of the specifed arm fpu. This uses the generic and arm specific
+ * information in the cpu structure to identify the fpu. The remaining fields
+ * in the cpu structure are filled in appropriately.
+ */
+
+void
+identify_arm_fpu(cpu_number)
+ int cpu_number;
+{
+ cpu_t *cpu;
+
+ cpu = &cpus[cpu_number];
+ if (cpu->cpu_host == CPU_HOST_NONE || cpu->cpu_class == CPU_CLASS_NONE) {
+ printf("No installed processor\n");
+ return;
+ }
+
+ if (cpu->cpu_class != CPU_CLASS_ARM) {
+ printf("identify_arm_cpu: Can only identify ARM FPU's\n");
+ return;
+ }
+
+/* Now for the FP info */
+
+ switch (cpu->fpu_class) {
+ case FPU_CLASS_NONE :
+ strcpy(cpu->fpu_model, "None");
+ break;
+ case FPU_CLASS_FPE :
+ printf("fpe%d at cpu%d: %s\n", cpu_number, cpu_number, cpu->fpu_model);
+ printf("fpe%d: no hardware found\n", cpu_number);
+ break;
+ case FPU_CLASS_FPA :
+ printf("fpe%d at cpu%d: %s\n", cpu_number, cpu_number, cpu->fpu_model);
+ if (cpu->fpu_type == FPU_TYPE_FPA11) {
+ strcpy(cpu->fpu_model, "FPA11");
+ printf("fpe%d: fpa11 found\n", cpu_number);
+ } else {
+ strcpy(cpu->fpu_model, "FPA");
+ printf("fpe%d: fpa10 found\n", cpu_number);
+ }
+ if ((cpu->fpu_flags & 4) == 0)
+ strcat(cpu->fpu_model, "");
+ else
+ strcat(cpu->fpu_model, " clk/2");
+ break;
+ case FPU_CLASS_FPU :
+ sprintf(cpu->fpu_model, "Unknown FPU (ID=%02x)\n", cpu->fpu_type);
+ printf("fpu%d at cpu%d: %s\n", cpu_number, cpu_number, cpu->fpu_model);
+ break;
+ }
+}
+
+
+int
+cpuopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct cpu_softc *sc;
+ int unit;
+ int s;
+
+ unit = minor(dev);
+ if (unit >= cpu_cd.cd_ndevs)
+ return(ENXIO);
+
+ sc = cpu_cd.cd_devs[unit];
+ if (!sc) return(ENXIO);
+
+ s = splhigh();
+ if (sc->sc_open) {
+ (void)splx(s);
+ return(EBUSY);
+ }
+
+ ++sc->sc_open;
+ (void)splx(s);
+
+ return(0);
+}
+
+
+int
+cpuclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct cpu_softc *sc;
+ int unit;
+ int s;
+
+ unit = minor(dev);
+ sc = cpu_cd.cd_devs[unit];
+
+ if (sc->sc_open == 0) return(ENXIO);
+
+ s = splhigh();
+ --sc->sc_open;
+ (void)splx(s);
+
+ return(0);
+}
+
+
+int
+cpuioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct cpu_softc *sc;
+ int unit;
+
+ unit = minor(dev);
+ sc = cpu_cd.cd_devs[unit];
+
+ switch (cmd) {
+ default:
+ return(ENXIO);
+ break;
+ }
+
+ return(0);
+}
+
+/* End of cpu.c */
--- /dev/null
+/* $NetBSD: fd.c,v 1.5 1996/03/28 21:52:41 mark Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994, 1995 Charles Hannum.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Don Ahn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fd.c 7.4 (Berkeley) 5/25/91
+ */
+
+/* The new config stuff do no use to use and need to be pulled out */
+
+#undef NEWCONFIG
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/dkstat.h>
+#include <sys/disk.h>
+#include <sys/buf.h>
+#include <sys/uio.h>
+#include <sys/syslog.h>
+#include <sys/queue.h>
+
+
+#include <machine/cpu.h>
+#include <machine/irqhandler.h>
+#include <machine/iomd.h>
+#include <machine/io.h>
+#include <machine/katelib.h>
+
+#include <arm32/mainbus/mainbus.h>
+#include <arm32/mainbus/fdreg.h>
+
+#define FDUNIT(dev) (minor(dev) / 8)
+#define FDTYPE(dev) (minor(dev) % 8)
+
+#define b_cylin b_resid
+
+enum fdc_state {
+ DEVIDLE = 0,
+ MOTORWAIT,
+ DOSEEK,
+ SEEKWAIT,
+ SEEKTIMEDOUT,
+ SEEKCOMPLETE,
+ DOIO,
+ IOCOMPLETE,
+ IOTIMEDOUT,
+ DORESET,
+ RESETCOMPLETE,
+ RESETTIMEDOUT,
+ DORECAL,
+ RECALWAIT,
+ RECALTIMEDOUT,
+ RECALCOMPLETE,
+};
+
+/* software state, per controller */
+struct fdc_softc {
+ struct device sc_dev; /* boilerplate */
+ irqhandler_t sc_ih;
+
+ int sc_iobase;
+ int sc_drq;
+
+ struct fd_softc *sc_fd[4]; /* pointers to children */
+ TAILQ_HEAD(drivehead, fd_softc) sc_drives;
+ enum fdc_state sc_state;
+ int sc_errors; /* number of retries so far */
+ u_char sc_status[7]; /* copy of registers */
+};
+
+/* controller driver configuration */
+int fdcprobe __P((struct device *, void *, void *));
+#ifdef NEWCONFIG
+void fdcforceintr __P((void *));
+#endif
+void fdcattach __P((struct device *, struct device *, void *));
+
+static fiqhandler_t fiqhandler;
+
+void floppy_read_fiq __P((void));
+void floppy_write_fiq __P((void));
+
+struct cfattach fdc_ca = {
+ sizeof(struct fdc_softc), fdcprobe, fdcattach
+};
+
+struct cfdriver fdc_cd = {
+ NULL, "fdc", DV_DULL
+};
+
+/*
+ * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
+ * we tell them apart.
+ */
+struct fd_type {
+ int sectrac; /* sectors per track */
+ int heads; /* number of heads */
+ int seccyl; /* sectors per cylinder */
+ int secsize; /* size code for sectors */
+ int datalen; /* data len when secsize = 0 */
+ int steprate; /* step rate and head unload time */
+ int gap1; /* gap len between sectors */
+ int gap2; /* formatting gap */
+ int tracks; /* total num of tracks */
+ int size; /* size of disk in sectors */
+ int step; /* steps per cylinder */
+ int rate; /* transfer speed code */
+ char *name;
+};
+
+/* The order of entries in the following table is important -- BEWARE! */
+struct fd_type fd_types[] = {
+ { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,"1.44MB" }, /* 1.44MB diskette */
+ { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, "1.2MB" }, /* 1.2 MB AT-diskettes */
+ { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, "360KB/AT" }, /* 360kB in 1.2MB drive */
+ { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, "360KB/PC" }, /* 360kB PC diskettes */
+ { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, "720KB" }, /* 3.5" 720kB diskette */
+ { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, "720KB/x" }, /* 720kB in 1.2MB drive */
+ { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS, "360KB/x" }, /* 360kB in 720kB drive */
+};
+
+/* software state, per disk (with up to 4 disks per ctlr) */
+struct fd_softc {
+ struct device sc_dev;
+ struct disk sc_dk;
+
+ struct fd_type *sc_deftype; /* default type descriptor */
+ struct fd_type *sc_type; /* current type descriptor */
+
+ daddr_t sc_blkno; /* starting block number */
+ int sc_bcount; /* byte count left */
+ int sc_skip; /* bytes already transferred */
+ int sc_nblks; /* number of blocks currently tranferring */
+ int sc_nbytes; /* number of bytes currently tranferring */
+
+ int sc_drive; /* physical unit number */
+ int sc_flags;
+#define FD_OPEN 0x01 /* it's open */
+#define FD_MOTOR 0x02 /* motor should be on */
+#define FD_MOTOR_WAIT 0x04 /* motor coming up */
+ int sc_cylin; /* where we think the head is */
+
+ void *sc_sdhook; /* saved shutdown hook for drive. */
+
+ TAILQ_ENTRY(fd_softc) sc_drivechain;
+ int sc_ops; /* I/O ops since last switch */
+ struct buf sc_q; /* head of buf chain */
+};
+
+/* floppy driver configuration */
+int fdprobe __P((struct device *, void *, void *));
+void fdattach __P((struct device *, struct device *, void *));
+
+struct cfattach fd_ca = {
+ sizeof(struct fd_softc), fdprobe, fdattach
+};
+
+struct cfdriver fd_cd = {
+ NULL, "fd", DV_DISK
+};
+
+void fdgetdisklabel __P((struct fd_softc *));
+int fd_get_parms __P((struct fd_softc *));
+void fdstrategy __P((struct buf *));
+void fdstart __P((struct fd_softc *));
+
+struct dkdriver fddkdriver = { fdstrategy };
+
+struct fd_type *fd_nvtotype __P((char *, int, int));
+void fd_set_motor __P((struct fdc_softc *fdc, int reset));
+void fd_motor_off __P((void *arg));
+void fd_motor_on __P((void *arg));
+int fdcresult __P((struct fdc_softc *fdc));
+int out_fdc __P((int iobase, u_char x));
+void fdcstart __P((struct fdc_softc *fdc));
+void fdcstatus __P((struct device *dv, int n, char *s));
+void fdctimeout __P((void *arg));
+void fdcpseudointr __P((void *arg));
+int fdcintr __P((void *));
+void fdcretry __P((struct fdc_softc *fdc));
+void fdfinish __P((struct fd_softc *fd, struct buf *bp));
+
+int
+fdcprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ register struct mainbus_attach_args *mb = aux;
+ int iobase = mb->mb_iobase;
+
+ /* reset */
+ outb(iobase + fdout, 0);
+ delay(100);
+ outb(iobase + fdout, FDO_FRST);
+
+ /* see if it can handle a command */
+ if (out_fdc(iobase, NE7CMD_SPECIFY) < 0)
+ return 0;
+ out_fdc(iobase, 0xdf);
+ out_fdc(iobase, 6/*2*/); /* Don't remember why - mark */
+
+#ifdef NEWCONFIG
+ if (iobase == IOBASEUNK || ia->ia_drq == DRQUNK)
+ return 0;
+
+ if (ia->ia_irq == IRQUNK) {
+ ia->ia_irq = isa_discoverintr(fdcforceintr, aux);
+ if (ia->ia_irq == IRQNONE)
+ return 0;
+
+ /* reset it again */
+ outb(iobase + fdout, 0);
+ delay(100);
+ outb(iobase + fdout, FDO_FRST);
+ }
+#endif
+
+ mb->mb_iosize = FDC_NPORT;
+ return 1;
+}
+
+#ifdef NEWCONFIG
+void
+fdcforceintr(aux)
+ void *aux;
+{
+ struct mainbus_attach_args *mb = aux;
+ int iobase = mb->mb_iobase;
+
+ /* the motor is off; this should generate an error with or
+ without a disk drive present */
+ out_fdc(iobase, NE7CMD_SEEK);
+ out_fdc(iobase, 0);
+ out_fdc(iobase, 0);
+}
+#endif
+
+/*
+ * Arguments passed between fdcattach and fdprobe.
+ */
+struct fdc_attach_args {
+ int fa_drive;
+ struct fd_type *fa_deftype;
+};
+
+/*
+ * Print the location of a disk drive (called just before attaching the
+ * the drive). If `fdc' is not NULL, the drive was found but was not
+ * in the system config file; print the drive name as well.
+ * Return QUIET (config_find ignores this if the device was configured) to
+ * avoid printing `fdN not configured' messages.
+ */
+int
+fdprint(aux, fdc)
+ void *aux;
+ char *fdc;
+{
+ register struct fdc_attach_args *fa = aux;
+
+ if (!fdc)
+ printf(" drive %d", fa->fa_drive);
+ return QUIET;
+}
+
+void
+fdcattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct fdc_softc *fdc = (void *)self;
+ struct mainbus_attach_args *mb = aux;
+ struct fdc_attach_args fa;
+ int type;
+
+ fdc->sc_iobase = mb->mb_iobase;
+ fdc->sc_drq = mb->mb_iobase + mb->mb_drq;
+ fdc->sc_state = DEVIDLE;
+ TAILQ_INIT(&fdc->sc_drives);
+
+ printf("\n");
+
+/*#ifdef NEWCONFIG
+ at_setup_dmachan(fdc->sc_drq, FDC_MAXIOSIZE);
+ isa_establish(&fdc->sc_id, &fdc->sc_dev);
+#endif*/
+
+ fdc->sc_ih.ih_func = fdcintr;
+ fdc->sc_ih.ih_arg = fdc;
+ fdc->sc_ih.ih_level = IPL_BIO;
+ fdc->sc_ih.ih_name = "fdc";
+ if (irq_claim(mb->mb_irq, &fdc->sc_ih))
+ panic("Cannot claim IRQ %d for fdc%d\n", mb->mb_irq, parent->dv_unit);
+
+ /*
+ * The NVRAM info only tells us about the first two disks on the
+ * `primary' floppy controller.
+ */
+/* if (fdc->sc_dev.dv_unit == 0)
+ type = mc146818_read(NULL, NVRAM_DISKETTE);
+ else
+ type = -1;*/
+
+ type = 0x10;
+
+ /* physical limit: four drives per controller. */
+ for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
+ if (type >= 0 && fa.fa_drive < 2)
+ fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
+ type, fa.fa_drive);
+ else
+ fa.fa_deftype = NULL; /* unknown */
+ (void)config_found(self, (void *)&fa, fdprint);
+ }
+}
+
+int
+fdprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct fdc_softc *fdc = (void *)parent;
+ struct cfdata *cf = match;
+ struct fdc_attach_args *fa = aux;
+ int drive = fa->fa_drive;
+ int iobase = fdc->sc_iobase;
+ int n;
+
+ if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
+ return 0;
+ /*
+ * XXX
+ * This is to work around some odd interactions between this driver
+ * and SMC Ethernet cards.
+ */
+
+ /* Don't need this for arm32 port but leave for the time being (it won't hurt) */
+
+ if (cf->cf_loc[0] == -1 && drive >= 2)
+ return 0;
+
+ /* select drive and turn on motor */
+ outb(iobase + fdout, drive | FDO_FRST | FDO_MOEN(drive));
+ /* wait for motor to spin up */
+ delay(250000);
+ out_fdc(iobase, NE7CMD_RECAL);
+ out_fdc(iobase, drive);
+ /* wait for recalibrate */
+ delay(2000000);
+ out_fdc(iobase, NE7CMD_SENSEI);
+ n = fdcresult(fdc);
+#ifdef FD_DEBUG
+ {
+ int i;
+ printf("fdprobe: status");
+ for (i = 0; i < n; i++)
+ printf(" %x", fdc->sc_status[i]);
+ printf("\n");
+ }
+#endif
+ if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20)
+ return 0;
+ /* turn off motor */
+ outb(iobase + fdout, FDO_FRST);
+
+ return 1;
+}
+
+/*
+ * Controller is working, and drive responded. Attach it.
+ */
+void
+fdattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct fdc_softc *fdc = (void *)parent;
+ struct fd_softc *fd = (void *)self;
+ struct fdc_attach_args *fa = aux;
+ struct fd_type *type = fa->fa_deftype;
+ int drive = fa->fa_drive;
+
+ /* XXX Allow `flags' to override device type? */
+
+ if (type)
+ printf(": %s %d cyl, %d head, %d sec\n", type->name,
+ type->tracks, type->heads, type->sectrac);
+ else
+ printf(": density unknown\n");
+
+ fd->sc_cylin = -1;
+ fd->sc_drive = drive;
+ fd->sc_deftype = type;
+ fdc->sc_fd[drive] = fd;
+
+ /*
+ * Initialize and attach the disk structure.
+ */
+ fd->sc_dk.dk_name = fd->sc_dev.dv_xname;
+ fd->sc_dk.dk_driver = &fddkdriver;
+ disk_attach(&fd->sc_dk);
+
+#ifdef NEWCONFIG
+ /* XXX Need to do some more fiddling with sc_dk. */
+ dk_establish(&fd->sc_dk, &fd->sc_dev);
+#endif
+ /* Needed to power off if the motor is on when we halt. */
+ fd->sc_sdhook = shutdownhook_establish(fd_motor_off, fd);
+}
+
+/*
+ * Translate nvram type into internal data structure. Return NULL for
+ * none/unknown/unusable.
+ */
+struct fd_type *
+fd_nvtotype(fdc, nvraminfo, drive)
+ char *fdc;
+ int nvraminfo, drive;
+{
+ int type;
+
+ type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0;
+ switch (type) {
+/* case 0x00 :
+ return NULL;*/
+ case 0x10 :
+ return &fd_types[0];
+ default:
+ printf("%s: drive %d: unknown device type 0x%x\n",
+ fdc, drive, type);
+ return NULL;
+ }
+}
+
+inline struct fd_type *
+fd_dev_to_type(fd, dev)
+ struct fd_softc *fd;
+ dev_t dev;
+{
+ int type = FDTYPE(dev);
+
+ if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
+ return NULL;
+ return type ? &fd_types[type - 1] : fd->sc_deftype;
+}
+
+void
+fdstrategy(bp)
+ register struct buf *bp; /* IO operation to perform */
+{
+ struct fd_softc *fd;
+ int unit = FDUNIT(bp->b_dev);
+ int sz;
+ int s;
+
+/* printf("fdstrategy: bp=%08x\n", bp);*/
+
+ /* Valid unit, controller, and request? */
+ if (unit >= fd_cd.cd_ndevs ||
+ (fd = fd_cd.cd_devs[unit]) == 0 ||
+ bp->b_blkno < 0 ||
+ (bp->b_bcount % FDC_BSIZE) != 0) {
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+
+ /* If it's a null transfer, return immediately. */
+ if (bp->b_bcount == 0)
+ goto done;
+
+ sz = howmany(bp->b_bcount, FDC_BSIZE);
+
+ if (bp->b_blkno + sz > fd->sc_type->size) {
+ sz = fd->sc_type->size - bp->b_blkno;
+ if (sz == 0) {
+ /* If exactly at end of disk, return EOF. */
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ if (sz < 0) {
+ /* If past end of disk, return EINVAL. */
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ /* Otherwise, truncate request. */
+ bp->b_bcount = sz << DEV_BSHIFT;
+ }
+
+ bp->b_cylin = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl;
+
+#ifdef FD_DEBUG
+ printf("fdstrategy: b_blkno %d b_bcount %d blkno %d cylin %d sz %d\n",
+ bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylin, sz);
+#endif
+
+ /* Queue transfer on drive, activate drive and controller if idle. */
+ s = splbio();
+ disksort(&fd->sc_q, bp);
+ untimeout(fd_motor_off, fd); /* a good idea */
+ /* Instrumentation. */
+ disk_busy(&fd->sc_dk);
+ if (!fd->sc_q.b_active)
+ fdstart(fd);
+#ifdef DIAGNOSTIC
+ else {
+ struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
+ if (fdc->sc_state == DEVIDLE) {
+ printf("fdstrategy: controller inactive\n");
+ fdcstart(fdc);
+ }
+ }
+#endif
+ splx(s);
+ return;
+
+bad:
+ bp->b_flags |= B_ERROR;
+done:
+ /* Toss transfer; we're done early. */
+ biodone(bp);
+}
+
+void
+fdstart(fd)
+ struct fd_softc *fd;
+{
+ struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
+ int active = fdc->sc_drives.tqh_first != 0;
+
+/* printf("fdstart:\n");*/
+
+ /* Link into controller queue. */
+ fd->sc_q.b_active = 1;
+ TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
+
+ /* Instrumentation. */
+/* disk_busy(&fd->sc_dk);*/
+
+ /* If controller not already active, start it. */
+ if (!active)
+ fdcstart(fdc);
+}
+
+void
+fdfinish(fd, bp)
+ struct fd_softc *fd;
+ struct buf *bp;
+{
+ struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
+
+ /*
+ * Move this drive to the end of the queue to give others a `fair'
+ * chance. We only force a switch if N operations are completed while
+ * another drive is waiting to be serviced, since there is a long motor
+ * startup delay whenever we switch.
+ */
+ if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) {
+ fd->sc_ops = 0;
+ TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
+ if (bp->b_actf) {
+ TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
+ } else
+ fd->sc_q.b_active = 0;
+ }
+ bp->b_resid = fd->sc_bcount;
+ fd->sc_skip = 0;
+ fd->sc_q.b_actf = bp->b_actf;
+
+/* printf("fdfinish: fd=%08x buf=%08x busy=%d\n", (u_int)fd, (u_int)bp, fd->sc_dk.dk_busy);*/
+
+ disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid));
+
+ biodone(bp);
+ /* turn off motor 5s from now */
+ timeout(fd_motor_off, fd, 5 * hz);
+ fdc->sc_state = DEVIDLE;
+}
+
+int
+fdread(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+
+ return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+fdwrite(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+
+ return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+void
+fd_set_motor(fdc, reset)
+ struct fdc_softc *fdc;
+ int reset;
+{
+ struct fd_softc *fd;
+ u_char status;
+ int n;
+
+ if (fd = fdc->sc_drives.tqh_first)
+ status = fd->sc_drive;
+ else
+ status = 0;
+ if (!reset)
+ status |= FDO_FRST | FDO_FDMAEN;
+ for (n = 0; n < 4; n++)
+ if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
+ status |= FDO_MOEN(n);
+ outb(fdc->sc_iobase + fdout, status);
+}
+
+void
+fd_motor_off(arg)
+ void *arg;
+{
+ struct fd_softc *fd = arg;
+ int s;
+
+ s = splbio();
+ fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
+ fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0);
+ splx(s);
+}
+
+void
+fd_motor_on(arg)
+ void *arg;
+{
+ struct fd_softc *fd = arg;
+ struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
+ int s;
+
+ s = splbio();
+ fd->sc_flags &= ~FD_MOTOR_WAIT;
+ if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
+ (void) fdcintr(fdc);
+ splx(s);
+}
+
+int
+fdcresult(fdc)
+ struct fdc_softc *fdc;
+{
+ int iobase = fdc->sc_iobase;
+ u_char i;
+ int j = 100000,
+ n = 0;
+
+ for (; j; j--) {
+ i = inb(iobase + fdsts) & (NE7_DIO | NE7_RQM | NE7_CB);
+ if (i == NE7_RQM)
+ return n;
+ if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
+ if (n >= sizeof(fdc->sc_status)) {
+ log(LOG_ERR, "fdcresult: overrun\n");
+ return -1;
+ }
+ fdc->sc_status[n++] = inb(iobase + fddata);
+ }
+ }
+ log(LOG_ERR, "fdcresult: timeout\n");
+ return -1;
+}
+
+int
+out_fdc(iobase, x)
+ int iobase;
+ u_char x;
+{
+ int i = 100000;
+
+ while ((inb(iobase + fdsts) & NE7_DIO) && i-- > 0);
+ if (i <= 0)
+ return -1;
+ while ((inb(iobase + fdsts) & NE7_RQM) == 0 && i-- > 0);
+ if (i <= 0)
+ return -1;
+ outb(iobase + fddata, x);
+ return 0;
+}
+
+int
+fdopen(dev, flags)
+ dev_t dev;
+ int flags;
+{
+ int unit;
+ struct fd_softc *fd;
+ struct fd_type *type;
+
+ unit = FDUNIT(dev);
+ if (unit >= fd_cd.cd_ndevs)
+ return ENXIO;
+ fd = fd_cd.cd_devs[unit];
+ if (fd == 0)
+ return ENXIO;
+ type = fd_dev_to_type(fd, dev);
+ if (type == NULL)
+ return ENXIO;
+
+ if ((fd->sc_flags & FD_OPEN) != 0 &&
+ fd->sc_type != type)
+ return EBUSY;
+
+ fd->sc_type = type;
+ fd->sc_cylin = -1;
+ fd->sc_flags |= FD_OPEN;
+
+ return 0;
+}
+
+int
+fdclose(dev, flags)
+ dev_t dev;
+ int flags;
+{
+ struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
+
+ fd->sc_flags &= ~FD_OPEN;
+ return 0;
+}
+
+void
+fdcstart(fdc)
+ struct fdc_softc *fdc;
+{
+
+#ifdef DIAGNOSTIC
+ /* only got here if controller's drive queue was inactive; should
+ be in idle state */
+ if (fdc->sc_state != DEVIDLE) {
+ printf("fdcstart: not idle\n");
+ return;
+ }
+#endif
+ (void) fdcintr(fdc);
+}
+
+void
+fdcstatus(dv, n, s)
+ struct device *dv;
+ int n;
+ char *s;
+{
+ struct fdc_softc *fdc = (void *)dv->dv_parent;
+ int iobase = fdc->sc_iobase;
+
+ if (n == 0) {
+ out_fdc(fdc->sc_iobase, NE7CMD_SENSEI);
+ (void) fdcresult(fdc);
+ n = 2;
+ }
+
+ printf("%s: %s", dv->dv_xname, s);
+
+ switch (n) {
+ case 0:
+ printf("\n");
+ break;
+ case 2:
+ printf(" (st0 %b cyl %d)\n",
+ fdc->sc_status[0], NE7_ST0BITS,
+ fdc->sc_status[1]);
+ break;
+ case 7:
+ printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
+ fdc->sc_status[0], NE7_ST0BITS,
+ fdc->sc_status[1], NE7_ST1BITS,
+ fdc->sc_status[2], NE7_ST2BITS,
+ fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
+ break;
+#ifdef DIAGNOSTIC
+ default:
+ printf("\nfdcstatus: weird size");
+ break;
+#endif
+ }
+}
+
+void
+fdctimeout(arg)
+ void *arg;
+{
+ struct fdc_softc *fdc = arg;
+ struct fd_softc *fd = fdc->sc_drives.tqh_first;
+ int s;
+
+ s = splbio();
+ fdcstatus(&fd->sc_dev, 0, "timeout");
+
+ if (fd->sc_q.b_actf)
+ fdc->sc_state++;
+ else
+ fdc->sc_state = DEVIDLE;
+
+ (void) fdcintr(fdc);
+ splx(s);
+}
+
+void
+fdcpseudointr(arg)
+ void *arg;
+{
+ int s;
+
+ /* Just ensure it has the right spl. */
+ s = splbio();
+ (void) fdcintr(arg);
+ splx(s);
+}
+
+int
+fdcintr(arg)
+ void *arg;
+{
+ struct fdc_softc *fdc = arg;
+#define st0 fdc->sc_status[0]
+#define cyl fdc->sc_status[1]
+ struct fd_softc *fd;
+ struct buf *bp;
+ int iobase = fdc->sc_iobase;
+ int read, head, trac, sec, i, s, nblks;
+ struct fd_type *type;
+
+loop:
+ /* Is there a drive for the controller to do a transfer with? */
+ fd = fdc->sc_drives.tqh_first;
+ if (fd == NULL) {
+ fdc->sc_state = DEVIDLE;
+ return 1;
+ }
+
+ /* Is there a transfer to this drive? If not, deactivate drive. */
+ bp = fd->sc_q.b_actf;
+ if (bp == NULL) {
+ fd->sc_ops = 0;
+ TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
+ fd->sc_q.b_active = 0;
+ goto loop;
+ }
+
+ switch (fdc->sc_state) {
+ case DEVIDLE:
+ fdc->sc_errors = 0;
+ fd->sc_skip = 0;
+ fd->sc_bcount = bp->b_bcount;
+ fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE);
+ untimeout(fd_motor_off, fd);
+ if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
+ fdc->sc_state = MOTORWAIT;
+ return 1;
+ }
+ if ((fd->sc_flags & FD_MOTOR) == 0) {
+ /* Turn on the motor, being careful about pairing. */
+ struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1];
+ if (ofd && ofd->sc_flags & FD_MOTOR) {
+ untimeout(fd_motor_off, ofd);
+ ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
+ }
+ fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
+ fd_set_motor(fdc, 0);
+ fdc->sc_state = MOTORWAIT;
+ /* Allow .25s for motor to stabilize. */
+ timeout(fd_motor_on, fd, hz / 4);
+ return 1;
+ }
+ /* Make sure the right drive is selected. */
+ fd_set_motor(fdc, 0);
+
+ /* fall through */
+ case DOSEEK:
+ doseek:
+ if (fd->sc_cylin == bp->b_cylin)
+ goto doio;
+
+ out_fdc(iobase, NE7CMD_CONFIGURE);/* configure command */
+ out_fdc(iobase, 0);
+ out_fdc(iobase, 0x1a);
+ out_fdc(iobase, 0);
+
+ out_fdc(iobase, NE7CMD_SPECIFY);/* specify command */
+ out_fdc(iobase, fd->sc_type->steprate);
+ out_fdc(iobase, 6); /* XXX head load time == 6ms */
+
+ out_fdc(iobase, NE7CMD_SEEK); /* seek function */
+ out_fdc(iobase, fd->sc_drive); /* drive number */
+ out_fdc(iobase, bp->b_cylin * fd->sc_type->step);
+
+ fd->sc_cylin = -1;
+ fdc->sc_state = SEEKWAIT;
+ timeout(fdctimeout, fdc, 4 * hz);
+ return 1;
+
+ case DOIO:
+ doio:
+ type = fd->sc_type;
+ sec = fd->sc_blkno % type->seccyl;
+ nblks = type->seccyl - sec;
+ nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
+ nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE);
+ fd->sc_nblks = nblks;
+ fd->sc_nbytes = nblks * FDC_BSIZE;
+ head = sec / type->sectrac;
+ sec -= head * type->sectrac;
+#ifdef DIAGNOSTIC
+ {int block;
+ block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
+ if (block != fd->sc_blkno) {
+ printf("fdcintr: block %d != blkno %d\n", block, fd->sc_blkno);
+#ifdef DDB
+ Debugger();
+#endif
+ }}
+#endif
+ read = bp->b_flags & B_READ;
+/*#ifdef NEWCONFIG
+ at_dma(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
+ fdc->sc_drq);
+#else
+ isa_dmastart(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
+ fdc->sc_drq);
+#endif*/
+ if (read)
+ fiqhandler.fh_func = floppy_read_fiq;
+ else
+ fiqhandler.fh_func = floppy_write_fiq;
+ fiqhandler.fh_r11 = nblks * FDC_BSIZE;
+ fiqhandler.fh_r12 = (int)bp->b_data + (int)fd->sc_skip;
+ fiqhandler.fh_r13 = fdc->sc_drq;
+ fiqhandler.fh_mask = 0x01;
+ if (fiq_claim(&fiqhandler) == -1)
+ panic("Cannot claim FIQ vector\n");
+
+ outb(iobase + fdctl, type->rate);
+#ifdef FD_DEBUG
+ printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
+ read ? "read" : "write", fd->sc_drive, fd->sc_cylin, head,
+ sec, nblks);
+#endif
+ if (read)
+ out_fdc(iobase, NE7CMD_READ); /* READ */
+ else
+ out_fdc(iobase, NE7CMD_WRITE); /* WRITE */
+ out_fdc(iobase, (head << 2) | fd->sc_drive);
+ out_fdc(iobase, fd->sc_cylin); /* track */
+ out_fdc(iobase, head);
+ out_fdc(iobase, sec + 1); /* sector +1 */
+ out_fdc(iobase, type->secsize); /* sector size */
+ out_fdc(iobase, type->sectrac); /* sectors/track */
+ out_fdc(iobase, type->gap1); /* gap1 size */
+ out_fdc(iobase, type->datalen); /* data length */
+ fdc->sc_state = IOCOMPLETE;
+ /* allow 2 seconds for operation */
+ timeout(fdctimeout, fdc, 2 * hz);
+ return 1; /* will return later */
+
+ case SEEKWAIT:
+ untimeout(fdctimeout, fdc);
+ fdc->sc_state = SEEKCOMPLETE;
+ /* allow 1/50 second for heads to settle */
+/* timeout(fdcpseudointr, fdc, hz / 50);*/
+ return 1;
+
+ case SEEKCOMPLETE:
+ /* Make sure seek really happened. */
+ out_fdc(iobase, NE7CMD_SENSEI);
+ if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
+ cyl != bp->b_cylin * fd->sc_type->step) {
+#ifdef FD_DEBUG
+ fdcstatus(&fd->sc_dev, 2, "seek failed");
+#endif
+ fdcretry(fdc);
+ goto loop;
+ }
+ fd->sc_cylin = bp->b_cylin;
+ goto doio;
+
+ case IOTIMEDOUT:
+/*#ifdef NEWCONFIG
+ at_dma_abort(fdc->sc_drq);
+#else
+ isa_dmaabort(fdc->sc_drq);
+#endif*/
+ if (fiq_release(&fiqhandler) == -1)
+ panic("Cannot release FIQ vector\n");
+ case SEEKTIMEDOUT:
+ case RECALTIMEDOUT:
+ case RESETTIMEDOUT:
+ fdcretry(fdc);
+ goto loop;
+
+ case IOCOMPLETE: /* IO DONE, post-analyze */
+ untimeout(fdctimeout, fdc);
+ if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
+/*#ifdef NEWCONFIG
+ at_dma_abort(fdc->sc_drq);
+#else
+ isa_dmaabort(fdc->sc_drq);
+#endif*/
+ if (fiq_release(&fiqhandler) == -1)
+ panic("Cannot release FIQ vector\n");
+#ifdef FD_DEBUG
+ fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
+ "read failed" : "write failed");
+ printf("blkno %d nblks %d\n",
+ fd->sc_blkno, fd->sc_nblks);
+#endif
+ fdcretry(fdc);
+ goto loop;
+ }
+/*#ifdef NEWCONFIG
+ at_dma_terminate(fdc->sc_drq);
+#else
+ read = bp->b_flags & B_READ;
+ isa_dmadone(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
+ fdc->sc_drq);
+#endif*/
+ if (fiq_release(&fiqhandler) == -1)
+ panic("Cannot release FIQ vector\n");
+
+ if (fdc->sc_errors) {
+/* diskerr(bp, "fd", "soft error", LOG_PRINTF,
+ fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
+ printf("\n");*/
+ fdc->sc_errors = 0;
+ }
+ fd->sc_blkno += fd->sc_nblks;
+ fd->sc_skip += fd->sc_nbytes;
+ fd->sc_bcount -= fd->sc_nbytes;
+ if (fd->sc_bcount > 0) {
+ bp->b_cylin = fd->sc_blkno / fd->sc_type->seccyl;
+ goto doseek;
+ }
+/* printf("IOCOMPLETE:calling fdfinish fd=%08x bp=%08x blkno=%d\n", (u_int)fd, (u_int)bp, fd->sc_blkno);*/
+ fdfinish(fd, bp);
+ goto loop;
+
+ case DORESET:
+ /* try a reset, keep motor on */
+ fd_set_motor(fdc, 1);
+ delay(100);
+ fd_set_motor(fdc, 0);
+ fdc->sc_state = RESETCOMPLETE;
+ timeout(fdctimeout, fdc, hz / 2);
+ return 1; /* will return later */
+
+ case RESETCOMPLETE:
+ untimeout(fdctimeout, fdc);
+ /* clear the controller output buffer */
+ for (i = 0; i < 4; i++) {
+ out_fdc(iobase, NE7CMD_SENSEI);
+ (void) fdcresult(fdc);
+ }
+
+ /* fall through */
+ case DORECAL:
+ out_fdc(iobase, NE7CMD_RECAL); /* recalibrate function */
+ out_fdc(iobase, fd->sc_drive);
+ fdc->sc_state = RECALWAIT;
+ timeout(fdctimeout, fdc, 5 * hz);
+ return 1; /* will return later */
+
+ case RECALWAIT:
+ untimeout(fdctimeout, fdc);
+ fdc->sc_state = RECALCOMPLETE;
+ /* allow 1/30 second for heads to settle */
+/* timeout(fdcpseudointr, fdc, hz / 30);*/
+ return 1; /* will return later */
+
+ case RECALCOMPLETE:
+ out_fdc(iobase, NE7CMD_SENSEI);
+ if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
+#ifdef FD_DEBUG
+ fdcstatus(&fd->sc_dev, 2, "recalibrate failed");
+#endif
+ fdcretry(fdc);
+ goto loop;
+ }
+ fd->sc_cylin = 0;
+ goto doseek;
+
+ case MOTORWAIT:
+ if (fd->sc_flags & FD_MOTOR_WAIT)
+ return 1; /* time's not up yet */
+ goto doseek;
+
+ default:
+ fdcstatus(&fd->sc_dev, 0, "stray interrupt");
+ return 1;
+ }
+#ifdef DIAGNOSTIC
+ panic("fdcintr: impossible");
+#endif
+#undef st0
+#undef cyl
+}
+
+void
+fdcretry(fdc)
+ struct fdc_softc *fdc;
+{
+ struct fd_softc *fd;
+ struct buf *bp;
+
+ fd = fdc->sc_drives.tqh_first;
+ bp = fd->sc_q.b_actf;
+
+ switch (fdc->sc_errors) {
+ case 0:
+ /* try again */
+/* fdc->sc_state = SEEKCOMPLETE;*/
+ fdc->sc_state = DOSEEK;
+ break;
+
+ case 1: case 2: case 3:
+ /* didn't work; try recalibrating */
+ fdc->sc_state = DORECAL;
+ break;
+
+ case 4:
+ /* still no go; reset the bastard */
+ fdc->sc_state = DORESET;
+ break;
+
+ default:
+ diskerr(bp, "fd", "hard error", LOG_PRINTF,
+ fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
+ printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
+ fdc->sc_status[0], NE7_ST0BITS,
+ fdc->sc_status[1], NE7_ST1BITS,
+ fdc->sc_status[2], NE7_ST2BITS,
+ fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
+
+ bp->b_flags |= B_ERROR;
+ bp->b_error = EIO;
+ fdfinish(fd, bp);
+ }
+ fdc->sc_errors++;
+}
+
+int
+fdsize(dev)
+ dev_t dev;
+{
+
+ /* Swapping to floppies would not make sense. */
+ return -1;
+}
+
+int
+fddump(dev, blkno, va, size)
+ dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
+{
+
+ /* Not implemented. */
+ return ENXIO;
+}
+
+int
+fdioctl(dev, cmd, addr, flag)
+ dev_t dev;
+ u_long cmd;
+ caddr_t addr;
+ int flag;
+{
+ struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
+ struct disklabel buffer;
+ int error;
+
+ switch (cmd) {
+ case DIOCGDINFO:
+ bzero(&buffer, sizeof(buffer));
+
+ buffer.d_secpercyl = fd->sc_type->seccyl;
+ buffer.d_type = DTYPE_FLOPPY;
+ buffer.d_secsize = FDC_BSIZE;
+
+ if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL)
+ return EINVAL;
+
+ *(struct disklabel *)addr = buffer;
+ return 0;
+
+ case DIOCWLABEL:
+ if ((flag & FWRITE) == 0)
+ return EBADF;
+ /* XXX do something */
+ return 0;
+
+ case DIOCWDINFO:
+ if ((flag & FWRITE) == 0)
+ return EBADF;
+
+ error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL);
+ if (error)
+ return error;
+
+ error = writedisklabel(dev, fdstrategy, &buffer, NULL);
+ return error;
+
+ default:
+ return ENOTTY;
+ }
+
+#ifdef DIAGNOSTIC
+ panic("fdioctl: impossible");
+#endif
+}
+
+
+#include "rd.h"
+#if NRD > 0
+
+#include <dev/ramdisk.h>
+
+int
+load_ramdisc_from_floppy(rd, dev)
+ struct rd_conf *rd;
+ dev_t dev;
+{
+ struct buf *bp;
+ int loop;
+ int s;
+ int type;
+ int floppysize;
+
+ if (major(dev) != 17)
+ return(EINVAL);
+
+ if (rd->rd_type == RD_UNCONFIGURED || rd->rd_addr == 0)
+ return(EBUSY);
+
+ type = FDTYPE(dev) - 1;
+ if (type < 0) type = 0;
+ floppysize = fd_types[type].size << (fd_types[type].secsize + 7);
+
+ if (rd->rd_size < floppysize) {
+ printf("Ramdisc not big enough for floppy image\n");
+ return(EINVAL);
+ }
+
+/* We have the ramdisk ! */
+
+ printf("Loading ramdisc : %4dK ", 0);
+
+/* obtain a buffer */
+
+ bp = geteblk(fd_types[type].sectrac * DEV_BSIZE);
+
+/* request no partition relocation by driver on I/O operations */
+
+ bp->b_dev = dev;
+
+ s = spl0();
+
+ if (fdopen(bp->b_dev, 0) != 0) {
+ brelse(bp);
+ printf("Cannot open floppy device\n");
+ return(EINVAL);
+ }
+
+ for (loop = 0;
+ loop < (floppysize / DEV_BSIZE / fd_types[type].sectrac);
+ ++loop) {
+ printf("\x08\x08\x08\x08\x08\x08%4dK ",
+ loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
+ bp->b_blkno = loop * fd_types[type].sectrac;
+ bp->b_bcount = fd_types[type].sectrac * DEV_BSIZE;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_error = 0;
+ bp->b_resid = 0;
+ fdstrategy(bp);
+
+ if (biowait(bp))
+ panic("Cannot load floppy image\n");
+
+ bcopy((caddr_t)bp->b_data, (caddr_t)rd->rd_addr
+ + loop * fd_types[type].sectrac * DEV_BSIZE,
+ fd_types[type].sectrac * DEV_BSIZE);
+ }
+ printf("\x08\x08\x08\x08\x08\x08%4dK done\n",
+ loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
+
+ fdclose(bp->b_dev, 0);
+
+ brelse(bp);
+
+ splx(s);
+ return(0);
+}
+
+#endif
--- /dev/null
+/* $NetBSD: fdreg.h,v 1.2 1996/03/18 20:50:02 mark Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fdreg.h 7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * AT floppy controller registers and bitfields
+ */
+
+
+/*
+ * Nec 765 floppy disc controller definitions
+ */
+
+/* Main status register */
+#define NE7_DAB 0x01 /* Diskette drive A is seeking, thus busy */
+#define NE7_DBB 0x02 /* Diskette drive B is seeking, thus busy */
+#define NE7_CB 0x10 /* Diskette Controller Busy */
+#define NE7_NDM 0x20 /* Diskette Controller in Non Dma Mode */
+#define NE7_DIO 0x40 /* Diskette Controller Data register I/O */
+#define NE7_RQM 0x80 /* Diskette Controller ReQuest for Master */
+
+/* Status register ST0 */
+#define NE7_ST0BITS "\020\010invld\007abnrml\006seek_cmplt\005drv_chck\004drive_rdy\003top_head"
+
+/* Status register ST1 */
+#define NE7_ST1BITS "\020\010end_of_cyl\006bad_crc\005data_overrun\003sec_not_fnd\002write_protect\001no_am"
+
+/* Status register ST2 */
+#define NE7_ST2BITS "\020\007ctrl_mrk\006bad_crc\005wrong_cyl\004scn_eq\003scn_not_fnd\002bad_cyl\001no_dam"
+
+/* Status register ST3 */
+#define NE7_ST3BITS "\020\010fault\007write_protect\006drdy\005tk0\004two_side\003side_sel\002"
+
+/* Commands */
+#define NE7CMD_SPECIFY 3 /* specify drive parameters - requires unit
+ parameters byte */
+#define NE7CMD_SENSED 4 /* sense drive - requires unit select byte */
+#define NE7CMD_WRITE 0xc5 /* write - requires eight additional bytes */
+#define NE7CMD_READ 0xe6 /* read - requires eight additional bytes */
+#define NE7CMD_FORMAT 0x4c /* format - requires five additional bytes */
+#define NE7CMD_RECAL 7 /* recalibrate drive - requires
+ unit select byte */
+#define NE7CMD_SENSEI 8 /* sense controller interrupt status */
+#define NE7CMD_SEEK 15 /* seek drive - requires unit select byte
+ and new cyl byte */
+#define NE7CMD_CONFIGURE 0x13
+
+/* registers */
+#define fdout 8 /* Digital Output Register (W) */
+#define FDO_FDSEL 0x03 /* floppy device select */
+#define FDO_FRST 0x04 /* floppy controller reset */
+#define FDO_FDMAEN 0x08 /* enable floppy DMA and Interrupt */
+#define FDO_MOEN(n) ((1 << n) * 0x10) /* motor enable */
+
+#define fdsts 16 /* NEC 765 Main Status Register (R) */
+#define fddata 20 /* NEC 765 Data Register (R/W) */
+
+#define fdctl 28 /* Control Register (W) */
+#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */
+#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */
+#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */
+#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */
+
+#define fdin 28 /* Digital Input Register (R) */
+#define FDI_DCHG 0x80 /* diskette has been changed */
+
+#define FDC_BSIZE 512
+#define FDC_NPORT 32
+#define FDC_MAXIOSIZE NBPG /* XXX should be MAXBSIZE */
--- /dev/null
+/* $NetBSD: iic.c,v 1.1 1996/04/19 19:49:03 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * iic.c
+ *
+ * Routines to communicate with IIC devices
+ *
+ * Created : 13/10/94
+ *
+ * Based of kate/display/iiccontrol.c
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <machine/io.h>
+#include <machine/iomd.h>
+#include <machine/katelib.h>
+#include <machine/cpu.h>
+#include <machine/irqhandler.h>
+#include <machine/iic.h>
+#include <arm32/mainbus/mainbus.h>
+
+/* Local function prototypes */
+
+static int iic_getack __P((void));
+static void iic_write_bit __P((int bit));
+static int iic_write_byte __P((u_char value));
+static u_char iic_read_byte __P((void));
+static void iic_start_bit __P((void));
+static void iic_stop_bit __P((void));
+
+struct iic_softc {
+ struct device sc_dev;
+ int sc_flags;
+#define IIC_BROKEN 1
+#define IIC_OPEN 2
+#define IIC_BUSY 4
+};
+
+void iicattach __P((struct device *parent, struct device *self, void *aux));
+int iicmatch __P((struct device *parent, void *match, void *aux));
+
+/*
+ * Main entry to IIC driver.
+ */
+
+int
+iic_control(address, buffer, count)
+ u_char address;
+ u_char *buffer;
+ int count;
+{
+ int loop;
+
+/* Send the start bit */
+
+ iic_start_bit();
+
+/* Send the address */
+
+ if (!iic_write_byte(address)) {
+ iic_stop_bit();
+ return(-1);
+ }
+
+/* Read or write the data as required */
+
+ if ((address & 1) == 0) {
+/* Write bytes */
+ for (loop = 0; loop < count; ++loop) {
+ if (!iic_write_byte(buffer[loop])) {
+ iic_stop_bit();
+ return(-1);
+ }
+ }
+ }
+ else {
+/* Read bytes */
+ for (loop = 0; loop < count; ++loop) {
+ buffer[loop] = iic_read_byte();
+
+/* Send final acknowledge */
+
+ if (loop == (count - 1))
+ iic_write_bit(1);
+ else
+ iic_write_bit(0);
+ }
+ }
+
+/* Send stop bit */
+
+ iic_stop_bit();
+
+ return(0);
+}
+
+
+static int
+iic_getack()
+{
+ u_int oldirqstate;
+ int ack;
+
+ iic_set_state(1, 0);
+ oldirqstate = disable_interrupts(I32_bit);
+ iic_set_state_and_ack(1, 1);
+ ack = ReadByte(IOMD_IOCR);
+ iic_set_state(1, 0);
+ restore_interrupts(oldirqstate);
+
+ return((ack & 1) == 0);
+}
+
+
+static void
+iic_write_bit(bit)
+ int bit;
+{
+ u_int oldirqstate;
+
+ iic_set_state(bit, 0);
+ oldirqstate = disable_interrupts(I32_bit);
+ iic_set_state_and_ack(bit, 1);
+ iic_set_state(bit, 0);
+ restore_interrupts(oldirqstate);
+}
+
+
+static int
+iic_write_byte(value)
+ u_char value;
+{
+ int loop;
+ int bit;
+
+ for (loop = 0x80; loop != 0; loop = loop >> 1) {
+ bit = ((value & loop) != 0);
+ iic_write_bit(bit);
+ }
+
+ return(iic_getack());
+}
+
+
+static u_char
+iic_read_byte()
+{
+ int loop;
+ u_char byte;
+ u_int oldirqstate;
+
+ iic_set_state(1,0);
+
+ byte = 0;
+
+ for (loop = 0; loop < 8; ++loop) {
+ oldirqstate = disable_interrupts(I32_bit);
+ iic_set_state_and_ack(1, 1);
+ byte = (byte << 1) + (ReadByte(IOMD_IOCR) & 1);
+ iic_set_state(1, 0);
+ restore_interrupts(oldirqstate);
+ }
+
+ return(byte);
+}
+
+
+static void
+iic_start_bit()
+{
+ iic_set_state(1, 1);
+ iic_set_state(0, 1);
+ iic_delay(10);
+ iic_set_state(0, 0);
+}
+
+
+static void
+iic_stop_bit()
+{
+ iic_set_state(0, 1);
+ iic_set_state(1, 1);
+}
+
+
+struct cfattach iic_ca = {
+ sizeof(struct iic_softc), iicmatch, iicattach
+};
+
+struct cfdriver iic_cd = {
+ NULL, "iic", DV_DULL, 0
+};
+
+int
+iicmatch(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ int id;
+
+/* Make sure we have an IOMD we understand */
+
+ id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+ switch (id) {
+ case RPC600_IOMD_ID:
+ case RC7500_IOC_ID:
+ return(1);
+ break;
+ default:
+ printf("iic: Unknown IOMD id=%04x", id);
+ break;
+ }
+
+ return(0);
+}
+
+int
+iicprint(aux, name)
+ void *aux;
+ char *name;
+{
+ struct iicbus_attach_args *ib = aux;
+
+ if (!name) {
+ if (ib->ib_addr)
+ printf(" addr 0x%02x", ib->ib_addr);
+ }
+
+/* XXXX print flags */
+ return (QUIET);
+}
+
+
+int
+iicsubmatch(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ struct cfdata *cf = match;
+ struct iicbus_attach_args *ib = aux;
+
+ if (cf->cf_fstate == FSTATE_STAR)
+ panic("eekkk, I'm stuffed");
+
+ ib->ib_addr = cf->cf_loc[0];
+
+ if (ib->ib_addr == -1)
+ return(0);
+
+ return((*cf->cf_attach->ca_match)(parent, match, aux));
+}
+
+void
+iicattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct iicbus_attach_args iaa;
+
+ printf("\n");
+
+ while (config_found_sm(self, &iaa, iicprint, iicsubmatch));
+}
+
+
+int
+iicopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct iic_softc *sc;
+ int unit = minor(dev);
+
+ if (unit >= iic_cd.cd_ndevs)
+ return(ENXIO);
+
+ sc = iic_cd.cd_devs[unit];
+
+ if (!sc) return(ENXIO);
+
+ if (sc->sc_flags & IIC_OPEN) return(EBUSY);
+
+ sc->sc_flags |= IIC_OPEN;
+
+ return(0);
+}
+
+
+int
+iicclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ int unit = minor(dev);
+ struct iic_softc *sc = iic_cd.cd_devs[unit];
+
+ sc->sc_flags &= ~IIC_OPEN;
+
+ return(0);
+}
+
+
+int
+iicread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ int unit = minor(dev);
+ struct iic_softc *sc = iic_cd.cd_devs[unit];
+
+ return(ENXIO);
+}
+
+
+int
+iicwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ int unit = minor(dev);
+ struct iic_softc *sc = iic_cd.cd_devs[unit];
+
+ return(ENXIO);
+}
+
+
+int
+iicioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct iic_softc *sc = iic_cd.cd_devs[minor(dev)];
+
+/*
+ switch (cmd) {
+ case IICIOC_CONTROL:
+ if (iiccontrol() != 0) {
+ return(EIO);
+ }
+ return(0);
+ }
+*/
+
+ return(EINVAL);
+}
+
+/* End of iic.c */
--- /dev/null
+/* $NetBSD: iic_asm.S,v 1.1 1996/04/19 19:49:04 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * iic.s
+ *
+ * Low level routines to with IIC devices
+ *
+ * Created : 13/10/94
+ *
+ * Based of kate/display/iic.s
+ */
+
+#include <machine/cpu.h>
+#include <machine/iomd.h>
+
+#define IIC_BITDELAY 10
+
+sp .req r13
+lr .req r14
+pc .req r15
+
+.text
+
+ .global _iic_set_state
+
+_iic_set_state:
+/*
+ * Parameters
+ * r0 - IIC data bit
+ * r1 - IIC clock bit
+ */
+
+/* Store temporary register */
+/* stmfd sp!, {r4}*/
+
+/*
+ * Mask the data and clock bits
+ * Since these routines are only called from iiccontrol.c this is not
+ * really needed
+ */
+ and r0, r0, #0x00000001
+ and r1, r1, #0x00000001
+
+/* Get address of IOMD control register */
+
+ mov r2, #(IOMD_BASE)
+
+/* Get the current CPSR */
+/* mrs r4, cpsr_all
+ orr r3, r4, #(I32_bit | F32_bit)
+ msr cpsr_all, r3
+*/
+
+ IRQdisable
+
+/* Get current value of control register */
+
+ ldrb r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+
+/* Preserve non-IIC bits */
+
+ bic r3, r3, #0x00000003
+ orr r3, r3, #0x000000c0
+
+/* Set the IIC clock and data bits */
+
+ orr r3, r3, r0
+ orr r3, r3, r1, lsl #1
+
+/* Store the new value of control register */
+
+ strb r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+
+/* Restore CPSR state */
+/* msr cpsr_all, r4 */
+
+ IRQenable
+
+/* Restore temporary register */
+/* ldmfd sp!, {r4} */
+
+/* Pause a bit */
+
+ mov r0, #(IIC_BITDELAY)
+
+/* Exit via iic_delay routine */
+ b _iic_delay
+
+
+ .global _iic_set_state_and_ack
+
+_iic_set_state_and_ack:
+/*
+ * Parameters
+ * r0 - IIC data bit
+ * r1 - IIC clock bit
+ */
+/* Store temporary register */
+/* stmfd sp!, {r4} */
+
+/*
+ * Mask the data and clock bits
+ * Since these routines are only called from iiccontrol.c this is not
+ * really needed
+ */
+
+ and r0, r0, #0x00000001
+ and r1, r1, #0x00000001
+
+/* Get address of IOMD control register */
+
+ mov r2, #(IOMD_BASE)
+
+/* Get the current CPSR */
+/* mrs r4, cpsr_all
+ orr r3, r4, #(I32_bit | F32_bit)
+ msr cpsr_all, r3
+*/
+ IRQdisable
+
+/* Get current value of control register */
+
+ ldrb r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+
+/* Preserve non-IIC bits */
+
+ bic r3, r3, #0x00000003
+ orr r3, r3, #0x000000c0
+
+/* Set the IIC clock and data bits */
+
+ orr r3, r3, r0
+ orr r3, r3, r1, lsl #1
+
+/* Store the new value of control register */
+
+ strb r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+
+iic_set_state_and_ack_loop:
+ ldrb r3, [r2, #(IOMD_IOCR - IOMD_BASE)]
+ tst r3, #0x00000002
+ beq iic_set_state_and_ack_loop
+
+/* Restore CPSR state */
+/* msr cpsr_all, r4 */
+
+ IRQenable
+
+/* Restore temporary register */
+/* ldmfd sp!, {r4} */
+
+/* Pause a bit */
+
+ mov r0, #(IIC_BITDELAY)
+
+/* Exit via iic_delay routine */
+ b _iic_delay
+
+
+ .global _iic_delay
+
+_iic_delay:
+/*
+ * Parameters
+ * r0 - time to wait
+ */
+
+/* Load address of IOMD */
+
+ mov r2, #(IOMD_BASE)
+
+/* Latch current value of timer 1 */
+
+ strb r2, [r2, #(IOMD_T0LATCH - IOMD_BASE)]
+
+/* Get the latched value */
+
+ ldrb r1, [r2, #(IOMD_T0LOW - IOMD_BASE)]
+
+/* Loop until timer reaches end value */
+
+iic_delay_loop:
+
+/* Latch the current value of timer1 */
+
+ strb r2, [r2, #(IOMD_T0LATCH - IOMD_BASE)]
+
+/* Get the latched value */
+
+ ldrb r3, [r2, #(IOMD_T0LOW - IOMD_BASE)]
+
+/* Loop until timer reached expected value */
+
+ teq r3, r1
+ movne r1, r3
+ beq iic_delay_loop
+
+ subs r0, r0, #0x00000001
+ bne iic_delay_loop
+
+/* Exit */
+ mov pc, lr
+
+/* End of iic_asm.S */
--- /dev/null
+/* $NetBSD: kbd.c,v 1.7 1996/03/28 21:55:15 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * kbd.c
+ *
+ * Keyboard driver functions
+ *
+ * Created : 09/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/malloc.h>
+#include <sys/tty.h>
+#include <sys/vnode.h>
+#include <sys/select.h>
+#include <sys/fcntl.h>
+#include <sys/signalvar.h>
+#include <sys/time.h>
+
+#include <machine/irqhandler.h>
+#include <machine/iomd.h>
+#include <machine/vidc.h>
+#include <machine/katelib.h>
+#include <machine/kbd.h>
+#include <arm32/mainbus/mainbus.h>
+#include "vt.h"
+#include "kbd.h"
+
+/* Declare global variables */
+
+/* Declare external variables */
+
+/* Local function prototypes */
+
+/* Now for the main code */
+
+/* Define the key_struct structure */
+
+typedef struct {
+ int base_code; /* Base ASCII code */
+ int shift_code; /* Shifted ASCII code */
+ int ctrl_code; /* CTRL code */
+ int alt_code; /* Alt code */
+ int flags; /* Flags field */
+} key_struct;
+
+/* Define mappings for each possible code */
+
+key_struct keys[256] = {
+/* 0x00 - 0x0f */
+ { 0x00, 0x00, 0x00, 0x00, 0x80 },
+ { 0x89, 0x99, 0x00, 0x489, 0x00 },
+ { 0x8a, 0x9a, 0x00, 0x00, 0x00 },
+ { 0x85, 0x95, 0x00, 0x485, 0x00 },
+ { 0x83, 0x93, 0x00, 0x483, 0x00 },
+ { 0x81, 0x91, 0x00, 0x481, 0x00 },
+ { 0x82, 0x92, 0x00, 0x482, 0x00 },
+ { 0x8c, 0x9c, 0x00, 0x48c, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x88, 0x98, 0x00, 0x488, 0x00 },
+ { 0x86, 0x96, 0x00, 0x486, 0x00 },
+ { 0x84, 0x94, 0x00, 0x484, 0x00 },
+ { 0x09, 0x09, 0x09, 0x09, 0x00 },
+ { 0x60, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x10 - 0x1f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x84 },
+ { 0x00, 0x00, 0x00, 0x00, 0x82 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x81 },
+ { 0x71, 0x51, 0x11, 0x00, 0x40 },
+ { 0x31, 0x21, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x7a, 0x5a, 0x1a, 0x00, 0x40 },
+ { 0x73, 0x53, 0x13, 0x00, 0x40 },
+ { 0x61, 0x41, 0x01, 0x00, 0x40 },
+ { 0x77, 0x57, 0x17, 0x00, 0x40 },
+ { 0x32, 0x22, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x20 - 0x2f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x63, 0x43, 0x03, 0x00, 0x40 },
+ { 0x78, 0x58, 0x18, 0x00, 0x40 },
+ { 0x64, 0x44, 0x04, 0x00, 0x40 },
+ { 0x65, 0x45, 0x05, 0x00, 0x40 },
+ { 0x34, 0x24, 0x00, 0x00, 0x00 },
+ { 0x33, 0x23, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x20, 0x20, 0x20, 0x20, 0x00 },
+ { 0x76, 0x56, 0x16, 0x00, 0x40 },
+ { 0x66, 0x46, 0x06, 0x00, 0x40 },
+ { 0x74, 0x54, 0x14, 0x00, 0x40 },
+ { 0x72, 0x52, 0x12, 0x00, 0x40 },
+ { 0x35, 0x25, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x30 - 0x3f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x6e, 0x4e, 0x0e, 0x00, 0x40 },
+ { 0x62, 0x42, 0x02, 0x00, 0x40 },
+ { 0x68, 0x48, 0x08, 0x00, 0x40 },
+ { 0x67, 0x47, 0x07, 0x00, 0x40 },
+ { 0x79, 0x59, 0x19, 0x00, 0x40 },
+ { 0x36, 0x5e, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x6d, 0x4d, 0x0d, 0x00, 0x40 },
+ { 0x6a, 0x4a, 0x0a, 0x00, 0x40 },
+ { 0x75, 0x55, 0x15, 0x00, 0x40 },
+ { 0x37, 0x26, 0x00, 0x00, 0x00 },
+ { 0x38, 0x2a, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x40 - 0x4f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2c, 0x3c, 0x00, 0x00, 0x00 },
+ { 0x6b, 0x4b, 0x0b, 0x00, 0x40 },
+ { 0x69, 0x49, 0x09, 0x00, 0x40 },
+ { 0x6f, 0x4f, 0x0f, 0x00, 0x40 },
+ { 0x30, 0x29, 0x00, 0x00, 0x00 },
+ { 0x39, 0x28, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2e, 0x3e, 0x00, 0x00, 0x00 },
+ { 0x2f, 0x3f, 0x00, 0x00, 0x00 },
+ { 0x6c, 0x4c, 0x0c, 0x00, 0x40 },
+ { 0x3b, 0x3a, 0x00, 0x00, 0x00 },
+ { 0x70, 0x50, 0x10, 0x00, 0x40 },
+ { 0x2d, 0x5f, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x50 - 0x5f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x27, 0x40, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x5b, 0x7b, 0x00, 0x00, 0x00 },
+ { 0x3d, 0x2b, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0xa0 },
+ { 0x00, 0x00, 0x00, 0x00, 0x82 },
+ { 0x0d, 0x0d, 0x0d, 0x00, 0x00 },
+ { 0x5d, 0x7d, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x23, 0x7e, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x60 - 0x6f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x5c, 0x7c, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x08, 0x7f, 0x08, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x31, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x34, 0x00, 0x00, 0x00, 0x00 },
+ { 0x37, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x70 - 0x7f */
+ { 0x30, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2e, 0x00, 0x00, 0x00, 0x00 },
+ { 0x32, 0x00, 0x00, 0x00, 0x00 },
+ { 0x35, 0x00, 0x00, 0x00, 0x00 },
+ { 0x36, 0x00, 0x00, 0x00, 0x00 },
+ { 0x38, 0x00, 0x00, 0x00, 0x00 },
+ { 0x1b, 0x1b, 0x21b, 0x1b, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x90 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2b, 0x00, 0x00, 0x22b, 0x00 },
+ { 0x33, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2d, 0x00, 0x00, 0x22d, 0x00 },
+ { 0x2a, 0x00, 0x00, 0x00, 0x00 },
+ { 0x39, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x88 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x80 - 0x8f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x87, 0x97, 0x00, 0x487, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x90 - 0x9f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xa0 - 0xaf */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xb0 - 0xbf */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xc0 - 0xcf */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xd0 - 0xdf */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xe0 - 0xef */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0xf0 - 0xff */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+/* Define mappings for each possible code */
+
+key_struct E0keys[128] = {
+
+/* 0x00 - 0x0f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x10 - 0x1f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x84 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x81 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x20 - 0x2f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x30 - 0x3f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x40 - 0x4f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x2f, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x50 - 0x5f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x0d, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x60 - 0x6f */
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x10b, 0x00, 0x00, 0x20b, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x102, 0x00, 0x00, 0x202, 0x00 },
+ { 0x10a, 0x00, 0x00, 0x20a, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+
+/* 0x70 - 0x7f */
+ { 0x108, 0x00, 0x00, 0x208, 0x00 },
+ { 0x109, 0x00, 0x00, 0x209, 0x00 },
+ { 0x101, 0x105, 0x00, 0x201, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x103, 0x00, 0x00, 0x203, 0x00 },
+ { 0x100, 0x104, 0x00, 0x200, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x104, 0x100, 0x00, 0x204, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x105, 0x101, 0x00, 0x205, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00 },
+};
+
+/* Special keycodes */
+
+#define KEYCODE_UP 0x100
+#define KEYCODE_DOWN 0x101
+#define KEYCODE_LEFT 0x102
+#define KEYCODE_RIGHT 0x103
+#define KEYCODE_PGUP 0x104
+#define KEYCODE_PGDN 0x105
+#define KEYCODE_INSERT 0x108
+#define KEYCODE_DELETE 0x109
+#define KEYCODE_HOME 0x10a
+#define KEYCODE_END 0x10b
+
+/* Key modifiers flags */
+
+#define MODIFIER_CTRL 0x01
+#define MODIFIER_SHIFT 0x02
+#define MODIFIER_ALT 0x04
+#define MODIFIER_MASK 0x07
+
+#define MODIFIER_CAPS 0x20
+#define MODIFIER_NUM 0x10
+#define MODIFIER_SCROLL 0x08
+#define MODIFIER_LOCK_MASK 0x38
+
+#define MODIFIER_CAPSLOCK 0x40
+#define MODIFIER_NORETURN 0x80
+
+/* Keyboard buffer variables */
+
+#define BUFFER_SIZE 32
+#define RAWKBD_BSIZE 128
+
+static int autorepeatkey = -1;
+static struct kbd_autorepeat kbdautorepeat = { 5, 20 };
+static int rawkbd_device = 0;
+int modifiers = 0;
+static int kbd_ack = 0;
+static int kbd_resend = 0;
+
+extern int pmap_debug_level;
+
+struct kbd_softc {
+ struct device sc_device;
+ irqhandler_t sc_ih;
+
+ int sc_state;
+#define RAWKBD_OPEN 0x01
+#define KBD_OPEN 0x02
+#define RAWKBD_ASLEEP 0x04
+ int sc_iobase;
+ struct clist sc_q;
+ struct selinfo sc_rsel;
+ struct proc *sc_proc;
+};
+
+#define KBDUNIT(u) (minor(u) / 2)
+#define KBDFLAG(u) (minor(u) % 2)
+
+#define KBDFLAG_RAWUNIT 0
+#define KBDFLAG_CONUNIT 1
+
+int kbdprobe __P((struct device *, void *, void *));
+void kbdattach __P((struct device *, struct device *, void *));
+
+int kbdopen __P((dev_t, int, int, struct proc *));
+int kbdclose __P((dev_t, int, int, struct proc *));
+int kbdread __P((dev_t, struct uio *, int));
+int kbdselect __P((dev_t, int, struct proc *));
+int kbdioctl __P((dev_t, int, caddr_t, int, struct proc *));
+
+void kbdinit __P((struct kbd_softc *sc));
+void kbdsetleds __P((int /*leds*/));
+
+int PollKeyboard __P((int));
+int kbddecodekey __P((struct kbd_softc *, int));
+int kbdintr __P((struct kbd_softc *));
+
+void autorepeatstart __P((void *));
+void autorepeat __P((void *));
+
+struct cfattach kbd_ca = {
+ sizeof(struct kbd_softc), kbdprobe, kbdattach
+};
+
+struct cfdriver kbd_cd = {
+ NULL, "kbd", DV_TTY
+};
+
+
+int
+kbdprobe(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+/* struct mainbus_attach_args *mb = aux;*/
+ int id;
+
+/* Make sure we have an IOMD we understand */
+
+ id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+ switch (id) {
+ case RPC600_IOMD_ID:
+ case RC7500_IOC_ID:
+ return(1);
+ break;
+ default:
+ printf("kbd: Unknown IOMD id=%04x", id);
+ break;
+ }
+
+ return(0);
+}
+
+
+void
+kbdattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct kbd_softc *sc = (void *)self;
+ struct mainbus_attach_args *mb = aux;
+
+ sc->sc_iobase = mb->mb_iobase;
+
+ kbdinit(sc);
+
+ printf("\n");
+}
+
+
+int
+kbdopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct kbd_softc *sc;
+ int unit = KBDUNIT(dev);
+
+ if (unit >= kbd_cd.cd_ndevs)
+ return(ENXIO);
+
+ sc = kbd_cd.cd_devs[unit];
+
+ if (!sc) return(ENXIO);
+
+ switch (KBDFLAG(dev)) {
+ case KBDFLAG_RAWUNIT :
+ if (sc->sc_state & RAWKBD_OPEN)
+ return(EBUSY);
+ sc->sc_state |= RAWKBD_OPEN;
+ if (clalloc(&sc->sc_q, RAWKBD_BSIZE, 0) == -1)
+ return(ENOMEM);
+ sc->sc_proc = p;
+ rawkbd_device = 1;
+ break;
+ case KBDFLAG_CONUNIT :
+ if (sc->sc_state & KBD_OPEN)
+ return(EBUSY);
+ sc->sc_state |= KBD_OPEN;
+ break;
+ }
+
+/* Kill any active autorepeat */
+
+ untimeout(autorepeatstart, &autorepeatkey);
+ untimeout(autorepeat, &autorepeatkey);
+
+ return(0);
+}
+
+
+int
+kbdclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ int unit = KBDUNIT(dev);
+ struct kbd_softc *sc = kbd_cd.cd_devs[unit];
+
+ switch (KBDFLAG(dev)) {
+ case KBDFLAG_RAWUNIT :
+ if (!(sc->sc_state & RAWKBD_OPEN))
+ return(EINVAL);
+ sc->sc_state &= ~RAWKBD_OPEN;
+ clfree(&sc->sc_q);
+ sc->sc_proc = NULL;
+ rawkbd_device = 0;
+ break;
+ case KBDFLAG_CONUNIT :
+ if (!(sc->sc_state & KBD_OPEN))
+ return(EINVAL);
+ sc->sc_state &= ~KBD_OPEN;
+ break;
+ }
+
+ return(0);
+}
+
+
+int
+kbdread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct kbd_softc *sc = kbd_cd.cd_devs[KBDUNIT(dev)];
+ int s;
+ int error = 0;
+ size_t length;
+ u_char buffer[128];
+
+ if (KBDFLAG(dev) == KBDFLAG_CONUNIT)
+ return(ENXIO);
+
+ /* Block until keyboard activity occured. */
+
+ s = spltty();
+ while (sc->sc_q.c_cc == 0) {
+ if (flag & IO_NDELAY) {
+ splx(s);
+ return EWOULDBLOCK;
+ }
+ sc->sc_state |= RAWKBD_ASLEEP;
+ if ((error = tsleep((caddr_t)sc, PZERO | PCATCH, "kbdread", 0))) {
+ sc->sc_state &= (~RAWKBD_ASLEEP);
+ splx(s);
+ return error;
+ }
+ }
+ splx(s);
+
+ /* Transfer as many chunks as possible. */
+
+ while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
+ length = min(sc->sc_q.c_cc, uio->uio_resid);
+ if (length > sizeof(buffer))
+ length = sizeof(buffer);
+
+ /* Remove a small chunk from the input queue. */
+ (void) q_to_b(&sc->sc_q, buffer, length);
+
+ /* Copy the data to the user process. */
+ if ((error = (uiomove(buffer, length, uio))))
+ break;
+ }
+ return error;
+}
+
+int
+kbdselect(dev, rw, p)
+ dev_t dev;
+ int rw;
+ struct proc *p;
+{
+ struct kbd_softc *sc = kbd_cd.cd_devs[KBDUNIT(dev)];
+ int s;
+ int ret;
+
+ if (KBDFLAG(dev) == KBDFLAG_CONUNIT)
+ return(ENXIO);
+
+ if (rw == FWRITE)
+ return 0;
+
+ s = spltty();
+ if (!sc->sc_q.c_cc) {
+ selrecord(p, &sc->sc_rsel);
+ ret = 0;
+ } else
+ ret = 1;
+ splx(s);
+ return ret;
+}
+
+
+int
+kbdioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+/* struct kbd_softc *sc = kbd_cd.cd_devs[KBDUNIT(dev)];*/
+ struct kbd_autorepeat *kbdar = (void *)data;
+ int *leds = (int *)data;
+ int s;
+
+ switch (cmd) {
+ case KBD_GETAUTOREPEAT:
+/* if (KBDFLAG(dev) == KBDFLAG_RAWUNIT)
+ return(EINVAL);*/
+
+ *kbdar = kbdautorepeat;
+ break;
+ case KBD_SETAUTOREPEAT:
+/* if (KBDFLAG(dev) == KBDFLAG_RAWUNIT)
+ return(EINVAL);*/
+ s = spltty();
+ kbdautorepeat = *kbdar;
+ if (kbdautorepeat.ka_rate < 1)
+ kbdautorepeat.ka_rate = 1;
+ if (kbdautorepeat.ka_rate > 50)
+ kbdautorepeat.ka_rate = 50;
+ if (kbdautorepeat.ka_delay > 50)
+ kbdautorepeat.ka_delay = 50;
+ if (kbdautorepeat.ka_delay < 1)
+ kbdautorepeat.ka_delay = 1;
+ (void)splx(s);
+ break;
+ case KBD_SETLEDS:
+ kbdsetleds(*leds);
+ break;
+ default:
+ return(ENXIO);
+ }
+ return(0);
+}
+
+
+void
+kbdsetleds(leds)
+ int leds;
+{
+ int loop;
+
+ if ((ReadByte(IOMD_KBDCR) & 0x80)) {
+ WriteByte(IOMD_KBDDAT, 0xed);
+ loop = 10000;
+ while ((ReadByte(IOMD_KBDCR) & 0x40) && loop > 0)
+ --loop;
+ if ((ReadByte(IOMD_KBDCR) & 0x80)) {
+ WriteByte(IOMD_KBDDAT, leds);
+ loop = 10000;
+ while ((ReadByte(IOMD_KBDCR) & 0x40) && loop > 0)
+ --loop;
+ }
+ }
+}
+
+
+void
+kbdsetstate(state)
+ int state;
+{
+ modifiers = state & MODIFIER_LOCK_MASK;
+}
+
+
+int
+kdbgetstate()
+{
+ return(modifiers);
+}
+
+
+void
+kbdinit(sc)
+ struct kbd_softc *sc;
+{
+ sc->sc_ih.ih_func = kbdintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_TTY;
+ sc->sc_ih.ih_name = "kbd rx";
+ if (irq_claim(IRQ_KBDRX, &sc->sc_ih))
+ panic("Cannot claim IRQ for kbd%d\n", sc->sc_device.dv_unit);
+
+ modifiers = 0;
+ kbdsetleds((modifiers >> 3) & 7);
+}
+
+
+int
+getkey_polled()
+{
+ int code;
+ int key;
+ int up;
+ key_struct *ks;
+ int s;
+
+ s = splhigh();
+
+ key = 0;
+
+ do {
+ while ((ReadByte(IOMD_KBDCR) & (1<<5)) == 0) ;
+
+/* Read the IOMD keyboard register and process the key */
+
+ code = PollKeyboard(ReadByte(IOMD_KBDDAT));
+
+ if (code != 0) {
+ up = (code & 0x100);
+ key = code & 0xff;
+
+/* printf("code=%04x mod=%04x\n", code, modifiers);*/
+
+/* By default we use the main keycode lookup table */
+
+ ks = keys;
+
+/* If we have an E0 or E1 sqeuence we use the extended table */
+
+ if (code > 0x1ff)
+ ks = E0keys;
+
+/* Is the key a temporary modifier ? */
+
+ if (ks[key].flags & MODIFIER_MASK) {
+ if (up)
+ modifiers &= ~ks[key].flags;
+ else
+ modifiers |= ks[key].flags;
+ key = 0;
+ continue;
+ }
+
+/* Is the key a locking modifier ? */
+
+ if (ks[key].flags & MODIFIER_LOCK_MASK) {
+ if (!up) {
+ modifiers ^= ks[key].flags;
+ kbdsetleds((modifiers >> 3) & 7);
+ }
+ key = 0;
+ continue;
+ }
+
+/* Lookup the correct key code */
+
+ if (modifiers & 0x01)
+ key = ks[key].ctrl_code;
+ else if (modifiers & 0x02)
+ key = ks[key].shift_code;
+ else if (modifiers & 0x04)
+ key = ks[key].alt_code;
+ else
+ key = ks[key].base_code;
+
+ if (modifiers & MODIFIER_CAPS) {
+ if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z'))
+ key ^= 0x20;
+ }
+
+ if (up)
+ key = 0;
+ if (!up && key >= 0x200) {
+
+#if (NVT > 0)
+ if ((key & ~0x0f) == 0x480)
+ console_switch((key & 0x0f) - 1);
+ else
+#endif
+ switch (key) {
+#if (NVT > 0)
+ case 0x201:
+ console_scrollforward();
+ break;
+ case 0x200:
+ console_scrollback();
+ break;
+#endif
+ default:
+ break;
+ }
+ key = 0;
+ }
+ }
+ } while (key == 0);
+
+ if (key == '\r')
+ key = '\n';
+
+ splx(s);
+ return(key);
+}
+
+
+/* Keyboard IRQ handler */
+
+int
+kbdintr(sc)
+ struct kbd_softc *sc;
+{
+ int key;
+
+/* Read the IOMD keyboard register and process the key */
+
+ key = PollKeyboard(ReadByte(IOMD_KBDDAT));
+
+/* If we have a raw keycode convert it to an ASCII code */
+
+ if (key != 0)
+ kbddecodekey(sc, key);
+ return(1);
+}
+
+
+/* Flags used to decode the raw keys */
+
+#define FLAG_KEYUP 0x01
+#define FLAG_E0 0x02
+#define FLAG_E1 0x04
+
+static int flags = 0;
+
+/*
+ * This function is now misnamed.
+ * It processes the raw key codes from the keyboard and generates
+ * a unique code that can be decoded with the key translation array.
+ */
+
+int
+PollKeyboard(code)
+ int code;
+{
+/* printf("%02x.", code);*/
+
+/*
+ * Set the keyup flag if this is the release code.
+ */
+
+ if (code == 0xf0) {
+ flags |= FLAG_KEYUP;
+ return(0);
+ }
+
+/* If it is a special code ignore it */
+
+ if (code == 0xff || code == 0x00) {
+ flags = 0;
+ return(0);
+ }
+
+/* If it is a resend code note it down */
+
+ if (code == 0xfe) {
+ printf("kbd:resend\n");
+ kbd_resend = 1;
+ return(0);
+ }
+
+/* If it is an ack code note it down */
+
+ if (code == 0xfa) {
+/* printf("kbd:ack\n");*/
+ kbd_ack = 1;
+ return(0);
+ }
+
+/* Flag the start of an E0 sequence. */
+
+ if (code == 0xe0) {
+ flags |= FLAG_E0;
+ return(0);
+ }
+
+/* Flag the start of an E1 sequence. */
+
+ if (code == 0xe1) {
+ flags |= FLAG_E1;
+ return(0);
+ }
+
+/* Ignore any other invalid codes */
+
+ if (code > 0x8f) {
+ flags = 0;
+ return(0);
+ }
+
+/* printf("%02x:%02x.", code, flags);*/
+
+/* Mark the code appropriately if it is part of an E0 sequence */
+
+ if (flags & FLAG_E0) {
+ flags &= ~FLAG_E0;
+ if (code == 0x12) {
+ flags &= ~FLAG_KEYUP;
+ return(0);
+ }
+ code |= 0x200;
+ }
+
+/* Mark the key if it is the upcode */
+
+ if (flags & FLAG_KEYUP) {
+ flags &= ~FLAG_KEYUP;
+ code |= 0x100;
+ }
+
+/* Mark the code appropriately if it is part of an E1 sequence */
+
+ if (flags & FLAG_E1) {
+ if ((code & 0xff) == 0x14) {
+ return(0);
+ }
+ flags &= ~FLAG_E1;
+ code |= 0x400;
+ flags &= ~FLAG_KEYUP;
+ }
+
+ return(code);
+}
+
+
+/*
+ * This routine decodes the unique keycode and generates an ASCII code
+ * if necessary.
+ */
+
+int
+kbddecodekey(sc, code)
+ struct kbd_softc *sc;
+ int code;
+{
+ key_struct *ks;
+ int up;
+ int key;
+
+ console_unblank();
+
+/* Do we have the raw kbd device open ... */
+
+ if (rawkbd_device == 1 && code != 0) {
+ struct kbd_data buffer;
+ int s;
+
+ /* Add this event to the queue. */
+
+ buffer.keycode = code;
+ microtime(&buffer.event_time);
+ s=spltty();
+ (void) b_to_q((char *)&buffer, sizeof(buffer), &sc->sc_q);
+ splx(s);
+ selwakeup(&sc->sc_rsel);
+
+ if (sc->sc_state & RAWKBD_ASLEEP) {
+ sc->sc_state &= ~RAWKBD_ASLEEP;
+ wakeup((caddr_t)sc);
+ }
+
+ psignal(sc->sc_proc, SIGIO);
+ return(1);
+ }
+
+ up = (code & 0x100);
+ key = code & 0xff;
+
+/* By default we use the main keycode lookup table */
+
+ ks = keys;
+
+/* If we have an E0 or E1 sqeuence we use the extended table */
+
+ if (code > 0x1ff)
+ ks = E0keys;
+
+/* Is the key a temporary modifier ? */
+
+ if (ks[key].flags & MODIFIER_MASK) {
+ if (up)
+ modifiers &= ~ks[key].flags;
+ else
+ modifiers |= ks[key].flags;
+ return(0);
+ }
+
+/* Is the key a locking modifier ? */
+
+ if (ks[key].flags & MODIFIER_LOCK_MASK) {
+ if (!up) {
+ modifiers ^= ks[key].flags;
+ kbdsetleds((modifiers >> 3) & 7);
+ }
+ return(0);
+ }
+
+/* Lookup the correct key code */
+
+ if (modifiers & 0x01)
+ key = ks[key].ctrl_code;
+ else if (modifiers & 0x02)
+ key = ks[key].shift_code;
+ else if (modifiers & 0x04)
+ key = ks[key].alt_code;
+ else
+ key = ks[key].base_code;
+
+ if (modifiers & MODIFIER_CAPS) {
+ if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z'))
+ key ^= 0x20;
+ }
+
+/* If no valid code the key is not yet mapped so report error */
+
+#ifdef DEBUG_TERM
+/* if (key == 0) {
+ char err[80];
+
+ sprintf(err, "\n\rUnknown keycode %04x\n\r", code);
+ dprintf(err);
+
+ }*/
+#endif
+
+/* If we have an ASCII code insert it into the keyboard buffer */
+
+ if (!up && key != 0) {
+ if (key >= 0x200) {
+
+ untimeout(autorepeatstart, &autorepeatkey);
+ untimeout(autorepeat, &autorepeatkey);
+ autorepeatkey = -1;
+#if (NVT > 0)
+ if ((key & ~0x0f) == 0x480)
+ console_switch((key & 0x0f) - 1);
+ else
+#endif
+ switch (key) {
+ case 0x22b:
+ pmap_debug(pmap_debug_level + 1);
+ break;
+ case 0x22d:
+ pmap_debug(pmap_debug_level - 1);
+ break;
+#if (NVT > 0)
+ case 0x201:
+ console_scrollforward();
+ break;
+ case 0x200:
+ console_scrollback();
+ break;
+ case 0x202:
+ console_switchdown();
+ break;
+ case 0x203:
+ console_switchup();
+ break;
+#endif
+ case 0x204:
+ --kbdautorepeat.ka_rate;
+ if (kbdautorepeat.ka_rate < 1)
+ kbdautorepeat.ka_rate = 1;
+ break;
+ case 0x205:
+ ++kbdautorepeat.ka_rate;
+ if (kbdautorepeat.ka_rate > 50)
+ kbdautorepeat.ka_rate = 50;
+ break;
+ case 0x20a:
+ ++kbdautorepeat.ka_delay;
+ if (kbdautorepeat.ka_delay > 50)
+ kbdautorepeat.ka_delay = 50;
+ break;
+ case 0x20b:
+ --kbdautorepeat.ka_delay;
+ if (kbdautorepeat.ka_delay < 1)
+ kbdautorepeat.ka_delay = 1;
+ break;
+#ifdef DDB
+ case 0x208:
+ Debugger();
+ break;
+#endif
+ case 0x21b:
+ printf("Kernel interruption\n");
+ boot(RB_HALT);
+ break;
+ case 0x209:
+ printf("Kernel interruption - nosync\n");
+ boot(RB_NOSYNC | RB_HALT);
+ break;
+
+ default:
+ printf("Special key %04x\n", key);
+ break;
+ }
+ } else {
+ if (physconkbd(key) == 0 && rawkbd_device == 0) {
+ if (autorepeatkey != key) {
+ untimeout(autorepeatstart, &autorepeatkey);
+ untimeout(autorepeat, &autorepeatkey);
+ autorepeatkey = key;
+ timeout(autorepeatstart, &autorepeatkey, hz/kbdautorepeat.ka_delay);
+ }
+ }
+
+ return(1);
+ }
+ } else {
+ untimeout(autorepeatstart, &autorepeatkey);
+ untimeout(autorepeat, &autorepeatkey);
+ autorepeatkey = -1;
+ }
+ return(0);
+}
+
+
+void
+autorepeatstart(key)
+ void *key;
+{
+ physconkbd(*((int *)key));
+ timeout(autorepeat, key, hz/kbdautorepeat.ka_rate);
+}
+
+
+void
+autorepeat(key)
+ void *key;
+{
+ physconkbd(*((int *)key));
+ timeout(autorepeat, key, hz/kbdautorepeat.ka_rate);
+}
+
+/* End of kbd.c */
--- /dev/null
+/* $NetBSD: lpt.c,v 1.6 1996/03/28 21:52:47 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * Copyright (c) 1993, 1994 Charles Hannum.
+ * Copyright (c) 1990 William F. Jolitz, TeleMuse
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This software is a component of "386BSD" developed by
+ * William F. Jolitz, TeleMuse.
+ * 4. Neither the name of the developer nor the name "386BSD"
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
+ * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
+ * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
+ * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
+ * NOT MAKE USE OF THIS WORK.
+ *
+ * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
+ * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
+ * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
+ * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
+ * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
+ * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
+ * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
+ * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from:$NetBSD: lpt.c,v 1.6 1996/03/28 21:52:47 mark Exp $
+ */
+
+/*
+ * Device Driver for AT parallel printer port
+ */
+/*
+ * PLIP driver code added by Mark Brinicombe
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/buf.h>
+#include <sys/kernel.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/device.h>
+#include <sys/syslog.h>
+
+#if defined(INET) && defined(PLIP)
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <sys/time.h>
+#include <net/bpf.h>
+#endif
+#endif
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/irqhandler.h>
+#include <machine/io.h>
+#include <arm32/mainbus/lptreg.h>
+#include <arm32/mainbus/mainbus.h>
+
+#define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */
+#define STEP hz/4
+
+#define LPTPRI (PZERO+8)
+#define LPT_BSIZE 1024
+
+#if defined(INET) && defined(PLIP)
+#ifndef PLIPMTU /* MTU for the plip# interfaces */
+#if defined(COMPAT_PLIP10)
+#define PLIPMTU 1600
+#else
+#define PLIPMTU (ETHERMTU - ifp->if_hdrlen)
+#endif
+#endif
+
+#ifndef PLIPMXSPIN1 /* DELAY factor for the plip# interfaces */
+#define PLIPMXSPIN1 2000 /* Spinning for remote intr to happen */
+#endif
+
+#ifndef PLIPMXSPIN2 /* DELAY factor for the plip# interfaces */
+#define PLIPMXSPIN2 6000 /* Spinning for remote handshake to happen */
+#endif
+
+#ifndef PLIPMXERRS /* Max errors before !RUNNING */
+#define PLIPMXERRS 100
+#endif
+#ifndef PLIPMXRETRY
+#define PLIPMXRETRY 10 /* Max number of retransmits */
+#endif
+#ifndef PLIPRETRY
+#define PLIPRETRY hz/10 /* Time between retransmits */
+#endif
+#endif
+
+#if !defined(DEBUG) || !defined(notdef)
+#define lprintf
+#else
+#define lprintf if (lptdebug) printf
+int lptdebug = 1;
+#endif
+
+struct lpt_softc {
+ struct device sc_dev;
+ irqhandler_t sc_ih;
+
+ size_t sc_count;
+ struct buf *sc_inbuf;
+ u_char *sc_cp;
+ int sc_spinmax;
+ int sc_iobase;
+ int sc_irq;
+ u_char sc_state;
+#define LPT_OPEN 0x01 /* device is open */
+#define LPT_OBUSY 0x02 /* printer is busy doing output */
+#define LPT_INIT 0x04 /* waiting to initialize for open */
+#define LPT_PLIP 0x08 /* busy with PLIP */
+ u_char sc_flags;
+#define LPT_AUTOLF 0x20 /* automatic LF on CR */
+#define LPT_NOPRIME 0x40 /* don't prime on open */
+#define LPT_NOINTR 0x80 /* do not use interrupt */
+ u_char sc_control;
+ u_char sc_laststatus;
+#if defined(INET) && defined(PLIP)
+ struct arpcom sc_arpcom;
+ u_char *sc_ifbuf;
+ int sc_iferrs;
+ int sc_ifretry;
+#if defined(COMPAT_PLIP10)
+ u_char sc_adrcksum;
+#endif
+#endif
+};
+
+int lptprobe __P((struct device *, void *, void *));
+void lptattach __P((struct device *, struct device *, void *));
+int lptintr __P((void *));
+
+#if defined(INET) && defined(PLIP)
+/* Functions for the plip# interface */
+static void plipattach(struct lpt_softc *,int);
+static int plipioctl(struct ifnet *, u_long, caddr_t);
+static void plipstart(struct ifnet *);
+static int plipintr(struct lpt_softc *);
+#endif
+
+struct cfattach lpt_ca = {
+ sizeof(struct lpt_softc), lptprobe, lptattach
+};
+
+struct cfdriver lpt_cd = {
+ NULL, "lpt", DV_TTY
+};
+
+#define LPTUNIT(s) (minor(s) & 0x1f)
+#define LPTFLAGS(s) (minor(s) & 0xe0)
+
+#define LPS_INVERT (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK)
+#define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK|LPS_NOPAPER)
+#define NOT_READY() ((inb(iobase + lpt_status) ^ LPS_INVERT) & LPS_MASK)
+#define NOT_READY_ERR() not_ready(inb(iobase + lpt_status), sc)
+static int not_ready __P((u_char, struct lpt_softc *));
+
+static void lptwakeup __P((void *arg));
+static int pushbytes __P((struct lpt_softc *));
+
+/*
+ * Internal routine to lptprobe to do port tests of one byte value.
+ */
+int
+lpt_port_test(port, data, mask)
+ int port;
+ u_char data, mask;
+{
+ int timeout;
+ u_char temp;
+
+ data &= mask;
+ outb(port, data);
+ timeout = 1000;
+ do {
+ delay(10);
+ temp = inb(port) & mask;
+ } while (temp != data && --timeout);
+ lprintf("lpt: port=0x%x out=0x%x in=0x%x timeout=%d\n", port, data,
+ temp, timeout);
+ return (temp == data);
+}
+
+/*
+ * Logic:
+ * 1) You should be able to write to and read back the same value
+ * to the data port. Do an alternating zeros, alternating ones,
+ * walking zero, and walking one test to check for stuck bits.
+ *
+ * 2) You should be able to write to and read back the same value
+ * to the control port lower 5 bits, the upper 3 bits are reserved
+ * per the IBM PC technical reference manauls and different boards
+ * do different things with them. Do an alternating zeros, alternating
+ * ones, walking zero, and walking one test to check for stuck bits.
+ *
+ * Some printers drag the strobe line down when the are powered off
+ * so this bit has been masked out of the control port test.
+ *
+ * XXX Some printers may not like a fast pulse on init or strobe, I
+ * don't know at this point, if that becomes a problem these bits
+ * should be turned off in the mask byte for the control port test.
+ *
+ * 3) Set the data and control ports to a value of 0
+ */
+int
+lptprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct mainbus_attach_args *mb = aux;
+ int iobase = mb->mb_iobase;
+ int port;
+ u_char mask, data;
+ int i;
+
+#ifdef DEBUG
+#define ABORT do {printf("lptprobe: mask %x data %x failed\n", mask, data); \
+ return 0;} while (0)
+#else
+#define ABORT return 0
+#endif
+
+ port = iobase + lpt_data;
+ mask = 0xff;
+
+ data = 0x55; /* Alternating zeros */
+ if (!lpt_port_test(port, data, mask))
+ ABORT;
+
+ data = 0xaa; /* Alternating ones */
+ if (!lpt_port_test(port, data, mask))
+ ABORT;
+
+ for (i = 0; i < CHAR_BIT; i++) { /* Walking zero */
+ data = ~(1 << i);
+ if (!lpt_port_test(port, data, mask))
+ ABORT;
+ }
+
+ for (i = 0; i < CHAR_BIT; i++) { /* Walking one */
+ data = (1 << i);
+ if (!lpt_port_test(port, data, mask))
+ ABORT;
+ }
+
+ outb(iobase + lpt_data, 0);
+ outb(iobase + lpt_control, 0);
+
+ mb->mb_iosize = LPT_NPORTS;
+ return 1;
+}
+
+void
+lptattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct lpt_softc *sc = (void *)self;
+ struct mainbus_attach_args *mb = aux;
+ int iobase = mb->mb_iobase;
+
+ if (mb->mb_irq != IRQUNK)
+ printf("\n");
+ else
+ printf(": polled\n");
+
+ sc->sc_iobase = iobase;
+ sc->sc_irq = mb->mb_irq;
+ sc->sc_state = 0;
+ outb(iobase + lpt_control, LPC_NINIT);
+
+ if (mb->mb_irq != IRQUNK) {
+ sc->sc_ih.ih_func = lptintr;
+ sc->sc_ih.ih_arg = sc;
+#if defined(INET) && defined(PLIP)
+ sc->sc_ih.ih_level = IPL_NET;
+ sc->sc_ih.ih_name = "lpt/plip";
+ plipattach(sc, self->dv_unit);
+#else
+ sc->sc_ih.ih_level = IPL_NONE;
+ sc->sc_ih.ih_name = "lpt";
+#endif
+ if (irq_claim(mb->mb_irq, &sc->sc_ih))
+ panic("Cannot claim IRQ %d for lpt%d\n", mb->mb_irq, sc->sc_dev.dv_unit);
+
+ }
+#if defined(INET) && defined(PLIP)
+ else {
+ printf("Warning PLIP device needs IRQ driven lpt driver\n");
+ }
+#endif
+}
+
+/*
+ * Reset the printer, then wait until it's selected and not busy.
+ */
+int
+lptopen(dev, flag)
+ dev_t dev;
+ int flag;
+{
+ int unit = LPTUNIT(dev);
+ u_char flags = LPTFLAGS(dev);
+ struct lpt_softc *sc;
+ int iobase;
+ u_char control;
+ int error;
+ int spin;
+
+ if (unit >= lpt_cd.cd_ndevs)
+ return ENXIO;
+ sc = lpt_cd.cd_devs[unit];
+ if (!sc)
+ return ENXIO;
+
+ if (sc->sc_irq == IRQUNK && (flags & LPT_NOINTR) == 0)
+ return ENXIO;
+
+#ifdef DIAGNOSTIC
+ if (sc->sc_state)
+ printf("%s: stat=0x%x not zero\n", sc->sc_dev.dv_xname,
+ sc->sc_state);
+#endif
+
+ if (sc->sc_state)
+ return EBUSY;
+
+ sc->sc_state = LPT_INIT;
+ sc->sc_flags = flags;
+ lprintf("%s: open: flags=0x%x\n", sc->sc_dev.dv_xname, flags);
+ iobase = sc->sc_iobase;
+
+ if ((flags & LPT_NOPRIME) == 0) {
+ /* assert INIT for 100 usec to start up printer */
+ outb(iobase + lpt_control, LPC_SELECT);
+ delay(100);
+ }
+
+ control = LPC_SELECT | LPC_NINIT;
+ outb(iobase + lpt_control, control);
+
+ /* wait till ready (printer running diagnostics) */
+ for (spin = 0; NOT_READY_ERR(); spin += STEP) {
+ if (spin >= TIMEOUT) {
+ sc->sc_state = 0;
+ return EBUSY;
+ }
+
+ /* wait 1/4 second, give up if we get a signal */
+ if (error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptopen",
+ STEP) != EWOULDBLOCK) {
+ sc->sc_state = 0;
+ return error;
+ }
+ }
+
+ if ((flags & LPT_NOINTR) == 0)
+ control |= LPC_IENABLE;
+ if (flags & LPT_AUTOLF)
+ control |= LPC_AUTOLF;
+ sc->sc_control = control;
+ outb(iobase + lpt_control, control);
+
+ sc->sc_inbuf = geteblk(LPT_BSIZE);
+ sc->sc_count = 0;
+ sc->sc_state = LPT_OPEN;
+
+ if ((sc->sc_flags & LPT_NOINTR) == 0)
+ lptwakeup(sc);
+
+ lprintf("%s: opened\n", sc->sc_dev.dv_xname);
+ return 0;
+}
+
+int
+not_ready(status, sc)
+ u_char status;
+ struct lpt_softc *sc;
+{
+ u_char new;
+
+ status = (status ^ LPS_INVERT) & LPS_MASK;
+ new = status & ~sc->sc_laststatus;
+ sc->sc_laststatus = status;
+
+ if (new & LPS_SELECT)
+ log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname);
+ else if (new & LPS_NOPAPER)
+ log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname);
+ else if (new & LPS_NERR)
+ log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname);
+
+ return status;
+}
+
+
+void
+lptwakeup(arg)
+ void *arg;
+{
+ struct lpt_softc *sc = arg;
+ int s;
+
+ s = spltty();
+ lptintr(sc);
+ splx(s);
+
+ timeout(lptwakeup, sc, STEP);
+}
+
+/*
+ * Close the device, and free the local line buffer.
+ */
+lptclose(dev, flag)
+ dev_t dev;
+ int flag;
+{
+ int unit = LPTUNIT(dev);
+ struct lpt_softc *sc = lpt_cd.cd_devs[unit];
+ int iobase = sc->sc_iobase;
+
+ if (sc->sc_count)
+ (void) pushbytes(sc);
+
+ if ((sc->sc_flags & LPT_NOINTR) == 0)
+ untimeout(lptwakeup, sc);
+
+ outb(iobase + lpt_control, LPC_NINIT);
+ sc->sc_state = 0;
+ outb(iobase + lpt_control, LPC_NINIT);
+ brelse(sc->sc_inbuf);
+
+ lprintf("%s: closed\n", sc->sc_dev.dv_xname);
+ return 0;
+}
+
+int
+pushbytes(sc)
+ struct lpt_softc *sc;
+{
+ int iobase = sc->sc_iobase;
+ int error;
+
+ if (sc->sc_flags & LPT_NOINTR) {
+ int spin, tic;
+ u_char control = sc->sc_control;
+
+ while (sc->sc_count > 0) {
+ spin = 0;
+ while (NOT_READY()) {
+ if (++spin < sc->sc_spinmax)
+ continue;
+ tic = 0;
+ /* adapt busy-wait algorithm */
+ sc->sc_spinmax++;
+ while (NOT_READY_ERR()) {
+ /* exponential backoff */
+ tic = tic + tic + 1;
+ if (tic > TIMEOUT)
+ tic = TIMEOUT;
+ error = tsleep((caddr_t)sc,
+ LPTPRI | PCATCH, "lptpsh", tic);
+ if (error != EWOULDBLOCK)
+ return error;
+ }
+ break;
+ }
+
+ outb(iobase + lpt_data, *sc->sc_cp++);
+ outb(iobase + lpt_control, control | LPC_STROBE);
+ sc->sc_count--;
+ outb(iobase + lpt_control, control);
+
+ /* adapt busy-wait algorithm */
+ if (spin*2 + 16 < sc->sc_spinmax)
+ sc->sc_spinmax--;
+ }
+ } else {
+ int s;
+
+ while (sc->sc_count > 0) {
+ /* if the printer is ready for a char, give it one */
+ if ((sc->sc_state & LPT_OBUSY) == 0) {
+ lprintf("%s: write %d\n", sc->sc_dev.dv_xname,
+ sc->sc_count);
+ s = spltty();
+ (void) lptintr(sc);
+ splx(s);
+ }
+ if (error = tsleep((caddr_t)sc, LPTPRI | PCATCH,
+ "lptwrite2", 0))
+ return error;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Copy a line from user space to a local buffer, then call putc to get the
+ * chars moved to the output queue.
+ */
+lptwrite(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+ struct lpt_softc *sc = lpt_cd.cd_devs[LPTUNIT(dev)];
+ size_t n;
+ int error = 0;
+
+ while (n = min(LPT_BSIZE, uio->uio_resid)) {
+ uiomove(sc->sc_cp = sc->sc_inbuf->b_data, n, uio);
+ sc->sc_count = n;
+ error = pushbytes(sc);
+ if (error) {
+ /*
+ * Return accurate residual if interrupted or timed
+ * out.
+ */
+ uio->uio_resid += sc->sc_count;
+ sc->sc_count = 0;
+ return error;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Handle printer interrupts which occur when the printer is ready to accept
+ * another char.
+ */
+int
+lptintr(arg)
+ void *arg;
+{
+ struct lpt_softc *sc = arg;
+ int iobase = sc->sc_iobase;
+
+/*printf("lptintr:\n");*/
+
+#if defined(INET) && defined(PLIP)
+ if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) {
+ return(plipintr(sc));
+ }
+#endif
+
+#if 0
+ if ((sc->sc_state & LPT_OPEN) == 0)
+ return 0;
+#endif
+
+ /* is printer online and ready for output */
+ if (NOT_READY() && NOT_READY_ERR())
+ return 0;
+
+ if (sc->sc_count) {
+ u_char control = sc->sc_control;
+ /* send char */
+ outb(iobase + lpt_data, *sc->sc_cp++);
+ outb(iobase + lpt_control, control | LPC_STROBE);
+ sc->sc_count--;
+ outb(iobase + lpt_control, control);
+ sc->sc_state |= LPT_OBUSY;
+ } else
+ sc->sc_state &= ~LPT_OBUSY;
+
+ if (sc->sc_count == 0) {
+ /* none, wake up the top half to get more */
+ wakeup((caddr_t)sc);
+ }
+
+ return(1);
+}
+
+int
+lptioctl(dev, cmd, data, flag)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+{
+ int error = 0;
+
+ switch (cmd) {
+ default:
+ error = ENODEV;
+ }
+
+ return error;
+}
+
+
+#if defined(INET) && defined(PLIP)
+
+#define PLIP_INTR_ENABLE (LPC_NINIT | LPC_SELECT | LPC_IENABLE)
+#define PLIP_INTR_DISABLE (LPC_NINIT | LPC_SELECT)
+#define PLIP_DATA (iobase + lpt_data)
+#define PLIP_STATUS (iobase + lpt_status)
+#define PLIP_CONTROL (iobase + lpt_control)
+#define PLIP_REMOTE_TRIGGER 0x08
+#define PLIP_DELAY_UNIT 50
+#if PLIP_DELAY_UNIT > 0
+#define PLIP_DELAY DELAY(PLIP_DELAY_UNIT)
+#else
+#define PLIP_DELAY
+#endif
+#define PLIP_DEBUG_RX 0x01
+#define PLIP_DEBUG_TX 0x02
+#define PLIP_DEBUG_IF 0x04
+#define PLIP_DEBUG 0x07
+#if PLIP_DEBUG != 0
+static int plip_debug = PLIP_DEBUG;
+#endif
+
+static void
+plipattach(struct lpt_softc *sc, int unit)
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+
+ sc->sc_ifbuf = NULL;
+ ifp->if_unit = unit;
+ ifp->if_name = "plip";
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
+ ifp->if_output = ether_output;
+ ifp->if_start = plipstart;
+ ifp->if_ioctl = plipioctl;
+ ifp->if_watchdog = 0;
+
+ ifp->if_type = IFT_ETHER;
+ ifp->if_addrlen = 6;
+ ifp->if_hdrlen = 14;
+ ifp->if_mtu = PLIPMTU;
+
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+ printf("plip%d at lpt%d: mtu=%d,%d,%d", unit, unit, (int) ifp->if_mtu,
+ ifp->if_hdrlen, ifp->if_addrlen);
+ if (sizeof(struct ether_header) != 14)
+ printf(" ethhdr super kludge mode enabled\n");
+ else
+ printf("\n");
+
+#if NBPFILTER > 0
+ bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+}
+
+/*
+ * Process an ioctl request.
+ */
+static int
+plipioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct proc *p = curproc;
+ struct lpt_softc *sc = (struct lpt_softc *) lpt_cd.cd_devs[ifp->if_unit];
+ unsigned int iobase = sc->sc_iobase;
+ struct ifaddr *ifa = (struct ifaddr *)data;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int s;
+ int error = 0;
+
+#if PLIP_DEBUG > 0
+ printf("plipioctl: cmd=%08x ifp=%08x data=%08x\n", cmd, ifp, data);
+ printf("plipioctl: ifp->flags=%08x\n", ifp->if_flags);
+#endif
+
+ switch (cmd) {
+
+ case SIOCSIFFLAGS:
+ if (((ifp->if_flags & IFF_UP) == 0) &&
+ (ifp->if_flags & IFF_RUNNING)) {
+ ifp->if_flags &= ~IFF_RUNNING;
+/* Deactive the parallel port */
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_IF)
+ printf("plip: Disabling lpt irqs\n");
+#endif
+ outb(PLIP_DATA, 0x00);
+ outb(PLIP_CONTROL, PLIP_INTR_DISABLE);
+ sc->sc_state = 0;
+
+ if (sc->sc_ifbuf)
+ free(sc->sc_ifbuf, M_DEVBUF);
+
+ sc->sc_ifbuf = NULL;
+ }
+ if (((ifp->if_flags & IFF_UP)) &&
+ ((ifp->if_flags & IFF_RUNNING) == 0)) {
+ if (sc->sc_state) {
+ error = EBUSY;
+ break;
+ }
+/* if (!(ifp->if_flags & IFF_DEBUG))
+ plip_debug = PLIP_DEBUG;
+ else
+ plip_debug = 0;*/
+ sc->sc_state = LPT_OPEN | LPT_PLIP;
+ if (!sc->sc_ifbuf)
+ sc->sc_ifbuf =
+ malloc(ifp->if_mtu + ifp->if_hdrlen,
+ M_DEVBUF, M_WAITOK);
+ ifp->if_flags |= IFF_RUNNING;
+/* This starts it running */
+/* Enable lpt interrupts */
+
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_IF)
+ printf("plip: Enabling lpt irqs\n");
+#endif
+ outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+ outb(PLIP_DATA, 0x00);
+ }
+ break;
+
+ case SIOCSIFADDR:
+ if (ifa->ifa_addr->sa_family == AF_INET) {
+ if (!sc->sc_ifbuf)
+ sc->sc_ifbuf =
+ malloc(PLIPMTU + ifp->if_hdrlen,
+ M_DEVBUF, M_WAITOK);
+
+ sc->sc_arpcom.ac_enaddr[0] = 0xfc;
+ sc->sc_arpcom.ac_enaddr[1] = 0xfc;
+ bcopy((caddr_t)&IA_SIN(ifa)->sin_addr,
+ (caddr_t)&sc->sc_arpcom.ac_enaddr[2], 4);
+ sc->sc_arpcom.ac_ipaddr = IA_SIN(ifa)->sin_addr;
+#if defined(COMPAT_PLIP10)
+ if (ifp->if_flags & IFF_LINK0) {
+ int i;
+ sc->sc_arpcom.ac_enaddr[0] = 0xfd;
+ sc->sc_arpcom.ac_enaddr[1] = 0xfd;
+ for (i = sc->sc_adrcksum = 0; i < 5; i++)
+ sc->sc_adrcksum += sc->sc_arpcom.ac_enaddr[i];
+ sc->sc_adrcksum *= 2;
+ }
+#endif
+ ifp->if_flags |= IFF_RUNNING | IFF_UP;
+#if 0
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
+ struct sockaddr_dl *sdl;
+ if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
+ sdl->sdl_family == AF_LINK) {
+ sdl->sdl_type = IFT_ETHER;
+ sdl->sdl_alen = ifp->if_addrlen;
+ bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
+ LLADDR(sdl), ifp->if_addrlen);
+ break;
+ }
+ }
+#endif
+/* Looks the same as the start condition above */
+/* Enable lpt interrupts */
+
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_IF)
+ printf("plip: Enabling lpt irqs\n");
+#endif
+ outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+ outb(PLIP_DATA, 0x00);
+
+ arp_ifinit(&sc->sc_arpcom, ifa);
+ } else
+ error = EAFNOSUPPORT;
+ break;
+
+ case SIOCAIFADDR:
+ case SIOCDIFADDR:
+ case SIOCSIFDSTADDR:
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ error = EAFNOSUPPORT;
+ break;
+
+ case SIOCSIFMTU:
+ if ((error = suser(p->p_ucred, &p->p_acflag)))
+ return(error);
+ if (ifp->if_mtu != ifr->ifr_metric) {
+ ifp->if_mtu = ifr->ifr_metric;
+ if (sc->sc_ifbuf) {
+ s = splimp();
+
+ free(sc->sc_ifbuf, M_DEVBUF);
+ sc->sc_ifbuf =
+ malloc(ifp->if_mtu + ifp->if_hdrlen,
+ M_DEVBUF, M_WAITOK);
+ splx(s);
+ }
+ }
+ break;
+
+ case SIOCGIFMTU:
+ ifr->ifr_metric = ifp->if_mtu;
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ return (error);
+}
+
+static int
+plipreceive(unsigned int iobase, u_char *buf, int len)
+{
+ int i;
+ u_char cksum = 0, c;
+ u_char c0, c1;
+
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_RX)
+ printf("Rx: ");
+#endif
+
+ while (len--) {
+ i = PLIPMXSPIN2;
+/* Receive a byte */
+
+/* Wait for a steady handshake */
+ while (1) {
+ c0 = inb(PLIP_STATUS);
+ if ((c0 & LPS_NBSY) == 0) {
+ c1 = inb(PLIP_STATUS);
+ if (c0 == c1) break;
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_RX)
+ printf("rx: %02x-%02x ", c0, c1);
+#endif
+ }
+ --i;
+ if (i < 0) {
+#if PLIP_DEBUG > 0
+ printf("timeout rx lsn %02x\n", c0);
+#endif
+ return(-1);
+ }
+ PLIP_DELAY;
+ }
+ c = (c0 >> 3) & 0x0f;
+
+/* Acknowledge */
+ outb(PLIP_DATA, 0x10);
+
+/* Another handshake */
+ i = PLIPMXSPIN2;
+ while (1) {
+ c0 = inb(PLIP_STATUS);
+ if (c0 & LPS_NBSY) {
+ c1 = inb(PLIP_STATUS);
+ if (c0 == c1) break;
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_RX)
+ printf("rx: %02x-%02x ", c0, c1);
+#endif
+ }
+ --i;
+ if (i < 0) {
+#if PLIP_DEBUG > 0
+ printf("timeout rx msn %02x\n", c0);
+#endif
+ return(-1);
+ }
+ PLIP_DELAY;
+ }
+ c = c | ((c0 << 1) & 0xf0);
+/* Acknowledge */
+ outb(PLIP_DATA, 0x00);
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_RX)
+ printf("%02x ", c);
+#endif
+
+ cksum += (*buf++ = c);
+ }
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_RX)
+ printf("\n");
+#endif
+ return(cksum);
+}
+
+static int
+plipintr(struct lpt_softc *sc)
+{
+ extern struct mbuf *m_devget(char *, int, int, struct ifnet *, void (*)());
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ unsigned int iobase = sc->sc_iobase;
+ struct mbuf *m;
+ struct ether_header *eh;
+ u_char *p = sc->sc_ifbuf, minibuf[4];
+ int c, s, len, cksum;
+ u_char c0;
+
+printf("plipintr:\n");
+
+/* Get the status */
+
+ c0 = inb(PLIP_STATUS);
+#if PLIP_DEBUG > 0
+ if ((c0 & 0xf8) != 0xc0) {
+ printf("st5=%02x ", c0);
+ }
+#endif
+
+/* Don't want ints while receiving */
+
+ outb(PLIP_CONTROL, PLIP_INTR_DISABLE);
+
+ outb(PLIP_DATA, 0x01); /* send ACK */ /* via NERR */
+
+#if defined(COMPAT_PLIP10)
+ if (ifp->if_flags & IFF_LINK0) {
+ if (plipreceive(iobase, minibuf, 3) < 0) goto err;
+ len = (minibuf[1] << 8) | minibuf[2];
+ if (len > (ifp->if_mtu + ifp->if_hdrlen)) goto err;
+
+ switch (minibuf[0]) {
+ case 0xfc:
+ p[0] = p[ 6] = ifp->ac_enaddr[0];
+ p[1] = p[ 7] = ifp->ac_enaddr[1];
+ p[2] = p[ 8] = ifp->ac_enaddr[2];
+ p[3] = p[ 9] = ifp->ac_enaddr[3];
+ p[4] = p[10] = ifp->ac_enaddr[4];
+ p += 5;
+ if ((cksum = plipreceive(iobase, p, 1)) < 0) goto err;
+ p += 6;
+ if ((c = plipreceive(iobase, p, len - 11)) < 0) goto err;
+ cksum += c + sc->sc_adrcksum;
+ c = p[1]; p[1] = p[2]; p[2] = c;
+ cksum &= 0xff;
+ break;
+ case 0xfd:
+ if ((cksum = plipreceive(iobase, p, len)) < 0) goto err;
+ break;
+ default:
+ goto err;
+ }
+ } else
+#endif
+ {
+ if (plipreceive(iobase, minibuf, 2) < 0) goto err;
+ len = (minibuf[1] << 8) | minibuf[0];
+ if (len > (ifp->if_mtu + ifp->if_hdrlen)) {
+ log(LOG_NOTICE, "plip%d: packet > MTU\n", ifp->if_unit);
+ goto err;
+ }
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_RX)
+ printf("len=%d ", len);
+#endif
+ if (sizeof(struct ether_header) != 14) {
+ if ((cksum = plipreceive(iobase, p, 14)) < 0) goto err;
+ if ((c = plipreceive(iobase, p+16, len-14)) < 0) goto err;
+ cksum += c;
+ len += 2;
+ }
+ else
+ if ((cksum = plipreceive(iobase, p, len)) < 0) goto err;
+ }
+
+ if (plipreceive(iobase, minibuf, 1) < 0) goto err;
+ if ((cksum & 0xff) != minibuf[0]) {
+ printf("cksum=%d, %d, %d\n", cksum, c, minibuf[0]);
+ log(LOG_NOTICE, "plip%d: checksum error\n", ifp->if_unit);
+ goto err;
+ }
+
+ outb(PLIP_DATA, 0x00); /* clear ACK */ /* via NERR */
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_RX)
+ printf("done\n");
+#endif
+ s = splimp();
+
+ eh = (struct ether_header *)sc->sc_ifbuf;
+
+ if ((m = m_devget(sc->sc_ifbuf + sizeof(struct ether_header), len - sizeof(struct ether_header), 0, ifp, NULL))) {
+ /* We assume that the header fit entirely in one mbuf. */
+/* eh = mtod(m, struct ether_header *);*/
+/* m->m_pkthdr.len -= sizeof(*eh);*/
+/* m->m_len -= sizeof(*eh);*/
+/* m->m_data += sizeof(*eh);*/
+/* printf("m->m_data=%08x ifbuf=%08x eh=%08x\n", m->m_data, sc->sc_ifbuf, eh);*/
+
+#if NBPFILTER > 0
+/*
+ * Check if there's a BPF listener on this interface.
+ * If so, hand off the raw packet to bpf.
+ */
+ if (sc->sc_arpcom.ac_if.if_bpf) {
+ bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);
+ }
+#endif
+ ether_input(ifp, eh, m);
+ }
+ splx(s);
+ sc->sc_iferrs = 0;
+ ifp->if_ipackets++;
+
+/* Allow ints again */
+
+ outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+ return(1);
+
+err:
+ outb(PLIP_DATA, 0x00); /* clear ACK */ /* via NERR */
+
+ ifp->if_ierrors++;
+ sc->sc_iferrs++;
+ if (sc->sc_iferrs > PLIPMXERRS
+ || (sc->sc_iferrs > 5 && (inb(iobase + lpt_status) & LPS_NBSY))) {
+ /* We are not able to send receive anything for now,
+ * so stop wasting our time and leave the interrupt
+ * disabled.
+ */
+ if (sc->sc_iferrs == PLIPMXERRS + 1)
+ log(LOG_NOTICE, "plip%d: rx hard error\n", ifp->if_unit);
+/* xxx i8255->port_a |= LPA_ACTIVE;*/
+ } else
+;
+/* xxx i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;*/
+
+/* Allow ints again */
+
+ outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+ return(1);
+}
+
+static int
+pliptransmit(unsigned int iobase, u_char *buf, int len)
+{
+ int i;
+ u_char cksum = 0, c;
+ u_char c0;
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_TX)
+ printf("tx: len=%d ", len);
+#endif
+
+ while (len--) {
+ i = PLIPMXSPIN2;
+ cksum += (c = *buf++);
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_TX)
+ printf("%02x ", c);
+#endif
+/* xxx while ((i8255->port_c & LPC_NBUSY) == 0)
+ if (i-- < 0) return -1;
+ i8255->port_b = c & 0x0f;
+ i8255->port_b = c & 0x0f | 0x10;
+ c >>= 4;
+ while ((i8255->port_c & LPC_NBUSY) != 0)
+ if (i-- < 0) return -1;
+ i8255->port_b = c | 0x10;
+ i8255->port_b = c;
+*/
+
+/* Send the nibble + handshake */
+
+ outb(PLIP_DATA, 0x00 | (c & 0x0f));
+ outb(PLIP_DATA, 0x10 | (c & 0x0f));
+
+ while (1) {
+ c0 = inb(PLIP_STATUS);
+ if ((c0 & LPS_NBSY) == 0)
+ break;
+ if (--i == 0) { /* time out */
+#if PLIP_DEBUG > 0
+ printf("timeout tx lsn %02x ", c0);
+#endif
+ return(-1);
+ }
+ PLIP_DELAY;
+ }
+
+ outb(PLIP_DATA, 0x10 | (c >> 4));
+ outb(PLIP_DATA, 0x00 | (c >> 4));
+ i = PLIPMXSPIN2;
+ while (1) {
+ c0 = inb(PLIP_STATUS);
+ if ((c0 & LPS_NBSY) != 0)
+ break;
+ if (--i == 0) { /* time out */
+#if PLIP_DEBUG > 0
+ printf("timeout tx msn %02x ", c0);
+#endif
+ return(-1);
+ }
+ PLIP_DELAY;
+ }
+ }
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_TX)
+ printf("done\n");
+#endif
+ return(cksum);
+}
+
+/*
+ * Setup output on interface.
+ */
+static void
+plipstart(struct ifnet *ifp)
+{
+ struct lpt_softc *sc = (struct lpt_softc *) lpt_cd.cd_devs[ifp->if_unit];
+ unsigned int iobase = sc->sc_iobase;
+ struct mbuf *m0, *m;
+ u_char minibuf[4], cksum;
+ int len, i, s;
+ u_char *p;
+
+#if PLIP_DEBUG != 0
+ if (plip_debug & PLIP_DEBUG_TX)
+ printf("plipstart: ");
+#endif
+ if (ifp->if_flags & IFF_OACTIVE)
+ return;
+ ifp->if_flags |= IFF_OACTIVE;
+
+ if (sc->sc_ifretry)
+ untimeout((void (*)(void *))plipstart, ifp);
+
+ for (;;) {
+ s = splimp();
+ IF_DEQUEUE(&ifp->if_snd, m0);
+ splx(s);
+ if (!m0)
+ break;
+
+ for (len = 0, m = m0; m; m = m->m_next) {
+#if PLIP_DEBUG > 0
+ if (plip_debug & PLIP_DEBUG_TX)
+ printf("len=%d %d\n", m->m_len, len);
+#endif
+ len += m->m_len;
+ }
+#if NBPFILTER > 0
+ p = sc->sc_ifbuf;
+ for (m = m0; m; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ bcopy(mtod(m, u_char *), p, m->m_len);
+ p += m->m_len;
+ }
+ if (sc->sc_arpcom.ac_if.if_bpf)
+ bpf_tap(sc->sc_arpcom.ac_if.if_bpf, sc->sc_ifbuf, len);
+#endif
+ if (sizeof(struct ether_header) != 14)
+ len -= 2;
+#if defined(COMPAT_PLIP10)
+ if (ifp->if_flags & IFF_LINK0) {
+ minibuf[0] = 3;
+ minibuf[1] = 0xfd;
+ minibuf[2] = len >> 8;
+ minibuf[3] = len;
+ } else
+#endif
+ {
+ minibuf[0] = 2;
+ minibuf[1] = len;
+ minibuf[2] = len >> 8;
+ }
+
+/*yyy for (i = PLIPMXSPIN1; (inb(PLIP_STATUS) & LPS_NERR) != 0; i--)
+ if (i < 0) goto retry;*/
+
+ /* Trigger remote interrupt */
+
+#if PLIP_DEBUG > 0
+ if (plip_debug & PLIP_DEBUG_TX)
+ printf("st=%02x ", inb(PLIP_STATUS));
+#endif
+ if (inb(PLIP_STATUS) & LPS_NERR) {
+ for (i = PLIPMXSPIN1; (inb(PLIP_STATUS) & LPS_NERR) != 0; i--)
+ PLIP_DELAY;
+#if PLIP_DEBUG > 0
+ if (plip_debug & PLIP_DEBUG_TX)
+ printf("st1=%02x ", inb(PLIP_STATUS));
+#endif
+ }
+
+ outb(PLIP_DATA, PLIP_REMOTE_TRIGGER);
+ for (i = PLIPMXSPIN1; (inb(PLIP_STATUS) & LPS_NERR) == 0; i--) {
+ if (i < 0 || (i > PLIPMXSPIN1/3
+ && inb(PLIP_STATUS) & LPS_NACK)) {
+#if PLIP_DEBUG > 0
+ printf("trigger ack timeout\n");
+#endif
+ goto retry;
+ }
+ PLIP_DELAY;
+ }
+#if PLIP_DEBUG > 0
+ if (plip_debug & PLIP_DEBUG_TX)
+ printf("st3=%02x ", inb(PLIP_STATUS));
+#endif
+
+/* Don't want ints while transmitting */
+
+ outb(PLIP_CONTROL, PLIP_INTR_DISABLE);
+
+ if (pliptransmit(iobase, minibuf + 1, minibuf[0]) < 0) goto retry;
+ for (cksum = 0, m = m0; m; m = m->m_next) {
+ if (sizeof(struct ether_header) != 14 && m == m0) {
+ i = pliptransmit(iobase, mtod(m, u_char *), 14);
+ if (i < 0) goto retry;
+ cksum += i;
+ i = pliptransmit(iobase, mtod(m, u_char *)+16, m->m_len-16);
+ if (i < 0) goto retry;
+ }
+ else
+ i = pliptransmit(iobase, mtod(m, u_char *), m->m_len);
+ if (i < 0) goto retry;
+ cksum += i;
+ }
+ if (pliptransmit(iobase, &cksum, 1) < 0) goto retry;
+ i = PLIPMXSPIN2;
+ while ((inb(PLIP_STATUS) & LPS_NBSY) == 0)
+ if (i-- < 0) goto retry;
+
+ outb(iobase + lpt_data, 0x00);
+/* Re-enable ints */
+
+ outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+
+ ifp->if_opackets++;
+ ifp->if_obytes += len + 4;
+ sc->sc_ifretry = 0;
+ s = splimp();
+ m_freem(m0);
+ splx(s);
+ }
+ ifp->if_flags &= ~IFF_OACTIVE;
+ return;
+
+retry:
+#if PLIP_DEBUG > 0
+ if (plip_debug & PLIP_DEBUG_TX)
+ printf("retry: %02x", inb(iobase + lpt_status));
+#endif
+ if (inb(PLIP_STATUS & LPS_NACK))
+ ifp->if_collisions++;
+ else
+ ifp->if_oerrors++;
+ if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == (IFF_RUNNING | IFF_UP)
+ && sc->sc_ifretry < PLIPMXRETRY) {
+ sc->sc_ifretry++;
+ s = splimp();
+ IF_PREPEND(&ifp->if_snd, m0);
+ splx(s);
+ timeout((void (*)(void *))plipstart, ifp, PLIPRETRY);
+ } else {
+ if (sc->sc_ifretry == PLIPMXRETRY) {
+ sc->sc_ifretry++;
+ log(LOG_NOTICE, "plip%d: tx hard error\n", ifp->if_unit);
+ }
+ s = splimp();
+ m_freem(m0);
+ splx(s);
+ }
+ ifp->if_flags &= ~IFF_OACTIVE;
+ outb(PLIP_DATA, 0x00);
+
+/* Re-enable ints */
+
+ outb(PLIP_CONTROL, PLIP_INTR_ENABLE);
+/*xxx if (sc->sc_iferrs > PLIPMXERRS)
+ i8255->port_a |= LPA_ACTIVE;
+ else
+ i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;*/
+ return;
+}
+
+#endif
--- /dev/null
+/* $NetBSD: lptreg.h,v 1.2 1996/03/18 20:50:03 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)lptreg.h 1.1 (Berkeley) 12/19/90
+ */
+
+/*
+ * AT Parallel Port (for lineprinter)
+ * Interface port and bit definitions
+ * Written by William Jolitz 12/18/90
+ * Copyright (C) William Jolitz 1990
+ */
+
+#define lpt_data 0 /* Data to/from printer (R/W) */
+
+#define lpt_status 4 /* Status of printer (R) */
+#define LPS_NERR 0x08 /* printer no error */
+#define LPS_SELECT 0x10 /* printer selected */
+#define LPS_NOPAPER 0x20 /* printer out of paper */
+#define LPS_NACK 0x40 /* printer no ack of data */
+#define LPS_NBSY 0x80 /* printer no ack of data */
+
+#define lpt_control 8 /* Control printer (R/W) */
+#define LPC_STROBE 0x01 /* strobe data to printer */
+#define LPC_AUTOLF 0x02 /* automatic linefeed */
+#define LPC_NINIT 0x04 /* initialize printer */
+#define LPC_SELECT 0x08 /* printer selected */
+#define LPC_IENABLE 0x10 /* printer out of paper */
+
+#define LPT_NPORTS 32
--- /dev/null
+/* $NetBSD: mainbus.c,v 1.3 1996/03/20 18:38:00 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * mainbus.c
+ *
+ * mainbus configuration
+ *
+ * Created : 15/12/94
+ * Last updated : 03/07/95
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+
+#include <arm32/mainbus/mainbus.h>
+#include <machine/io.h>
+
+int mainbusmatch __P((struct device *, void *, void *));
+void mainbusattach __P((struct device *, struct device *, void *));
+
+struct cfattach mainbus_ca = {
+ sizeof(struct device), mainbusmatch, mainbusattach
+};
+
+struct cfdriver mainbus_cd = {
+ NULL, "mainbus", DV_DULL, 1
+};
+
+int
+mainbusmatch(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ return (1);
+}
+
+int
+mainbusprint(aux, mainbus)
+ void *aux;
+ char *mainbus;
+{
+ struct mainbus_attach_args *mb = aux;
+
+ if (mb->mb_iobase)
+ printf(" base 0x%x", mb->mb_iobase);
+ if (mb->mb_iosize > 1)
+ printf("-0x%x", mb->mb_iobase + mb->mb_iosize - 1);
+ if (mb->mb_irq != -1)
+ printf(" irq %d", mb->mb_irq);
+ if (mb->mb_drq != -1)
+ printf(" drq 0x%08x", mb->mb_drq);
+
+/* XXXX print flags */
+ return (QUIET);
+}
+
+
+void
+mainbusscan(parent, match)
+ struct device *parent;
+ void *match;
+{
+ struct device *dev = match;
+ struct cfdata *cf = dev->dv_cfdata;
+ struct mainbus_attach_args mb;
+
+ if (cf->cf_fstate == FSTATE_STAR)
+ panic("eekkk, I'm stuffed");
+
+ if (cf->cf_loc[0] == -1) {
+ mb.mb_iobase = 0;
+ mb.mb_iosize = 0;
+ mb.mb_drq = -1;
+ mb.mb_irq = -1;
+ } else {
+ mb.mb_iobase = cf->cf_loc[0] + IO_CONF_BASE;
+ mb.mb_iosize = 0;
+ mb.mb_drq = cf->cf_loc[1];
+ mb.mb_irq = cf->cf_loc[2];
+ }
+ if ((*cf->cf_attach->ca_match)(parent, dev, &mb) > 0)
+ config_attach(parent, dev, &mb, mainbusprint);
+ else
+ free(dev, M_DEVBUF);
+}
+
+void
+mainbusattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ printf("\n");
+
+ config_scan(mainbusscan, self);
+}
+
+/* End of mainbus.c */
--- /dev/null
+/* $NetBSD: mainbus.h,v 1.2 1996/03/18 20:50:05 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * mainbus.c
+ *
+ * mainbus configuration
+ *
+ * Created : 15/12/94
+ */
+
+/*
+ * mainbus driver attach arguments
+ */
+
+struct mainbus_attach_args {
+ u_int mb_iobase; /* base i/o address */
+ int mb_iosize; /* span of ports used */
+ int mb_irq; /* interrupt request */
+ int mb_drq; /* DMA request */
+ void *mb_aux; /* driver specific */
+};
+
+#define DRQUNK -1
+#define INTUNK -1
+#define IRQUNK -1
+
+/* End of mainbus.h */
+
+
--- /dev/null
+/* $NetBSD: pms.c,v 1.1 1996/03/28 21:50:19 mark Exp $ */
+
+/*-
+ * Copyright (c) 1996 D.C. Tsen
+ * Copyright (c) 1994 Charles Hannum.
+ * Copyright (c) 1992, 1993 Erik Forsberg.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from:pms.c,v 1.24 1995/12/24 02:30:28 mycroft Exp
+ */
+
+/*
+ * Ported from 386 version of PS/2 mouse driver.
+ * D.C. Tsen
+ */
+
+#include "pms.h"
+#if NPMS > 1
+#error Only one PS/2 style mouse may be configured into your system.
+#endif
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/file.h>
+#include <sys/select.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/irqhandler.h>
+#include <machine/iomd.h>
+#include <machine/mouse.h>
+#include <arm32/mainbus/mainbus.h>
+
+/* mouse commands */
+#define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */
+#define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */
+#define PMS_SET_RES 0xe8 /* set resolution */
+#define PMS_GET_SCALE 0xe9 /* get scaling factor */
+#define PMS_SET_STREAM 0xea /* set streaming mode */
+#define PMS_SET_SAMPLE 0xf3 /* set sampling rate */
+#define PMS_DEV_ENABLE 0xf4 /* mouse on */
+#define PMS_DEV_DISABLE 0xf5 /* mouse off */
+#define PMS_RESET 0xff /* reset */
+
+#define PMS_CHUNK 128 /* chunk size for read */
+#define PMS_BSIZE (20*64) /* buffer size */
+
+struct pms_softc { /* driver status information */
+ struct device sc_dev;
+ irqhandler_t sc_ih;
+
+ struct proc *proc;
+ struct clist sc_q;
+ struct selinfo sc_rsel;
+ u_int sc_state; /* mouse driver state */
+#define PMS_OPEN 0x01 /* device is open */
+#define PMS_ASLP 0x02 /* waiting for mouse data */
+ u_int sc_status; /* mouse button status */
+ int sc_x, sc_y; /* accumulated motion in the X,Y axis */
+ int boundx, boundy, bounda, boundb; /* Bounding box. x,y is bottom left */
+ int origx, origy;
+ int lastx, lasty, lastb;
+};
+
+int pmsprobe __P((struct device *, void *, void *));
+void pmsattach __P((struct device *, struct device *, void *));
+int pmsintr __P((void *));
+
+struct cfattach pms_ca = {
+ sizeof(struct pms_softc), pmsprobe, pmsattach
+};
+
+struct cfdriver pms_cd = {
+ NULL, "pms", DV_DULL
+};
+
+#define PMSUNIT(dev) (minor(dev))
+
+static inline void
+pms_flush()
+{
+ while (inb(IOMD_MSCR) & 0x20) {
+ delay(6);
+ (void) inb(IOMD_MSDATA);
+ delay(6);
+ (void) inb(IOMD_MSDATA);
+ delay(6);
+ (void) inb(IOMD_MSDATA);
+ }
+}
+
+static void
+cmd_mouse(unsigned char cmd)
+{
+ unsigned char c;
+ int i = 0;
+ int retry = 10;
+
+ for (i = 0; i < 1000; i++) {
+ if (inb(IOMD_MSCR) & 0x80)
+ break;
+ delay(2);
+ }
+ if (i == 1000)
+ printf("Mouse transmit not ready\n");
+
+resend:
+ outb(IOMD_MSDATA, cmd);
+ delay(2);
+ c = inb(IOMD_MSCR) & (unsigned char) 0xff;
+ while (!(c & (unsigned char) 0x20)) {
+ delay(1);
+ c = inb(IOMD_MSCR);
+ }
+
+ delay(10000);
+
+ c = inb(IOMD_MSDATA) & 0xff;
+ if ((c == 0xFA) || (c == 0xEE))
+ return;
+
+ if (--retry) {
+ pms_flush();
+ goto resend;
+ }
+
+ printf("Mouse cmd failed, cmd = %x, status = %x\n", cmd, c);
+ return;
+}
+
+int
+pmsprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ /*struct mainbus_attach_args *mb = aux;*/
+ int i, j;
+ int mid;
+ int id;
+
+/* Make sure we have an IOMD we understand */
+
+ id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+ switch (id) {
+ case RPC600_IOMD_ID:
+ return(0);
+ break;
+ case RC7500_IOC_ID:
+ break;
+ default:
+ printf("pms: Unknown IOMD id=%04x", id);
+ return(0);
+ break;
+ }
+
+ outb(IOMD_MSCR, 0x08); /* enable the mouse */
+
+ i = 0;
+ while ((inb(IOMD_MSCR) & 0x03) != 0x03) {
+ if (i++ > 10) {
+ printf("Mouse not found, status = <%x>.\n", inb(IOMD_MSCR));
+ return(0);
+ }
+ pms_flush();
+ delay(2);
+ outb(IOMD_MSCR, 0x08);
+ }
+
+ pms_flush();
+
+ /*
+ * Disable, reset and enable the mouse.
+ */
+ cmd_mouse(PMS_DEV_DISABLE);
+ cmd_mouse(PMS_RESET);
+ delay(300000);
+ j = 10;
+ i = 0;
+ while ((mid = inb(IOMD_MSDATA)) != 0xAA) {
+ if (++i > 500) {
+ if (--j < 0) {
+ printf("Mouse Reset failed, status = <%x>.\n", mid);
+ return(0);
+ }
+ pms_flush();
+ cmd_mouse(PMS_RESET);
+ i = 0;
+ }
+ delay(100000);
+ }
+ mid = inb(IOMD_MSDATA);
+#if 0
+ cmd_mouse(PMS_SET_RES);
+ cmd_mouse(3); /* 8 counts/mm */
+ cmd_mouse(PMS_SET_SCALE21);
+ cmd_mouse(PMS_SET_SAMPLE);
+ cmd_mouse(100); /* 100 samples/sec */
+ cmd_mouse(PMS_SET_STREAM);
+#endif
+ cmd_mouse(PMS_DEV_ENABLE);
+ return 1;
+}
+
+void
+pmsattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pms_softc *sc = (void *)self;
+ struct mainbus_attach_args *mb = aux;
+
+ printf("\n");
+
+ /* Other initialization was done by pmsprobe. */
+ sc->sc_state = 0;
+ sc->origx = 0;
+ sc->origy = 0;
+ sc->boundx = -4095;
+ sc->boundy = -4095;
+ sc->bounda = 4096;
+ sc->boundb = 4096;
+
+ sc->sc_ih.ih_func = pmsintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_TTY;
+ sc->sc_ih.ih_name = "pms";
+ if (mb->mb_irq != IRQUNK)
+ sc->sc_ih.ih_num = mb->mb_irq;
+ else
+#ifdef RC7500
+ sc->sc_ih.ih_num = IRQ_MSDRX;
+#else
+ panic("pms: No IRQ specified for pms interrupt handler\n");
+#endif
+}
+
+int
+pmsopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ int unit = PMSUNIT(dev);
+ struct pms_softc *sc;
+
+ if (unit >= pms_cd.cd_ndevs)
+ return ENXIO;
+ sc = pms_cd.cd_devs[unit];
+ if (!sc)
+ return ENXIO;
+
+ if (sc->sc_state & PMS_OPEN)
+ return EBUSY;
+
+ if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1)
+ return ENOMEM;
+
+ sc->proc = p;
+ sc->sc_state |= PMS_OPEN;
+ sc->sc_status = 0;
+ sc->sc_x = sc->sc_y = 0;
+ sc->lastx = -1;
+ sc->lasty = -1;
+ sc->lastb = -1;
+
+ if (irq_claim(IRQ_INSTRUCT, &sc->sc_ih) == -1)
+ panic("Cannot claim MOUSE IRQ\n");
+
+ return 0;
+}
+
+int
+pmsclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+
+ if (irq_release(IRQ_INSTRUCT, &sc->sc_ih) != 0)
+ panic("Cannot release MOUSE IRQ\n");
+
+ sc->proc = NULL;
+ sc->sc_state &= ~PMS_OPEN;
+ sc->sc_x = sc->sc_y = 0;
+
+ clfree(&sc->sc_q);
+
+ return 0;
+}
+
+int
+pmsread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+ int s;
+ int error = 0;
+ size_t length;
+ u_char buffer[PMS_CHUNK];
+
+ /* Block until mouse activity occured. */
+
+ s = spltty();
+ while (sc->sc_q.c_cc == 0) {
+ if (flag & IO_NDELAY) {
+ splx(s);
+ return EWOULDBLOCK;
+ }
+ sc->sc_state |= PMS_ASLP;
+ if (error = tsleep((caddr_t)sc, (PZERO | PCATCH), "pmsread", 0)) {
+ sc->sc_state &= ~PMS_ASLP;
+ splx(s);
+ return error;
+ }
+ }
+
+ /* Transfer as many chunks as possible. */
+
+ while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
+ length = min(sc->sc_q.c_cc, uio->uio_resid);
+ if (length > sizeof(buffer))
+ length = sizeof(buffer);
+
+ /* Remove a small chunk from the input queue. */
+ (void) q_to_b(&sc->sc_q, buffer, length);
+
+ /* Copy the data to the user process. */
+ if (error = uiomove(buffer, length, uio))
+ break;
+ }
+ splx(s);
+
+ return error;
+}
+
+int
+pmsioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t addr;
+ int flag;
+ struct proc *p;
+{
+ struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+ struct mouseinfo info;
+ int s;
+ int error = 0;
+
+ s = spltty();
+
+ switch (cmd) {
+ case MOUSEIOC_SETSTATE:
+ printf("MOUSEIOC_SETSTATE called\n");
+ break;
+ case MOUSEIOC_WRITEX:
+ sc->sc_x = *(int *) addr;
+ break;
+ case MOUSEIOC_WRITEY:
+ sc->sc_y = *(int *) addr;
+ break;
+ case MOUSEIOC_SETBOUNDS:
+ {
+ register struct mouse_boundingbox *bo = (void *) addr;
+ sc->boundx = bo->x; sc->boundy = bo->y;
+ sc->bounda = bo->a; sc->boundb = bo->b;
+ break;
+ }
+ case MOUSEIOC_SETORIGIN:
+ {
+ register struct mouse_origin *oo = (void *) addr;
+ sc->origx = oo->x;
+ sc->origy = oo->y;
+ break;
+ }
+ case MOUSEIOC_GETBOUNDS:
+ {
+ register struct mouse_boundingbox *bo = (void *) addr;
+ bo->x = sc->boundx; bo->y = sc->boundy;
+ bo->a = sc->bounda; bo->b = sc->boundb;
+ break;
+ }
+ case MOUSEIOC_GETORIGIN:
+ {
+ register struct mouse_origin *oo = (void *) addr;
+ oo->x = sc->origx;
+ oo->y = sc->origy;
+ break;
+ }
+ case MOUSEIOC_GETSTATE:
+ printf("MOUSEIOC_GETSTATE called\n");
+ /*
+ * Fall through.
+ */
+/* case MOUSEIOCREAD:*/
+
+ info.status = sc->sc_status;
+ if (sc->sc_x || sc->sc_y)
+ info.status |= MOVEMENT;
+
+#if 1
+ info.xmotion = sc->sc_x;
+ info.ymotion = sc->sc_y;
+#else
+ if (sc->sc_x > sc->bounda)
+ info.xmotion = sc->bounda;
+ else if (sc->sc_x < sc->boundx)
+ info.xmotion = sc->boundx;
+ else
+ info.xmotion = sc->sc_x;
+
+ if (sc->sc_y > sc->boundb)
+ info.ymotion = sc->boundb;
+ else if (sc->sc_y < sc->boundy)
+ info.ymotion = sc->boundy;
+ else
+ info.ymotion = sc->sc_y;
+#endif
+
+ /* Reset historical information. */
+ sc->sc_x = sc->sc_y = 0;
+ sc->sc_status &= ~BUTCHNGMASK;
+ ndflush(&sc->sc_q, sc->sc_q.c_cc);
+
+ error = copyout(&info, addr, sizeof(struct mouseinfo));
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ splx(s);
+
+ return error;
+}
+
+/* Masks for the first byte of a packet */
+#define PS2LBUTMASK 0x01
+#define PS2RBUTMASK 0x02
+#define PS2MBUTMASK 0x04
+
+#define XNEG_MASK 0x10
+#define YNEG_MASK 0x20
+
+int
+pmsintr(arg)
+ void *arg;
+{
+ struct pms_softc *sc = arg;
+ static int state = 0;
+ static u_char buttons;
+ u_char changed;
+ static int dx, dy;
+ int dosignal = 0;
+ int s;
+ u_char b;
+ struct mousebufrec mbuffer;
+
+ if ((sc->sc_state & PMS_OPEN) == 0) {
+ /* Interrupts are not expected. Discard the byte. */
+ pms_flush();
+ return(-1);
+ }
+
+ switch (state) {
+
+ case 0:
+ buttons = inb(IOMD_MSDATA);
+ if ((buttons & 0xc0) == 0)
+ ++state;
+ break;
+
+ case 1:
+ dx = inb(IOMD_MSDATA);
+ dx = (buttons & XNEG_MASK) ? -dx : dx;
+ ++state;
+ break;
+
+ case 2:
+ dy = inb(IOMD_MSDATA);
+ dy = (buttons & YNEG_MASK) ? -dy : dy;
+ state = 0;
+
+ buttons = ((buttons & PS2LBUTMASK) << 2) |
+ ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1);
+ /*
+ * Ahhh, the Xarm server interrupt button bits reversed.
+ * If bit is set to 1, it means button is not pressed which is
+ * not what PS/2 mouse button bits said. Since we are simulating
+ * the quadmouse, that's not too picky about it.
+ */
+ buttons ^= BUTSTATMASK;
+ changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3;
+ sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed;
+
+ if (dx || dy || changed) {
+ if (dx < 0)
+ dx = -(256 + dx);
+ if (dy < 0)
+ dy = -(256 + dy);
+
+ /* Update accumulated movements. */
+ sc->sc_x += dx;
+ sc->sc_y += dy;
+
+ if (sc->sc_x > sc->bounda)
+ sc->sc_x = sc->bounda;
+ else if (sc->sc_x < sc->boundx)
+ sc->sc_x = sc->boundx;
+
+ if (sc->sc_y > sc->boundb)
+ sc->sc_y = sc->boundb;
+ else if (sc->sc_y < sc->boundy)
+ sc->sc_y = sc->boundy;
+
+ if (sc->sc_q.c_cc == 0) {
+ dosignal = 1;
+ }
+
+ /* Add this event to the queue. */
+ b = buttons & BUTSTATMASK;
+ mbuffer.status = b | (b ^ sc->lastb) << 3
+ | (((sc->sc_x==sc->lastx) && (sc->sc_y==sc->lasty))?0:0x40);
+ mbuffer.x = sc->sc_x * 2;
+ mbuffer.y = sc->sc_y * 2;
+ microtime(&mbuffer.event_time);
+ s = spltty();
+ (void) b_to_q((char *)&mbuffer, sizeof(mbuffer), &sc->sc_q);
+ (void) splx(s);
+ sc->lastx = sc->sc_x;
+ sc->lasty = sc->sc_y;
+ sc->lastb = b;
+
+ selwakeup(&sc->sc_rsel);
+ if (sc->sc_state & PMS_ASLP) {
+ sc->sc_state &= ~PMS_ASLP;
+ wakeup((caddr_t)sc);
+ }
+ if (dosignal)
+ psignal(sc->proc, SIGIO);
+ }
+
+ break;
+ }
+
+ return(0);
+}
+
+int
+pmsselect(dev, rw, p)
+ dev_t dev;
+ int rw;
+ struct proc *p;
+{
+ struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+ int s;
+ int ret;
+
+ if (rw == FWRITE)
+ return 0;
+
+ s = spltty();
+ if (!sc->sc_q.c_cc) {
+ selrecord(p, &sc->sc_rsel);
+ ret = 0;
+ } else
+ ret = 1;
+ splx(s);
+
+ return ret;
+}
--- /dev/null
+/* $NetBSD: qmouse.c,v 1.5 1996/03/28 21:56:40 mark Exp $ */
+
+/*
+ * Copyright (c) Scott Stevens 1995 All rights reserved
+ * Copyright (c) Melvin Tang-Richardson 1995 All rights reserved
+ * Copyright (c) Mark Brinicombe 1995 All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Quadrature mouse driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/kernel.h>
+#include <sys/types.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <dev/cons.h>
+#include <sys/fcntl.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+#include <sys/time.h>
+
+#include <arm32/mainbus/mainbus.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <machine/iomd.h>
+#include <machine/mouse.h>
+
+#include "quadmouse.h"
+
+#define TIMER1_COUNT 40000 /* 50Hz */
+
+#define QMOUSE_BSIZE 12*64
+
+struct quadmouse_softc {
+ struct device sc_device;
+ irqhandler_t sc_ih;
+ int sc_iobase;
+ struct selinfo sc_rsel;
+#define QMOUSE_OPEN 0x01
+#define QMOUSE_ASLEEP 0x02
+ int sc_state;
+ int boundx, boundy, bounda, boundb; /* Bounding box. x,y is bottom left */
+ int origx, origy;
+ int xmult, ymult; /* Multipliers */
+ int lastx, lasty, lastb;
+ struct proc *proc;
+ struct clist buffer;
+};
+
+int quadmouseprobe __P((struct device *, void *, void *));
+void quadmouseattach __P((struct device *, struct device *, void *));
+int quadmouseopen __P((dev_t, int, int, struct proc *));
+int quadmouseclose __P((dev_t, int, int, struct proc *));
+
+int strncmp __P((const char *, const char *, size_t));
+
+int quadmouseintr (struct quadmouse_softc *);
+
+struct cfattach quadmouse_ca = {
+ sizeof(struct quadmouse_softc), quadmouseprobe, quadmouseattach
+};
+
+struct cfdriver quadmouse_cd = {
+ NULL, "quadmouse", DV_DULL
+};
+
+
+int
+quadmouseprobe(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+/* struct mainbus_attach_args *mb = aux;*/
+ int id;
+
+/* Make sure we have an IOMD we understand */
+
+ id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8);
+
+/* So far I only know about this IOMD */
+
+ switch (id) {
+ case RPC600_IOMD_ID:
+ return(1);
+ break;
+ default:
+ printf("quadmouse: Unknown IOMD id=%04x", id);
+ break;
+ }
+
+ return(0);
+}
+
+
+void
+quadmouseattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct quadmouse_softc *sc = (void *)self;
+ struct mainbus_attach_args *mb = aux;
+
+ sc->sc_iobase = mb->mb_iobase;
+
+/* Check for a known IOMD chip */
+
+ sc->sc_ih.ih_func = quadmouseintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_TTY;
+ sc->sc_ih.ih_name = "T1 quadmouse";
+
+/* Set up origin and multipliers */
+
+ sc->origx = 0;
+ sc->origy = 0;
+ sc->xmult = 2;
+ sc->ymult = 2;
+
+/* Set up bounding box */
+
+ sc->boundx = -4095;
+ sc->boundy = -4095;
+ sc->bounda = 4096;
+ sc->boundb = 4096;
+
+ sc->sc_state = 0;
+
+ WriteWord(IOMD_MOUSEX, sc->origx);
+ WriteWord(IOMD_MOUSEY, sc->origy);
+
+ printf("\n");
+}
+
+
+int
+quadmouseopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct quadmouse_softc *sc;
+ int unit = minor(dev);
+
+ if (unit >= quadmouse_cd.cd_ndevs)
+ return(ENXIO);
+
+ sc = quadmouse_cd.cd_devs[unit];
+
+ if (!sc) return(ENXIO);
+
+ if (sc->sc_state & QMOUSE_OPEN) return(EBUSY);
+
+ sc->proc = p;
+
+ sc->lastx = -1;
+ sc->lasty = -1;
+ sc->lastb = -1;
+
+ /* initialise buffer */
+ if (clalloc(&sc->buffer, QMOUSE_BSIZE, 0) == -1)
+ return(ENOMEM);
+
+ sc->sc_state |= QMOUSE_OPEN;
+
+ WriteByte(IOMD_T1LOW, (TIMER1_COUNT >> 0) & 0xff);
+ WriteByte(IOMD_T1HIGH, (TIMER1_COUNT >> 8) & 0xff);
+ WriteByte(IOMD_T1GO, 0);
+
+ if (irq_claim(IRQ_TIMER1, &sc->sc_ih))
+ panic("Cannot claim TIMER1 IRQ for quadmouse%d\n", sc->sc_device.dv_unit);
+
+ return(0);
+}
+
+
+int
+quadmouseclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ int unit = minor (dev);
+ struct quadmouse_softc *sc = quadmouse_cd.cd_devs[unit];
+
+ if (irq_release(IRQ_TIMER1, &sc->sc_ih) != 0)
+ panic("Cannot release IRA\n");
+
+ sc->proc = NULL;
+ sc->sc_state = 0;
+
+ clfree(&sc->buffer);
+
+ return(0);
+}
+
+int
+quadmouseread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ int unit = minor(dev);
+ struct quadmouse_softc *sc = quadmouse_cd.cd_devs[unit];
+ int error;
+ int s;
+ int length;
+ u_char buffer[128];
+
+ s=spltty();
+ while(sc->buffer.c_cc==0) {
+ if(flag & IO_NDELAY) {
+ (void)splx(s);
+ return(EWOULDBLOCK);
+ }
+ sc->sc_state |= QMOUSE_ASLEEP;
+ if((error = tsleep((caddr_t)sc, PZERO | PCATCH, "quadmouseread", 0))) {
+ sc->sc_state &= ~QMOUSE_ASLEEP;
+ (void)splx(s);
+ return(error);
+ }
+ }
+
+ while(sc->buffer.c_cc>0 && uio->uio_resid>0) {
+ length=min(sc->buffer.c_cc, uio->uio_resid);
+ if(length>sizeof(buffer))
+ length=sizeof(buffer);
+
+ (void) q_to_b(&sc->buffer, buffer, length);
+
+ if(error = (uiomove(buffer, length, uio)))
+ break;
+ }
+ (void)splx(s);
+ return(error);
+}
+
+
+#define FMT_START int x = ReadWord(IOMD_MOUSEX)&0xffff; \
+ int y = ReadWord(IOMD_MOUSEY)&0xffff; \
+ int b = ReadByte(IO_MOUSE_BUTTONS)&0x70; \
+ if(x&0x8000) x|=0xffff0000; \
+ if(y&0x8000) y|=0xffff0000; \
+ x = (x - sc->origx); \
+ y = (y - sc->origy); \
+ if (x<(sc->boundx)) x = sc->boundx; \
+ WriteWord(IOMD_MOUSEX, x + sc->origx); \
+ if (x>(sc->bounda)) x = sc->bounda; \
+ WriteWord(IOMD_MOUSEX, x + sc->origx); \
+ if (y<(sc->boundy)) y = sc->boundy; \
+ WriteWord(IOMD_MOUSEY, y + sc->origy); \
+ if (y>(sc->boundb)) y = sc->boundb; \
+ WriteWord(IOMD_MOUSEY, y + sc->origy); \
+ x=x*sc->xmult; \
+ y=y*sc->ymult;
+
+#define FMT_END
+
+
+int
+quadmouseioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct quadmouse_softc *sc = quadmouse_cd.cd_devs[minor(dev)];
+
+ switch (cmd) {
+ case MOUSEIOC_WRITEX:
+ WriteWord(IOMD_MOUSEX, *(int *)data+sc->origx);
+ return 0;
+ case MOUSEIOC_WRITEY:
+ WriteWord(IOMD_MOUSEY, *(int *)data+sc->origy);
+ return 0;
+ case MOUSEIOC_SETSTATE:
+ {
+ register struct mouse_state *co = (void *)data;
+ WriteWord(IOMD_MOUSEX, co->x);
+ WriteWord(IOMD_MOUSEY, co->y);
+
+ /* Silly, but here for completeness, just incase */
+ /* the hardware supports it *giggle* */
+
+/* This is not writable -- mark -- technically this should fault */
+
+/* WriteWord ( IO_MOUSE_BUTTONS, co->buttons );*/
+ return 0;
+ }
+ case MOUSEIOC_SETBOUNDS:
+ {
+ register struct mouse_boundingbox *bo = (void *)data;
+ sc->boundx = bo->x; sc->boundy = bo->y;
+ sc->bounda = bo->a; sc->boundb = bo->b;
+ return 0;
+ }
+ case MOUSEIOC_SETORIGIN:
+ {
+ register struct mouse_origin *oo = (void *)data;
+/* int oldx, oldy;*/
+ /* Need to fix up! */
+ sc->origx = oo->x;
+ sc->origy = oo->y;
+ return 0;
+ }
+ case MOUSEIOC_GETSTATE:
+ {
+ register struct mouse_state *co = (void *)data;
+ FMT_START
+ co->x = x;
+ co->y = y;
+ co->buttons = b ^ 0x70;
+ FMT_END
+ return 0;
+ }
+ case MOUSEIOC_GETBOUNDS:
+ {
+ register struct mouse_boundingbox *bo = (void *)data;
+ bo->x = sc->boundx; bo->y = sc->boundy;
+ bo->a = sc->bounda; bo->b = sc->boundb;
+ return 0;
+ }
+ case MOUSEIOC_GETORIGIN:
+ {
+ register struct mouse_origin *oo = (void *)data;
+ oo->x = sc->origx;
+ oo->y = sc->origy;
+ return 0;
+ }
+ }
+
+ return (EINVAL);
+}
+
+
+int
+quadmouseintr(sc)
+ struct quadmouse_softc *sc;
+{
+ int s;
+ struct mousebufrec buffer;
+ int dosignal=0;
+
+ FMT_START
+
+ b &= 0x70;
+ b >>= 4;
+ if (x != sc->lastx || y != sc->lasty || b != sc->lastb) {
+ /* Mouse state changed */
+ buffer.status = b | ( b ^ sc->lastb) << 3 | (((x==sc->lastx) && (y==sc->lasty))?0:0x40);
+ buffer.x = x;
+ buffer.y = y;
+ microtime(&buffer.event_time);
+
+ if(sc->buffer.c_cc==0)
+ dosignal=1;
+
+ s=spltty();
+ (void) b_to_q((char *)&buffer, sizeof(buffer), &sc->buffer);
+ (void)splx(s);
+ selwakeup(&sc->sc_rsel);
+
+ if(sc->sc_state & QMOUSE_ASLEEP) {
+ sc->sc_state &= ~QMOUSE_ASLEEP;
+ wakeup((caddr_t)sc);
+ }
+
+ if(dosignal)
+ psignal(sc->proc, SIGIO);
+
+ sc->lastx = x;
+ sc->lasty = y;
+ sc->lastb = b;
+ }
+
+ FMT_END
+ return(0);
+}
+
+int
+quadmouseselect(dev, rw, p)
+ dev_t dev;
+ int rw;
+ struct proc *p;
+{
+ int unit = minor(dev);
+ struct quadmouse_softc *sc = quadmouse_cd.cd_devs[unit];
+ int s;
+
+ if(rw == FWRITE)
+ return 0;
+
+ s=spltty();
+ if(sc->buffer.c_cc > 0) {
+ selrecord(p, &sc->sc_rsel);
+ (void)splx(s);
+ return 0;
+ }
+ (void)splx(s);
+ return 1;
+}
+
+/* End of quadmouse.c */
--- /dev/null
+/* $NetBSD: rtc.c,v 1.1 1996/04/19 19:49:06 mark Exp $ */
+
+/*
+ * Copyright (c) 1994-1996 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * rtc.c
+ *
+ * Routines to read and write the RTC and CMOS RAM
+ *
+ * Created : 13/10/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <machine/iic.h>
+#include <machine/rtc.h>
+
+struct rtc_softc {
+ struct device sc_dev;
+ int sc_flags;
+#define RTC_BROKEN 1
+#define RTC_OPEN 2
+};
+
+void rtcattach __P((struct device *parent, struct device *self, void *aux));
+int rtcmatch __P((struct device *parent, void *match, void *aux));
+
+/* Read a byte from CMOS RAM */
+
+int
+cmos_read(location)
+ int location;
+{
+ u_char buff;
+
+/*
+ * This commented code dates from when I was translating CMOS address
+ * from the RISCOS addresses. Now all addresses are specifed as
+ * actual addresses in the CMOS RAM
+ */
+
+/*
+ if (location > 0xF0)
+ return(-1);
+
+ if (location < 0xC0)
+ buff = location + 0x40;
+ else
+ buff = location - 0xB0;
+*/
+ buff = location;
+
+ if (iic_control(RTC_Write, &buff, 1))
+ return(-1);
+ if (iic_control(RTC_Read, &buff, 1))
+ return(-1);
+
+ return(buff);
+}
+
+
+/* Write a byte to CMOS RAM */
+
+int
+cmos_write(location, value)
+ int location;
+ int value;
+{
+ u_char buff[2];
+
+/*
+ * This commented code dates from when I was translating CMOS address
+ * from the RISCOS addresses. Now all addresses are specifed as
+ * actual addresses in the CMOS RAM
+ */
+
+/* if (location > 0xF0)
+ return(-1);
+
+ if (location < 0xC0)
+ buff = location + 0x40;
+ else
+ buff = location - 0xB0;
+*/
+ buff[0] = location;
+ buff[1] = value;
+
+ if (iic_control(RTC_Write, buff, 2))
+ return(-1);
+
+ return(0);
+}
+
+
+/* Hex to BCD and BCD to hex conversion routines */
+
+static inline int
+hexdectodec(n)
+ u_char n;
+{
+ return(((n >> 4) & 0x0F) * 10 + (n & 0x0F));
+}
+
+static inline int
+dectohexdec(n)
+ u_char n;
+{
+ return(((n / 10) << 4) + (n % 10));
+}
+
+
+/* Write the RTC data from an 8 byte buffer */
+
+int
+rtc_write(rtc)
+ rtc_t *rtc;
+{
+ u_char buff[8];
+
+ buff[0] = 1;
+
+ buff[1] = dectohexdec(rtc->rtc_centi);
+ buff[2] = dectohexdec(rtc->rtc_sec);
+ buff[3] = dectohexdec(rtc->rtc_min);
+ buff[4] = dectohexdec(rtc->rtc_hour) & 0x3f;
+ buff[5] = dectohexdec(rtc->rtc_day);
+ buff[6] = dectohexdec(rtc->rtc_mon);
+
+ if (iic_control(RTC_Write, buff, 7))
+ return(0);
+
+ cmos_write(RTC_ADDR_YEAR, rtc->rtc_year);
+ cmos_write(RTC_ADDR_CENT, rtc->rtc_cen);
+
+ return(1);
+}
+
+
+/* Read the RTC data into a 8 byte buffer */
+
+int
+rtc_read(rtc)
+ rtc_t *rtc;
+{
+ u_char buff[8];
+ int byte;
+
+ buff[0] = 0;
+
+ if (iic_control(RTC_Write, buff, 1))
+ return(0);
+
+ if (iic_control(RTC_Read, buff, 8))
+ return(0);
+
+ rtc->rtc_micro = 0;
+ rtc->rtc_centi = hexdectodec(buff[1] & 0xff);
+ rtc->rtc_sec = hexdectodec(buff[2] & 0x7f);
+ rtc->rtc_min = hexdectodec(buff[3] & 0x7f);
+ rtc->rtc_hour = hexdectodec(buff[4] & 0x3f);
+
+ /* If in 12 hour mode need to look at the AM/PM flag */
+
+ if (buff[4] & 0x80)
+ rtc->rtc_hour += (buff[4] & 0x40) ? 12 : 0;
+
+ rtc->rtc_day = hexdectodec(buff[5] & 0x3f);
+ rtc->rtc_mon = hexdectodec(buff[6] & 0x1f);
+
+ byte = cmos_read(RTC_ADDR_YEAR);
+ if (byte == -1)
+ return(0);
+ rtc->rtc_year = byte;
+
+ byte = cmos_read(RTC_ADDR_CENT);
+ if (byte == -1)
+ return(0);
+ rtc->rtc_cen = byte;
+
+ return(1);
+}
+
+
+struct cfattach rtc_ca = {
+ sizeof(struct rtc_softc), rtcmatch, rtcattach
+};
+
+struct cfdriver rtc_cd = {
+ NULL, "rtc", DV_DULL, 0
+};
+
+int
+rtcmatch(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+/* struct iicbus_attach_args *ib = aux;*/
+
+ return(1);
+}
+
+
+void
+rtcattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct rtc_softc *sc = (struct rtc_softc *)self;
+ struct iicbus_attach_args *ib = aux;
+ u_char buff[1];
+
+ sc->sc_flags |= RTC_BROKEN;
+ if ((ib->ib_addr & IIC_PCF8583_MASK) == IIC_PCF8583_ADDR) {
+ printf(": PCF8583");
+
+ buff[0] = 0;
+
+ if (iic_control(RTC_Write, buff, 1))
+ return;
+
+ if (iic_control(RTC_Read, buff, 1))
+ return;
+
+ printf(" clock base ");
+ switch (buff[0] & 0x30) {
+ case 0x00:
+ printf("32.768KHz");
+ break;
+ case 0x10:
+ printf("50Hz");
+ break;
+ case 0x20:
+ printf("event");
+ break;
+ case 0x30:
+ printf("test mode");
+ break;
+ }
+
+ if (buff[0] & 0x80)
+ printf(" stopped");
+ if (buff[0] & 0x04)
+ printf(" alarm enabled");
+ sc->sc_flags &= ~RTC_BROKEN;
+ }
+
+
+/*
+ * Initialise the time of day register.
+ * This is normally left to the filing system to do but not all
+ * filing systems call it e.g. cd9660
+ */
+
+ inittodr(0);
+
+ printf("\n");
+}
+
+
+int
+rtcopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct rtc_softc *sc;
+ int unit = minor(dev);
+
+ if (unit >= rtc_cd.cd_ndevs)
+ return(ENXIO);
+
+ sc = rtc_cd.cd_devs[unit];
+
+ if (!sc) return(ENXIO);
+
+ if (sc->sc_flags & RTC_OPEN) return(EBUSY);
+
+ sc->sc_flags |= RTC_OPEN;
+
+ return(0);
+}
+
+
+int
+rtcclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ int unit = minor(dev);
+ struct rtc_softc *sc = rtc_cd.cd_devs[unit];
+
+ sc->sc_flags &= ~RTC_OPEN;
+
+ return(0);
+}
+
+
+int
+rtcread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ int unit = minor(dev);
+ struct rtc_softc *sc = rtc_cd.cd_devs[unit];
+
+ return(ENXIO);
+}
+
+
+int
+rtcwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ int unit = minor(dev);
+ struct rtc_softc *sc = rtc_cd.cd_devs[unit];
+
+ return(ENXIO);
+}
+
+
+int
+rtcioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct rtc_softc *sc = rtc_cd.cd_devs[minor(dev)];
+
+/* switch (cmd) {
+ case RTCIOC_READ:
+ return(0);
+ } */
+
+ return(EINVAL);
+}
+
+/* End of rtc.c */
--- /dev/null
+/* $NetBSD: vidcaudio.c,v 1.3 1996/03/17 01:24:37 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the RiscBSD team.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Yikes just had a look at this and realised that it does not conform
+ * to Kernel Normal Form at all. I have fixed the first few functions
+ * but there are a lot more still to do - mark
+ */
+
+/*
+ * vidcaudio driver for RiscBSD by Melvin Tang-Richardson (c) 1995
+ *
+ * Interfaces with the NetBSD generic audio driver to provide SUN
+ * /dev/audio (partial) compatibility.
+ *
+ * Do not include me in conf.c. My interface is done by the generic
+ * audio driver. Put me in config file and files.arm32. Do not put
+ * the audio.c generic driver in them. I do the autoconfig for it.
+ *
+ * The following files need to be altered
+ *
+ * [files.arm32]
+ * device vidcaudio at mainbus :audio
+ * file arch/arm32/mainbus/vidcaudio.c vidcaudio needs-flag
+ * major { audio=36 }
+ *
+ * [conf.c]
+ * #include "audio.h"
+ * cdev_decl(audio)
+ *
+ * cdev_audio_init(NAUDIO,audio) /* 36: generic audio I/O */
+ *
+ * [GENERIC]
+ * vidcaudio0 at mainbus? base 0x00000000
+ *
+ */
+
+#include <sys/param.h> /* proc.h */
+#include <sys/types.h> /* dunno */
+#include <sys/conf.h> /* autoconfig functions */
+#include <sys/device.h> /* device calls */
+#include <sys/proc.h> /* device calls */
+#include <sys/audioio.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+#include <dev/audio_if.h>
+
+#include <machine/irqhandler.h>
+#include <machine/iomd.h>
+#include <machine/vidc.h>
+#include <machine/katelib.h> /* ReadByte etc. */
+
+#include <arm32/mainbus/mainbus.h>
+#include "waveform.h"
+#include "vidcaudio.h"
+
+#undef DEBUG
+
+struct audio_general {
+ int in_sr;
+ int out_sr;
+ vm_offset_t silence;
+ irqhandler_t ih;
+
+ void (*intr) ();
+ void *arg;
+
+ vm_offset_t next_cur;
+ vm_offset_t next_end;
+ void (*next_intr) ();
+ void *next_arg;
+
+ int buffer;
+ int in_progress;
+
+ int open;
+} ag;
+
+struct vidcaudio_softc {
+ struct device device;
+ int iobase;
+
+ int open;
+
+ u_int encoding;
+ int inport;
+ int outport;
+};
+
+int vidcaudio_probe __P((struct device *parent, struct device *match, void *aux));
+void vidcaudio_attach __P((struct device *parent, struct device *self, void *aux));
+int vidcaudio_open __P((dev_t dev, int flags));
+void vidcaudio_close __P((void *addr));
+
+int vidcaudio_intr __P((void *arg));
+int vidcaudio_dma_program __P((vm_offset_t cur, vm_offset_t end, void (*intr)(), void *arg));
+void vidcaudio_dummy_routine __P((void *arg));
+int vidcaudio_stereo __P((int channel, int position));
+int vidcaudio_rate __P((int rate));
+void vidcaudio_shutdown __P((void));
+int vidcaudio_hw_attach __P((struct vidcaudio_softc *sc));
+
+struct cfattach vidcaudio_ca = {
+ sizeof(struct vidcaudio_softc), vidcaudio_probe, vidcaudio_attach
+};
+
+struct cfdriver vidcaudio_cd = {
+ NULL, "vidcaudio", DV_DULL
+};
+
+
+void
+vidcaudio_beep_generate()
+{
+ vidcaudio_dma_program ( ag.silence, ag.silence+sizeof(beep_waveform)-16,
+ vidcaudio_dummy_routine, NULL );
+}
+
+
+int
+vidcaudio_probe(parent, match, aux)
+ struct device *parent;
+ struct device *match;
+ void *aux;
+{
+ int id;
+
+ id = ReadByte(IOMD_ID0) | ReadByte(IOMD_ID1) << 8;
+
+/* So far I only know about this IOMD */
+
+ switch (id) {
+ case RPC600_IOMD_ID:
+ return(1);
+ break;
+ default:
+ printf("vidcaudio: Unknown IOMD id=%04x", id);
+ break;
+ }
+
+ return (0);
+}
+
+
+void
+vidcaudio_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct mainbus_attach_args *mb = aux;
+ struct vidcaudio_softc *sc = (void *)self;
+
+ sc->iobase = mb->mb_iobase;
+
+ sc->open = 0;
+ sc->encoding = 0;
+ sc->inport = 0;
+ sc->outport = 0;
+ ag.in_sr = 24*1024;
+ ag.out_sr = 24*1024;
+ ag.in_progress = 0;
+
+ ag.next_cur = 0;
+ ag.next_end = 0;
+ ag.next_intr = NULL;
+ ag.next_arg = NULL;
+
+ vidcaudio_rate(32);
+
+/* Program the silence buffer and reset the DMA channel */
+
+ ag.silence = kmem_alloc(kernel_map, NBPG);
+ if (ag.silence == NULL)
+ panic("vidcaudio: Cannot allocate memory\n");
+
+ bzero((char *)ag.silence, NBPG);
+ bcopy((char *)beep_waveform, (char *)ag.silence, sizeof(beep_waveform));
+
+ ag.buffer = 0;
+
+ /* Install the irq handler for the DMA interrupt */
+ ag.ih.ih_func = vidcaudio_intr;
+ ag.ih.ih_arg = NULL;
+ ag.ih.ih_level = IPL_NONE;
+
+ ag.intr = NULL;
+ ag.nextintr = NULL;
+
+ disable_irq(IRQ_DMASCH0);
+
+ if (irq_claim(IRQ_DMASCH0, &(ag.ih)))
+ panic("vidcaudio: couldn't claim IRQ_DMASCH0");
+
+ disable_irq(IRQ_DMASCH0);
+
+ vidcaudio_dma_program(ag.silence, ag.silence+NBPG-16,
+ vidcaudio_dummy_routine, NULL);
+
+ vidcaudio_hw_attach(sc);
+
+#ifdef DEBUG
+ printf(" UNDER DEVELOPMENT (nuts)\n");
+#endif
+}
+
+int
+vidcaudio_open(dev, flags)
+ dev_t dev;
+ int flags;
+{
+ struct vidcaudio_softc *sc;
+ int unit = AUDIOUNIT (dev);
+ int s;
+
+#ifdef DEBUG
+ printf("DEBUG: vidcaudio_open called\n");
+#endif
+
+ if (unit >= vidcaudio_cd.cd_ndevs)
+ return ENODEV;
+
+ sc = vidcaudio_cd.cd_devs[unit];
+
+ if (!sc)
+ return ENXIO;
+
+ s = splhigh();
+
+ if (sc->open != 0) {
+ (void)splx(s);
+ return EBUSY;
+ }
+
+ sc->open=1;
+ ag.open=1;
+
+ (void)splx(s);
+ return 0;
+}
+
+void
+vidcaudio_close(addr)
+ void *addr;
+{
+ struct vidcaudio_softc *sc = addr;
+
+ vidcaudio_shutdown ();
+
+#ifdef DEBUG
+ printf("DEBUG: vidcaudio_close called\n");
+#endif
+
+ sc->open = 0;
+ ag.open = 0;
+}
+
+/* ************************************************************************* *
+ | Interface to the generic audio driver |
+ * ************************************************************************* */
+
+int vidcaudio_set_in_sr __P((void *, u_long));
+u_long vidcaudio_get_in_sr __P((void *));
+int vidcaudio_set_out_sr __P((void *, u_long));
+u_long vidcaudio_get_out_sr __P((void *));
+int vidcaudio_query_encoding __P((void *, struct audio_encoding *));
+int vidcaudio_set_encoding __P((void *, u_int));
+int vidcaudio_get_encoding __P((void *));
+int vidcaudio_set_precision __P((void *, u_int));
+int vidcaudio_getprecision __P((void *));
+int vidcaudio_set_channels __P((void *, int));
+int vidcaudio_get_channels __P((void *));
+int vidcaudio_round_blocksize __P((void *, int));
+int vidcaudio_set_out_port __P((void *, int));
+int vidcaudio_get_out_port __P((void *));
+int vidcaudio_set_in_port __P((void *, int));
+int vidcaudio_get_in_port __P((void *));
+int vidcaudio_commit_settings __P((void *));
+u_int vidcaudio_get_silence __P((int));
+void vidcaudio_sw_encode __P((int, u_char *, int));
+void vidcaudio_sw_decode __P((int, u_char *, int));
+int vidcaudio_start_output __P((void *, void *, int, void (*)(), void *));
+int vidcaudio_start_input __P((void *, void *, int, void (*)(), void *));
+int vidcaudio_halt_output __P((void *));
+int vidcaudio_halt_input __P((void *));
+int vidcaudio_cont_output __P((void *));
+int vidcaudio_cont_input __P((void *));
+int vidcaudio_speaker_ctl __P((void *, int));
+int vidcaudio_getdev __P((void *, struct audio_device *));
+int vidcaudio_setfd __P((void *, int));
+int vidcaudio_set_port __P((void *, mixer_ctrl_t *));
+int vidcaudio_get_port __P((void *, mixer_ctrl_t *));
+int vidcaudio_query_devinfo __P((void *, mixer_devinfo_t *));
+
+struct audio_device vidcaudio_device = {
+ "VidcAudio 8-bit",
+ "x",
+ "vidcaudio"
+};
+
+int
+vidcaudio_set_in_sr(addr, sr)
+ void *addr;
+ u_long sr;
+{
+ ag.in_sr = sr;
+ return 0;
+}
+
+u_long
+vidcaudio_get_in_sr(addr)
+ void *addr;
+{
+ return ag.in_sr;
+}
+
+int
+vidcaudio_set_out_sr(addr, sr)
+ void *addr;
+ u_long sr;
+{
+ ag.out_sr = sr;
+ return 0;
+}
+
+u_long
+vidcaudio_get_out_sr(addr)
+ void *addr;
+{
+ return(ag.out_sr);
+}
+
+int vidcaudio_query_encoding ( void *addr, struct audio_encoding *fp )
+{
+ switch ( fp->index )
+ {
+ case 0:
+ strcpy (fp->name, "vidc" );
+ fp->format_id = AUDIO_ENCODING_ULAW;
+ break;
+
+ default:
+ return (EINVAL);
+ }
+ return 0;
+}
+
+int vidcaudio_set_encoding ( void *addr, u_int enc )
+{
+ struct vidcaudio_softc *sc = addr;
+
+ switch (enc)
+ {
+ case AUDIO_ENCODING_ULAW:
+#ifdef DEBUG
+ printf ( "DEBUG: Set ulaw encoding\n" );
+#endif
+ sc->encoding = enc;
+ break;
+
+ default:
+ return (EINVAL);
+ }
+ return 0;
+}
+
+int vidcaudio_get_encoding ( void *addr )
+{
+ struct vidcaudio_softc *sc = addr;
+ return sc->encoding;
+}
+
+int vidcaudio_set_precision ( void *addr, u_int prec )
+{
+ if (prec != 8)
+ return EINVAL;
+ return 0;
+}
+
+int vidcaudio_get_precision ( void *addr )
+{
+ return (8);
+}
+
+int vidcaudio_set_channels ( void *addr, int chans )
+{
+ if ( chans!=1 )
+ return EINVAL;
+
+ return 0;
+}
+
+int vidcaudio_get_channels ( void *addr )
+{
+ return 1;
+}
+
+int vidcaudio_round_blocksize ( void *addr, int blk )
+{
+ if (blk>NBPG) blk=NBPG;
+ return blk;
+}
+
+int vidcaudio_set_out_port ( void *addr, int port )
+{
+ struct vidcaudio_softc *sc = addr;
+ sc->outport = port;
+ return 0;
+}
+
+int vidcaudio_get_out_port ( void *addr )
+{
+ struct vidcaudio_softc *sc = addr;
+ return sc->outport;
+}
+
+int vidcaudio_set_in_port ( void *addr, int port )
+{
+ struct vidcaudio_softc *sc = addr;
+ sc->inport = port;
+ return 0;
+}
+
+int vidcaudio_get_in_port ( void *addr )
+{
+ struct vidcaudio_softc *sc = addr;
+ return sc->inport;
+}
+
+int vidcaudio_commit_settings ( void *addr )
+{
+#ifdef DEBUG
+printf ( "DEBUG: committ_settings\n" );
+#endif
+ return 0;
+}
+
+u_int vidcaudio_get_silence ( int enc )
+{
+ switch (enc)
+ {
+ case AUDIO_ENCODING_ULAW:
+ return 0x7f;
+
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+void vidcaudio_sw_encode ( int e, u_char *p, int cc )
+{
+#ifdef DEBUG
+ printf ( "DEBUG: sw_encode\n" );
+#endif
+ return;
+}
+
+void vidcaudio_sw_decode ( int e, u_char *p, int cc )
+{
+#ifdef DEBUG
+ printf ( "DEBUG: sw_decode\n" );
+#endif
+}
+
+#define ROUND(s) ( ((int)s) & (~(NBPG-1)) )
+
+int vidcaudio_start_output ( void *addr, void *p, int cc,
+ void (*intr)(), void *arg )
+{
+ /* I can only DMA inside 1 page */
+
+#ifdef DEBUG
+ printf ( "vidcaudio_start_output (%d) %08x %08x\n", cc, intr, arg );
+#endif
+
+ if ( ROUND(p) != ROUND(p+cc) )
+ {
+ /* If it's over a page I can fix it up by copying it into my buffer */
+
+#ifdef DEBUG
+ printf ( "vidcaudio: DMA over page boundary requested. Fixing up\n" );
+#endif
+ bcopy ( (char *)ag.silence, p, cc>NBPG ? NBPG : cc );
+ p=(void *)ag.silence;
+
+ /* I can't DMA any more than that, but it is possible to fix it up */
+ /* by handling multiple buffers and only interrupting the audio */
+ /* driver after sending out all the stuff it gave me. That it more */
+ /* than I can be bothered to do right now and it probablly wont */
+ /* happen so I'll just truncate the buffer and tell the user */
+
+ if ( cc>NBPG )
+ {
+ printf ( "vidcaudio: DMA buffer truncated. I could fix this up\n" );
+ cc=NBPG;
+ }
+ }
+ vidcaudio_dma_program ( (vm_offset_t)p, (vm_offset_t)(p+cc), intr, arg );
+ return 0;
+}
+
+int vidcaudio_start_input ( void *addr, void *p, int cc,
+ void (*intr)(), void *arg )
+{
+ return EIO;
+}
+
+int vidcaudio_halt_output ( void *addr )
+{
+#ifdef DEBUG
+ printf ( "DEBUG: vidcaudio_halt_output\n" );
+#endif
+ return EIO;
+}
+
+int vidcaudio_halt_input ( void *addr )
+{
+#ifdef DEBUG
+ printf ( "DEBUG: vidcaudio_halt_output\n" );
+#endif
+ return EIO;
+}
+
+int vidcaudio_cont_output ( void *addr )
+{
+#ifdef DEBUG
+ printf ( "DEBUG: vidcaudio_halt_output\n" );
+#endif
+ return EIO;
+}
+
+int vidcaudio_cont_input ( void *addr )
+{
+#ifdef DEBUG
+ printf ( "DEBUG: vidcaudio_halt_output\n" );
+#endif
+ return EIO;
+}
+
+int vidcaudio_speaker_ctl ( void *addr, int newstate )
+{
+#ifdef DEBUG
+ printf ( "DEBUG: vidcaudio_speaker_ctl\n" );
+#endif
+ return 0;
+}
+
+int vidcaudio_getdev ( void *addr, struct audio_device *retp )
+{
+ *retp = vidcaudio_device;
+ return 0;
+}
+
+
+int vidcaudio_setfd ( void *addr, int flag )
+{
+ return ENOTTY;
+}
+
+int vidcaudio_set_port ( void *addr, mixer_ctrl_t *cp )
+{
+ return EINVAL;
+}
+
+int vidcaudio_get_port ( void *addr, mixer_ctrl_t *cp )
+{
+ return EINVAL;
+}
+
+int vidcaudio_query_devinfo ( void *addr, mixer_devinfo_t *dip )
+{
+ return 0;
+}
+
+struct audio_hw_if vidcaudio_hw_if = {
+ vidcaudio_open,
+ vidcaudio_close,
+ NULL,
+ vidcaudio_set_in_sr,
+ vidcaudio_get_in_sr,
+ vidcaudio_set_out_sr,
+ vidcaudio_get_out_sr,
+ vidcaudio_query_encoding,
+ vidcaudio_set_encoding,
+ vidcaudio_get_encoding,
+ vidcaudio_set_precision,
+ vidcaudio_get_precision,
+ vidcaudio_set_channels,
+ vidcaudio_get_channels,
+ vidcaudio_round_blocksize,
+ vidcaudio_set_out_port,
+ vidcaudio_get_out_port,
+ vidcaudio_set_in_port,
+ vidcaudio_get_in_port,
+ vidcaudio_commit_settings,
+ vidcaudio_get_silence,
+ vidcaudio_sw_encode,
+ vidcaudio_sw_decode,
+ vidcaudio_start_output,
+ vidcaudio_start_input,
+ vidcaudio_halt_output,
+ vidcaudio_halt_input,
+ vidcaudio_cont_output,
+ vidcaudio_cont_input,
+ vidcaudio_speaker_ctl,
+ vidcaudio_getdev,
+ vidcaudio_setfd,
+ vidcaudio_set_port,
+ vidcaudio_get_port,
+ vidcaudio_query_devinfo,
+ 0, /* not full duplex */
+ 0
+};
+
+void vidcaudio_dummy_routine ( void *arg )
+{
+#ifdef DEBUG
+ printf ( "vidcaudio_dummy_routine\n" );
+#endif
+}
+
+int vidcaudio_hw_attach ( struct vidcaudio_softc *sc )
+{
+ return ( audio_hardware_attach ( &vidcaudio_hw_if, sc ) );
+}
+
+int vidcaudio_rate ( int rate )
+{
+ WriteWord ( VIDC_BASE, VIDC_SFR | rate );
+ return 0;
+}
+
+int vidcaudio_stereo ( int channel, int position )
+{
+ if ( channel<0 ) return EINVAL;
+ if ( channel>7 ) return EINVAL;
+ channel = channel<<24 | VIDC_SIR0;
+ WriteWord ( VIDC_BASE, channel|position );
+ return 0;
+}
+
+#define PHYS(x) (pmap_extract( kernel_pmap, ((x)&PG_FRAME) ))
+
+/*
+ * Program the next buffer to be used
+ * This function must be re-entrant, maximum re-entrancy of 2
+ */
+
+#define FLAGS (0)
+
+int vidcaudio_dma_program ( vm_offset_t cur, vm_offset_t end,
+ void (*intr)(), void *arg )
+{
+ /* If there isn't a transfer in progress then start a new one */
+ if ( ag.in_progress==0 )
+ {
+ ag.buffer = 0;
+ WriteWord ( IOMD_SD0CR, 0x90 ); /* Reset State Machine */
+ WriteWord ( IOMD_SD0CR, 0x30 ); /* Reset State Machine */
+
+ WriteWord ( IOMD_SD0CURB, PHYS(cur) );
+ WriteWord ( IOMD_SD0ENDB, PHYS(end-16)|FLAGS );
+ WriteWord ( IOMD_SD0CURA, PHYS(cur) );
+ WriteWord ( IOMD_SD0ENDA, PHYS(end-16)|FLAGS );
+
+ ag.in_progress = 1;
+
+ ag.next_cur = ag.next_end = 0;
+ ag.next_intr = ag.next_arg = 0;
+
+ ag.intr = intr;
+ ag.arg = arg;
+
+ /* The driver 'clicks' between buffer swaps, leading me to think */
+ /* that the fifo is much small than on other sound cards. So */
+ /* so I'm going to have to do some tricks here */
+
+ (*ag.intr)(ag.arg); /* Schedule the next buffer */
+ ag.intr = vidcaudio_dummy_routine; /* Already done this */
+ ag.arg = NULL;
+
+#ifdef PRINT
+printf ( "vidcaudio: start output\n" );
+#endif
+#ifdef DEBUG
+ printf ( "SE" );
+#endif
+ enable_irq ( IRQ_DMASCH0 );
+ }
+ else
+ {
+ /* Otherwise schedule the next one */
+ if ( ag.next_cur!=0 )
+ {
+ /* If there's one scheduled then complain */
+ printf ( "vidcaudio: Buffer already Q'ed\n" );
+ return EIO;
+ }
+ else
+ {
+ /* We're OK to schedule it now */
+ ag.buffer = (++ag.buffer) & 1;
+ ag.next_cur = PHYS(cur);
+ ag.next_end = PHYS(end-16);
+ ag.next_intr = intr;
+ ag.next_arg = arg;
+#ifdef DEBUG
+printf ( "s" );
+#endif
+ }
+ }
+ return 0;
+}
+
+void vidcaudio_shutdown ( void )
+{
+ /* Shut down the channel */
+ ag.intr = NULL;
+ ag.in_progress = 0;
+#ifdef PRINT
+printf ( "vidcaudio: stop output\n" );
+#endif
+ WriteWord ( IOMD_SD0CURB, ag.silence );
+ WriteWord ( IOMD_SD0ENDB, (ag.silence + NBPG - 16) | (1<<30) );
+ disable_irq ( IRQ_DMASCH0 );
+}
+
+int vidcaudio_intr ( void *arg )
+{
+ int status = ReadByte(IOMD_SD0ST);
+ void (*nintr)();
+ void *narg;
+ void (*xintr)();
+ void *xarg;
+ int xcur, xend;
+ WriteWord ( IOMD_DMARQ, 0x10 );
+
+#ifdef PRINT
+ printf ( "I" );
+#endif
+
+ if ( ag.open==0 )
+ {
+ vidcaudio_shutdown ();
+ return 0;
+ }
+
+ /* Have I got the generic audio device attached */
+
+#ifdef DEBUG
+ printf ( "[B%01x]", status );
+#endif
+
+ nintr=ag.intr;
+ narg=ag.arg;
+ ag.intr = NULL;
+
+ xintr=ag.next_intr;
+ xarg=ag.next_arg;
+ xcur=ag.next_cur;
+ xend=ag.next_end;
+ ag.next_cur = 0;
+ ag.intr = xintr;
+ ag.arg = xarg;
+
+ if ( nintr )
+ {
+#ifdef DEBUG
+ printf ( "i" );
+#endif
+ (*nintr)(narg);
+ }
+
+ if ( xcur==0 )
+ {
+ vidcaudio_shutdown ();
+ }
+ else
+ {
+#define OVERRUN (0x04)
+#define INTERRUPT (0x02)
+#define BANK_A (0x00)
+#define BANK_B (0x01)
+ switch ( status&0x7 )
+ {
+ case (INTERRUPT|BANK_A):
+#ifdef PRINT
+printf( "B" );
+#endif
+ WriteWord ( IOMD_SD0CURB, xcur );
+ WriteWord ( IOMD_SD0ENDB, xend|FLAGS );
+ break;
+
+ case (INTERRUPT|BANK_B):
+#ifdef PRINT
+printf( "A" );
+#endif
+ WriteWord ( IOMD_SD0CURA, xcur );
+ WriteWord ( IOMD_SD0ENDA, xend|FLAGS );
+ break;
+
+ case (OVERRUN|INTERRUPT|BANK_A):
+#ifdef PRINT
+printf( "A" );
+#endif
+ WriteWord ( IOMD_SD0CURA, xcur );
+ WriteWord ( IOMD_SD0ENDA, xend|FLAGS );
+ break;
+
+ case (OVERRUN|INTERRUPT|BANK_B):
+#ifdef PRINT
+printf( "B" );
+#endif
+ WriteWord ( IOMD_SD0CURB, xcur );
+ WriteWord ( IOMD_SD0ENDB, xend|FLAGS );
+ break;
+ }
+/*
+ ag.next_cur = 0;
+ ag.intr = xintr;
+ ag.arg = xarg;
+*/
+ }
+#ifdef PRINT
+printf ( "i" );
+#endif
+
+ if ( ag.next_cur==0 )
+ {
+ (*ag.intr)(ag.arg); /* Schedule the next buffer */
+ ag.intr = vidcaudio_dummy_routine; /* Already done this */
+ ag.arg = NULL;
+ }
+ return 0;
+}
+
+
--- /dev/null
+/* $NetBSD: waveform.h,v 1.2 1996/03/18 20:50:06 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+static unsigned char beep_waveform[] = {
+ 0x00, 0x06, 0x18, 0x2a, 0x3e, 0x4a, 0x54, 0x60,
+ 0x64, 0x68, 0x6a, 0x6a, 0x66, 0x62, 0x54, 0x3e,
+ 0x00, 0x45, 0x61, 0x6f, 0x7f, 0x87, 0x8d, 0x91,
+ 0x93, 0x95, 0x93, 0x91, 0x8b, 0x85, 0x73, 0x59,
+ 0x00, 0x5c, 0x78, 0x8a, 0x96, 0xa0, 0xa6, 0xa8,
+ 0xaa, 0xaa, 0xa8, 0xa6, 0xa2, 0x94, 0x86, 0x6a,
+ 0x00, 0x6b, 0x8b, 0x9d, 0xa7, 0xaf, 0xb5, 0xb9,
+ 0xbb, 0xbb, 0xb9, 0xb3, 0xad, 0xa5, 0x93, 0x77,
+ 0x00, 0x78, 0x96, 0xa8, 0xb2, 0xbc, 0xc2, 0xc4,
+ 0xc6, 0xc6, 0xc4, 0xc0, 0xb8, 0xac, 0x9e, 0x82,
+ 0x00, 0x83, 0xa3, 0xb1, 0xbf, 0xc5, 0xcb, 0xcd,
+ 0xcf, 0xcf, 0xcd, 0xc9, 0xc3, 0xb7, 0xa7, 0x89,
+ 0x00, 0x88, 0xa8, 0xb8, 0xc4, 0xcc, 0xd0, 0xd4,
+ 0xd6, 0xd4, 0xd2, 0xce, 0xc8, 0xbe, 0xac, 0x8e,
+ 0x00, 0x8f, 0xaf, 0xc3, 0xcb, 0xd3, 0xd9, 0xdd,
+ 0xdf, 0xdd, 0xdb, 0xd5, 0xcf, 0xc5, 0xb3, 0x95,
+ 0x00, 0x96, 0xb4, 0xc6, 0xd0, 0xd8, 0xe0, 0xe2,
+ 0xe4, 0xe2, 0xe2, 0xdc, 0xd2, 0xc8, 0xb8, 0x9a,
+ 0x00, 0x9d, 0xbb, 0xcb, 0xd7, 0xe1, 0xe5, 0xe7,
+ 0xe9, 0xe7, 0xe5, 0xe3, 0xd9, 0xcf, 0xbf, 0xa1,
+ 0x00, 0xa2, 0xc0, 0xce, 0xdc, 0xe4, 0xe8, 0xea,
+ 0xec, 0xea, 0xe8, 0xe4, 0xde, 0xd2, 0xc2, 0xa4,
+ 0x00, 0xa5, 0xc5, 0xd5, 0xe3, 0xe7, 0xed, 0xef,
+ 0xf1, 0xef, 0xed, 0xe9, 0xe3, 0xd7, 0xc7, 0xa9,
+ 0x00, 0xa8, 0xc6, 0xd8, 0xe4, 0xea, 0xee, 0xf2,
+ 0xf4, 0xf2, 0xf0, 0xec, 0xe6, 0xda, 0xc8, 0xaa,
+ 0x00, 0xab, 0xcb, 0xdd, 0xe7, 0xef, 0xf3, 0xf7,
+ 0xf9, 0xf7, 0xf5, 0xef, 0xe9, 0xdf, 0xcd, 0xaf,
+ 0x00, 0xae, 0xcc, 0xe0, 0xea, 0xf0, 0xf6, 0xfa,
+ 0xfc, 0xfa, 0xf8, 0xf2, 0xea, 0xe2, 0xd0, 0xb0,
+ 0x00, 0xb1, 0xd1, 0xe3, 0xed, 0xf5, 0xfb, 0xff,
+ 0xff, 0xff, 0xfb, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4,
+ 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff,
+ 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5,
+ 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe,
+ 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb2,
+ 0x00, 0xb3, 0xd3, 0xe5, 0xef, 0xf7, 0xfb, 0xff,
+ 0xff, 0xff, 0xfb, 0xf5, 0xef, 0xe5, 0xd1, 0xb3,
+ 0x00, 0xb2, 0xd0, 0xe4, 0xec, 0xf4, 0xfa, 0xfe,
+ 0xfe, 0xfe, 0xfa, 0xf4, 0xec, 0xe4, 0xd0, 0xb2,
+ 0x00, 0xb3, 0xd1, 0xe5, 0xed, 0xf5, 0xfb, 0xff,
+ 0xff, 0xff, 0xfb, 0xf5, 0xed, 0xe5, 0xd1, 0xb3,
+ 0x00, 0xb2, 0xd0, 0xe4, 0xec, 0xf4, 0xfa, 0xfc,
+ 0xfe, 0xfc, 0xfa, 0xf4, 0xec, 0xe2, 0xd0, 0xb2,
+ 0x00, 0xb3, 0xd1, 0xe3, 0xed, 0xf5, 0xf9, 0xfd,
+ 0xff, 0xfd, 0xf9, 0xf5, 0xed, 0xe3, 0xd1, 0xb1,
+ 0x00, 0xb0, 0xd0, 0xe2, 0xec, 0xf2, 0xf8, 0xfc,
+ 0xfc, 0xfc, 0xf8, 0xf2, 0xec, 0xe2, 0xd0, 0xb0,
+ 0x00, 0xb1, 0xcf, 0xe3, 0xed, 0xf3, 0xf9, 0xfd,
+ 0xfd, 0xfd, 0xf9, 0xf3, 0xed, 0xe3, 0xcf, 0xb1,
+ 0x00, 0xb0, 0xce, 0xe2, 0xea, 0xf2, 0xf8, 0xfa,
+ 0xfc, 0xfa, 0xf8, 0xf2, 0xea, 0xe2, 0xce, 0xb0,
+ 0x00, 0xb1, 0xcf, 0xe3, 0xeb, 0xf3, 0xf9, 0xfb,
+ 0xfd, 0xfb, 0xf7, 0xf3, 0xeb, 0xe3, 0xcf, 0xb1,
+ 0x00, 0xb0, 0xce, 0xe2, 0xea, 0xf2, 0xf6, 0xfa,
+ 0xfa, 0xfa, 0xf6, 0xf2, 0xea, 0xe2, 0xce, 0xae,
+ 0x00, 0xaf, 0xcf, 0xe3, 0xeb, 0xf1, 0xf7, 0xfb,
+ 0xfb, 0xfb, 0xf7, 0xf1, 0xeb, 0xe1, 0xcf, 0xaf,
+ 0x00, 0xae, 0xce, 0xe0, 0xea, 0xf0, 0xf6, 0xf8,
+ 0xfa, 0xf8, 0xf6, 0xf0, 0xea, 0xe0, 0xcc, 0xae,
+ 0x00, 0xaf, 0xcd, 0xe1, 0xeb, 0xf1, 0xf7, 0xf9,
+ 0xfb, 0xf9, 0xf7, 0xf1, 0xe9, 0xe1, 0xcd, 0xaf,
+ 0x00, 0xae, 0xcc, 0xe0, 0xe8, 0xf0, 0xf4, 0xf8,
+ 0xf8, 0xf8, 0xf4, 0xf0, 0xe8, 0xe0, 0xcc, 0xae,
+ 0x00, 0xaf, 0xcd, 0xe1, 0xe9, 0xf1, 0xf5, 0xf9,
+ 0xf9, 0xf9, 0xf5, 0xf1, 0xe9, 0xdf, 0xcd, 0xad,
+ 0x00, 0xac, 0xcc, 0xde, 0xe8, 0xee, 0xf4, 0xf6,
+ 0xf8, 0xf6, 0xf4, 0xee, 0xe8, 0xde, 0xcc, 0xac,
+ 0x00, 0xad, 0xcd, 0xdf, 0xe9, 0xef, 0xf5, 0xf7,
+ 0xf9, 0xf7, 0xf5, 0xef, 0xe9, 0xdf, 0xcb, 0xad,
+ 0x00, 0xac, 0xca, 0xde, 0xe8, 0xee, 0xf2, 0xf6,
+ 0xf6, 0xf6, 0xf2, 0xee, 0xe8, 0xde, 0xca, 0xac,
+ 0x00, 0xad, 0xcb, 0xdd, 0xe7, 0xef, 0xf3, 0xf7,
+ 0xf7, 0xf7, 0xf3, 0xef, 0xe7, 0xdd, 0xcb, 0xad,
+ 0x00, 0xac, 0xca, 0xdc, 0xe6, 0xee, 0xf2, 0xf4,
+ 0xf6, 0xf4, 0xf2, 0xee, 0xe6, 0xdc, 0xca, 0xaa,
+ 0x00, 0xab, 0xcb, 0xdd, 0xe7, 0xed, 0xf3, 0xf5,
+ 0xf7, 0xf5, 0xf3, 0xed, 0xe7, 0xdd, 0xcb, 0xab,
+ 0x00, 0xaa, 0xca, 0xdc, 0xe6, 0xec, 0xf2, 0xf4,
+ 0xf4, 0xf4, 0xf0, 0xec, 0xe6, 0xda, 0xc8, 0xaa,
+ 0x00, 0xab, 0xc9, 0xdb, 0xe7, 0xed, 0xf1, 0xf5,
+ 0xf5, 0xf5, 0xf1, 0xed, 0xe7, 0xdb, 0xc9, 0xab,
+ 0x00, 0xaa, 0xc8, 0xda, 0xe6, 0xec, 0xf0, 0xf4,
+ 0xf4, 0xf2, 0xf0, 0xec, 0xe6, 0xda, 0xc8, 0xaa,
+ 0x00, 0xab, 0xc9, 0xdb, 0xe5, 0xed, 0xf1, 0xf3,
+ 0xf5, 0xf3, 0xf1, 0xeb, 0xe5, 0xdb, 0xc9, 0xa9,
+ 0x00, 0xa8, 0xc8, 0xd8, 0xe4, 0xea, 0xf0, 0xf2,
+ 0xf2, 0xf2, 0xf0, 0xea, 0xe4, 0xd8, 0xc8, 0xa8,
+ 0x00, 0xa9, 0xc9, 0xd9, 0xe5, 0xeb, 0xef, 0xf3,
+ 0xf3, 0xf3, 0xef, 0xeb, 0xe5, 0xd9, 0xc9, 0xa9,
+ 0x00, 0xa8, 0xc6, 0xd8, 0xe4, 0xea, 0xee, 0xf2,
+ 0xf2, 0xf2, 0xee, 0xea, 0xe4, 0xd8, 0xc6, 0xa8,
+ 0x00, 0xa9, 0xc7, 0xd9, 0xe5, 0xeb, 0xef, 0xf1,
+ 0xf3, 0xf1, 0xef, 0xeb, 0xe5, 0xd7, 0xc7, 0xa9,
+ 0x00, 0xa8, 0xc6, 0xd6, 0xe4, 0xea, 0xee, 0xf0,
+ 0xf0, 0xf0, 0xee, 0xe8, 0xe2, 0xd6, 0xc6, 0xa8,
+ 0x00, 0xa7, 0xc7, 0xd7, 0xe3, 0xe9, 0xed, 0xf1,
+ 0xf1, 0xf1, 0xed, 0xe9, 0xe3, 0xd7, 0xc7, 0xa7,
+ 0x00, 0xa6, 0xc6, 0xd6, 0xe2, 0xe8, 0xec, 0xf0,
+ 0xf0, 0xf0, 0xec, 0xe8, 0xe2, 0xd6, 0xc6, 0xa6,
+ 0x00, 0xa7, 0xc5, 0xd7, 0xe3, 0xe9, 0xed, 0xef,
+ 0xf1, 0xef, 0xed, 0xe9, 0xe3, 0xd5, 0xc5, 0xa7,
+ 0x00, 0xa6, 0xc4, 0xd4, 0xe2, 0xe8, 0xec, 0xee,
+ 0xee, 0xee, 0xec, 0xe8, 0xe2, 0xd4, 0xc4, 0xa6,
+ 0x00, 0xa7, 0xc5, 0xd5, 0xe3, 0xe7, 0xed, 0xef,
+ 0xef, 0xef, 0xeb, 0xe7, 0xe3, 0xd5, 0xc5, 0xa7,
+ 0x00, 0xa6, 0xc4, 0xd4, 0xe0, 0xe6, 0xea, 0xee,
+ 0xee, 0xee, 0xea, 0xe6, 0xe0, 0xd4, 0xc4, 0xa4,
+ 0x00, 0xa5, 0xc5, 0xd3, 0xe1, 0xe7, 0xeb, 0xed,
+ 0xef, 0xed, 0xeb, 0xe7, 0xe1, 0xd3, 0xc5, 0xa5,
+ 0x00, 0xa4, 0xc4, 0xd2, 0xe0, 0xe6, 0xea, 0xec,
+ 0xec, 0xec, 0xea, 0xe6, 0xe0, 0xd2, 0xc2, 0xa4,
+ 0x00, 0xa5, 0xc3, 0xd3, 0xdf, 0xe7, 0xeb, 0xed,
+ 0xed, 0xed, 0xeb, 0xe7, 0xdf, 0xd3, 0xc3, 0xa5,
+ 0x00, 0xa4, 0xc2, 0xd2, 0xde, 0xe4, 0xe8, 0xec,
+ 0xec, 0xec, 0xe8, 0xe4, 0xde, 0xd0, 0xc2, 0xa4,
+ 0x00, 0xa5, 0xc3, 0xd1, 0xdf, 0xe5, 0xe9, 0xeb,
+ 0xed, 0xeb, 0xe9, 0xe5, 0xdf, 0xd1, 0xc3, 0xa3,
+ 0x00, 0xa2, 0xc2, 0xd0, 0xdc, 0xe4, 0xe8, 0xea,
+ 0xea, 0xea, 0xe8, 0xe4, 0xdc, 0xd0, 0xc2, 0xa2,
+ 0x00, 0xa3, 0xc3, 0xd1, 0xdd, 0xe5, 0xe9, 0xeb,
+ 0xeb, 0xeb, 0xe9, 0xe5, 0xdd, 0xd1, 0xc1, 0xa3,
+ 0x00, 0xa2, 0xc0, 0xce, 0xdc, 0xe4, 0xe6, 0xea,
+ 0xea, 0xea, 0xe6, 0xe4, 0xda, 0xce, 0xc0, 0xa2,
+ 0x00, 0xa3, 0xc1, 0xcf, 0xdb, 0xe3, 0xe7, 0xe9,
+ 0xeb, 0xe9, 0xe7, 0xe3, 0xdb, 0xcf, 0xc1, 0xa3,
+ 0x00, 0xa2, 0xc0, 0xce, 0xda, 0xe2, 0xe6, 0xe8,
+ 0xe8, 0xe8, 0xe6, 0xe2, 0xda, 0xce, 0xbe, 0xa0,
+ 0x00, 0xa1, 0xbf, 0xcf, 0xdb, 0xe3, 0xe7, 0xe9,
+ 0xe9, 0xe9, 0xe7, 0xe3, 0xd9, 0xcd, 0xbf, 0xa1,
+ 0x00, 0xa0, 0xbe, 0xcc, 0xd8, 0xe2, 0xe6, 0xe8,
+ 0xe8, 0xe8, 0xe4, 0xe2, 0xd8, 0xcc, 0xbc, 0x9e,
+ 0x00, 0x9f, 0xbd, 0xcd, 0xd9, 0xe3, 0xe5, 0xe7,
+ 0xe9, 0xe7, 0xe5, 0xe1, 0xd9, 0xcd, 0xbd, 0x9f,
+ 0x00, 0x9e, 0xbc, 0xcc, 0xd8, 0xe0, 0xe4, 0xe6,
+ 0xe6, 0xe6, 0xe4, 0xe0, 0xd6, 0xcc, 0xbc, 0x9e,
+ 0x00, 0x9f, 0xbd, 0xcd, 0xd7, 0xe1, 0xe5, 0xe7,
+ 0xe7, 0xe7, 0xe5, 0xe1, 0xd7, 0xcb, 0xbb, 0x9d,
+ 0x00, 0x9c, 0xba, 0xca, 0xd6, 0xde, 0xe4, 0xe6,
+ 0xe6, 0xe6, 0xe4, 0xde, 0xd6, 0xca, 0xba, 0x9c,
+ 0x00, 0x9d, 0xbb, 0xcb, 0xd5, 0xdf, 0xe3, 0xe5,
+ 0xe7, 0xe5, 0xe3, 0xdf, 0xd5, 0xcb, 0xbb, 0x9d,
+ 0x00, 0x9a, 0xb8, 0xca, 0xd4, 0xde, 0xe2, 0xe4,
+ 0xe4, 0xe4, 0xe2, 0xdc, 0xd4, 0xca, 0xb8, 0x9a,
+ 0x00, 0x9b, 0xb9, 0xc9, 0xd5, 0xdd, 0xe3, 0xe5,
+ 0xe5, 0xe5, 0xe3, 0xdd, 0xd5, 0xc9, 0xb9, 0x9b,
+ 0x00, 0x9a, 0xb8, 0xc8, 0xd2, 0xdc, 0xe2, 0xe4,
+ 0xe4, 0xe4, 0xe2, 0xdc, 0xd2, 0xc8, 0xb6, 0x98,
+ 0x00, 0x99, 0xb7, 0xc9, 0xd3, 0xdb, 0xe1, 0xe3,
+ 0xe5, 0xe3, 0xe1, 0xdb, 0xd3, 0xc9, 0xb7, 0x99,
+ 0x00, 0x98, 0xb6, 0xc8, 0xd2, 0xda, 0xe0, 0xe2,
+ 0xe2, 0xe2, 0xe0, 0xda, 0xd2, 0xc6, 0xb6, 0x98,
+ 0x00, 0x99, 0xb7, 0xc7, 0xd1, 0xd9, 0xdf, 0xe3,
+ 0xe3, 0xe3, 0xdf, 0xd9, 0xd1, 0xc7, 0xb5, 0x97,
+ 0x00, 0x96, 0xb4, 0xc6, 0xd0, 0xd8, 0xde, 0xe2,
+ 0xe2, 0xe2, 0xde, 0xd8, 0xd0, 0xc6, 0xb4, 0x96,
+ 0x00, 0x97, 0xb5, 0xc7, 0xd1, 0xd9, 0xdf, 0xe1,
+ 0xe3, 0xe1, 0xdd, 0xd7, 0xcf, 0xc7, 0xb3, 0x95,
+ 0x00, 0x94, 0xb2, 0xc4, 0xce, 0xd6, 0xdc, 0xe0,
+ 0xe0, 0xe0, 0xdc, 0xd6, 0xce, 0xc4, 0xb2, 0x94,
+ 0x00, 0x95, 0xb3, 0xc5, 0xcf, 0xd7, 0xdd, 0xdf,
+ 0xe1, 0xdf, 0xdd, 0xd7, 0xcf, 0xc5, 0xb3, 0x95,
+ 0x00, 0x94, 0xb2, 0xc4, 0xce, 0xd4, 0xda, 0xde,
+ 0xde, 0xde, 0xda, 0xd4, 0xcc, 0xc4, 0xb0, 0x92,
+ 0x00, 0x93, 0xb1, 0xc5, 0xcd, 0xd5, 0xdb, 0xdd,
+ 0xdf, 0xdd, 0xdb, 0xd5, 0xcd, 0xc3, 0xb1, 0x93,
+ 0x00, 0x92, 0xb0, 0xc2, 0xcc, 0xd4, 0xd8, 0xdc,
+ 0xdc, 0xdc, 0xd8, 0xd2, 0xcc, 0xc2, 0xb0, 0x90,
+ 0x00, 0x91, 0xaf, 0xc3, 0xcb, 0xd3, 0xd9, 0xdb,
+ 0xdd, 0xdb, 0xd9, 0xd3, 0xcb, 0xc3, 0xaf, 0x91,
+ 0x00, 0x90, 0xae, 0xc2, 0xca, 0xd2, 0xd6, 0xda,
+ 0xda, 0xda, 0xd6, 0xd2, 0xca, 0xc2, 0xae, 0x90,
+ 0x00, 0x91, 0xaf, 0xc3, 0xcb, 0xd1, 0xd7, 0xd9,
+ 0xdb, 0xd9, 0xd7, 0xd1, 0xcb, 0xc1, 0xad, 0x8f,
+ 0x00, 0x8e, 0xac, 0xc0, 0xc8, 0xd0, 0xd4, 0xd8,
+ 0xd8, 0xd8, 0xd4, 0xd0, 0xc8, 0xc0, 0xac, 0x8e,
+ 0x00, 0x8f, 0xad, 0xbf, 0xc9, 0xcf, 0xd5, 0xd7,
+ 0xd9, 0xd7, 0xd5, 0xcf, 0xc9, 0xbf, 0xad, 0x8f,
+ 0x00, 0x8c, 0xac, 0xbe, 0xc8, 0xce, 0xd2, 0xd6,
+ 0xd6, 0xd6, 0xd2, 0xce, 0xc8, 0xbe, 0xaa, 0x8c,
+ 0x00, 0x8d, 0xab, 0xbd, 0xc7, 0xcf, 0xd3, 0xd5,
+ 0xd7, 0xd5, 0xd3, 0xcd, 0xc7, 0xbd, 0xab, 0x8d,
+ 0x00, 0x8c, 0xaa, 0xbc, 0xc6, 0xcc, 0xd2, 0xd4,
+ 0xd4, 0xd4, 0xd0, 0xcc, 0xc6, 0xba, 0xaa, 0x8a,
+ 0x00, 0x8b, 0xa9, 0xbb, 0xc7, 0xcd, 0xd1, 0xd5,
+ 0xd5, 0xd3, 0xd1, 0xcd, 0xc5, 0xbb, 0xa9, 0x8b,
+ 0x00, 0x8a, 0xa8, 0xba, 0xc4, 0xca, 0xd0, 0xd2,
+ 0xd2, 0xd2, 0xd0, 0xca, 0xc4, 0xb8, 0xa8, 0x8a,
+ 0x00, 0x8b, 0xa9, 0xb9, 0xc5, 0xcb, 0xcf, 0xd3,
+ 0xd3, 0xd1, 0xcf, 0xcb, 0xc5, 0xb9, 0xa7, 0x89,
+ 0x00, 0x88, 0xa6, 0xb8, 0xc4, 0xca, 0xce, 0xd0,
+ 0xd0, 0xd0, 0xce, 0xc8, 0xc2, 0xb6, 0xa6, 0x88,
+ 0x00, 0x89, 0xa7, 0xb7, 0xc3, 0xc9, 0xcd, 0xd1,
+ 0xd1, 0xcf, 0xcd, 0xc9, 0xc3, 0xb7, 0xa7, 0x87,
+ 0x00, 0x86, 0xa6, 0xb4, 0xc2, 0xc8, 0xcc, 0xce,
+ 0xce, 0xce, 0xcc, 0xc8, 0xc2, 0xb4, 0xa4, 0x86,
+ 0x00, 0x87, 0xa5, 0xb5, 0xc3, 0xc7, 0xcb, 0xcf,
+ 0xcf, 0xcf, 0xcb, 0xc7, 0xc1, 0xb5, 0xa5, 0x87,
+ 0x00, 0x86, 0xa4, 0xb2, 0xc0, 0xc6, 0xca, 0xcc,
+ 0xcc, 0xcc, 0xca, 0xc6, 0xc0, 0xb2, 0xa2, 0x84,
+ 0x00, 0x85, 0xa3, 0xb3, 0xbf, 0xc5, 0xc9, 0xcd,
+ 0xcd, 0xcd, 0xc9, 0xc5, 0xbf, 0xb1, 0xa3, 0x85,
+ 0x00, 0x84, 0xa2, 0xb0, 0xbc, 0xc4, 0xc8, 0xca,
+ 0xca, 0xca, 0xc8, 0xc4, 0xbc, 0xb0, 0xa2, 0x82,
+ 0x00, 0x83, 0xa3, 0xb1, 0xbd, 0xc5, 0xc7, 0xcb,
+ 0xcb, 0xcb, 0xc7, 0xc3, 0xbb, 0xaf, 0xa1, 0x83,
+ 0x00, 0x82, 0xa0, 0xae, 0xba, 0xc2, 0xc6, 0xc8,
+ 0xc8, 0xc8, 0xc6, 0xc2, 0xba, 0xae, 0x9e, 0x82,
+ 0x00, 0x83, 0x9f, 0xaf, 0xb9, 0xc3, 0xc7, 0xc9,
+ 0xc9, 0xc9, 0xc5, 0xc3, 0xb9, 0xad, 0x9f, 0x81,
+ 0x00, 0x80, 0x9c, 0xac, 0xb8, 0xc0, 0xc4, 0xc6,
+ 0xc6, 0xc6, 0xc4, 0xc0, 0xb6, 0xac, 0x9c, 0x7e,
+ 0x00, 0x7f, 0x9d, 0xab, 0xb7, 0xbf, 0xc5, 0xc7,
+ 0xc7, 0xc7, 0xc5, 0xbf, 0xb7, 0xab, 0x9b, 0x7d,
+ 0x00, 0x7c, 0x9a, 0xaa, 0xb4, 0xbe, 0xc2, 0xc4,
+ 0xc4, 0xc4, 0xc2, 0xbc, 0xb4, 0xaa, 0x98, 0x7c,
+ 0x00, 0x7d, 0x99, 0xa9, 0xb5, 0xbd, 0xc3, 0xc5,
+ 0xc5, 0xc5, 0xc3, 0xbb, 0xb3, 0xa9, 0x99, 0x7b,
+ 0x00, 0x7a, 0x96, 0xa8, 0xb2, 0xba, 0xc0, 0xc2,
+ 0xc2, 0xc2, 0xc0, 0xba, 0xb0, 0xa6, 0x96, 0x78,
+ 0x00, 0x79, 0x97, 0xa7, 0xb1, 0xb9, 0xbf, 0xc3,
+ 0xc3, 0xc3, 0xbf, 0xb9, 0xb1, 0xa7, 0x95, 0x77,
+ 0x00, 0x76, 0x94, 0xa6, 0xae, 0xb6, 0xbc, 0xc0,
+ 0xc0, 0xc0, 0xbc, 0xb6, 0xae, 0xa4, 0x92, 0x76,
+ 0x00, 0x75, 0x93, 0xa5, 0xaf, 0xb5, 0xbb, 0xbf,
+ 0xbf, 0xbf, 0xbb, 0xb5, 0xad, 0xa5, 0x91, 0x75,
+ 0x00, 0x74, 0x90, 0xa4, 0xac, 0xb4, 0xb8, 0xbc,
+ 0xbc, 0xbc, 0xb8, 0xb2, 0xac, 0xa2, 0x90, 0x72,
+ 0x00, 0x73, 0x91, 0xa3, 0xab, 0xb3, 0xb7, 0xbb,
+ 0xbb, 0xbb, 0xb7, 0xb1, 0xab, 0xa3, 0x8f, 0x71,
+ 0x00, 0x70, 0x8e, 0xa0, 0xaa, 0xb0, 0xb4, 0xb8,
+ 0xb8, 0xb8, 0xb4, 0xb0, 0xa8, 0xa0, 0x8c, 0x6e,
+ 0x00, 0x6f, 0x8d, 0x9f, 0xa9, 0xaf, 0xb5, 0xb7,
+ 0xb7, 0xb7, 0xb3, 0xaf, 0xa9, 0x9f, 0x8b, 0x6f,
+ 0x00, 0x6e, 0x8a, 0x9c, 0xa6, 0xac, 0xb2, 0xb4,
+ 0xb4, 0xb4, 0xb0, 0xac, 0xa6, 0x9a, 0x8a, 0x6c,
+ 0x00, 0x6d, 0x89, 0x9b, 0xa5, 0xab, 0xb1, 0xb3,
+ 0xb3, 0xb3, 0xaf, 0xab, 0xa5, 0x99, 0x89, 0x6b,
+ 0x00, 0x6a, 0x88, 0x98, 0xa4, 0xaa, 0xae, 0xb0,
+ 0xb0, 0xb0, 0xae, 0xa8, 0xa2, 0x96, 0x86, 0x68,
+ 0x00, 0x69, 0x87, 0x97, 0xa3, 0xa9, 0xad, 0xaf,
+ 0xaf, 0xaf, 0xad, 0xa7, 0xa3, 0x95, 0x85, 0x69,
+ 0x00, 0x66, 0x84, 0x94, 0xa0, 0xa6, 0xaa, 0xac,
+ 0xac, 0xac, 0xaa, 0xa6, 0x9e, 0x92, 0x84, 0x66,
+ 0x00, 0x67, 0x83, 0x93, 0x9f, 0xa5, 0xa9, 0xab,
+ 0xab, 0xab, 0xa9, 0xa5, 0x9d, 0x91, 0x83, 0x65,
+ 0x00, 0x64, 0x82, 0x8e, 0x9a, 0xa2, 0xa6, 0xa8,
+ 0xa8, 0xa8, 0xa6, 0xa2, 0x9a, 0x8e, 0x80, 0x62,
+ 0x00, 0x63, 0x7f, 0x8d, 0x99, 0xa1, 0xa5, 0xa7,
+ 0xa7, 0xa7, 0xa5, 0xa1, 0x97, 0x8d, 0x7d, 0x61,
+ 0x00, 0x60, 0x7c, 0x8a, 0x94, 0x9e, 0xa2, 0xa4,
+ 0xa4, 0xa4, 0xa2, 0x9c, 0x94, 0x8a, 0x7a, 0x5e,
+ 0x00, 0x5f, 0x79, 0x89, 0x93, 0x9b, 0xa1, 0xa3,
+ 0xa3, 0xa3, 0xa1, 0x9b, 0x91, 0x87, 0x77, 0x5b,
+ 0x00, 0x5a, 0x76, 0x86, 0x90, 0x96, 0x9c, 0xa0,
+ 0xa0, 0xa0, 0x9c, 0x96, 0x8e, 0x84, 0x72, 0x58,
+ 0x00, 0x59, 0x73, 0x85, 0x8d, 0x95, 0x99, 0x9d,
+ 0x9d, 0x9d, 0x99, 0x93, 0x8d, 0x83, 0x71, 0x55,
+ 0x00, 0x54, 0x70, 0x82, 0x8a, 0x90, 0x96, 0x98,
+ 0x98, 0x98, 0x94, 0x90, 0x88, 0x80, 0x6c, 0x52,
+ 0x00, 0x51, 0x6d, 0x7f, 0x87, 0x8d, 0x93, 0x95,
+ 0x95, 0x95, 0x91, 0x8d, 0x87, 0x7b, 0x6b, 0x4f,
+ 0x00, 0x4e, 0x6a, 0x7a, 0x84, 0x8a, 0x8e, 0x90,
+ 0x90, 0x90, 0x8c, 0x88, 0x82, 0x76, 0x66, 0x4a,
+ 0x00, 0x4b, 0x67, 0x75, 0x83, 0x87, 0x8b, 0x8d,
+ 0x8d, 0x8d, 0x8b, 0x87, 0x7f, 0x73, 0x65, 0x49,
+ 0x00, 0x48, 0x62, 0x70, 0x7c, 0x82, 0x86, 0x88,
+ 0x88, 0x88, 0x86, 0x82, 0x78, 0x6e, 0x60, 0x44,
+ 0x00, 0x45, 0x5f, 0x6d, 0x77, 0x7f, 0x83, 0x85,
+ 0x85, 0x85, 0x83, 0x7d, 0x75, 0x6b, 0x5b, 0x43,
+ 0x00, 0x42, 0x58, 0x68, 0x70, 0x78, 0x7c, 0x80,
+ 0x80, 0x7e, 0x7c, 0x76, 0x6e, 0x64, 0x54, 0x3c,
+ 0x00, 0x3d, 0x53, 0x63, 0x6b, 0x73, 0x77, 0x79,
+ 0x79, 0x79, 0x75, 0x6f, 0x69, 0x61, 0x4f, 0x37,
+ 0x00, 0x34, 0x4c, 0x5c, 0x66, 0x6a, 0x6e, 0x70,
+ 0x70, 0x70, 0x6c, 0x68, 0x62, 0x56, 0x48, 0x30,
+ 0x00, 0x2f, 0x47, 0x55, 0x5f, 0x65, 0x67, 0x69,
+ 0x69, 0x69, 0x65, 0x63, 0x59, 0x4f, 0x43, 0x2b,
+ 0x00, 0x28, 0x40, 0x4a, 0x52, 0x5a, 0x5e, 0x60,
+ 0x60, 0x5e, 0x5a, 0x54, 0x4c, 0x44, 0x36, 0x22,
+ 0x00, 0x23, 0x33, 0x43, 0x49, 0x4d, 0x4f, 0x51,
+ 0x51, 0x4f, 0x4d, 0x47, 0x43, 0x37, 0x2b, 0x19,
+ 0x00, 0x16, 0x26, 0x30, 0x36, 0x3c, 0x40, 0x40,
+ 0x40, 0x3c, 0x38, 0x32, 0x2c, 0x24, 0x1a, 0x0c,
+ 0x00, 0x0b, 0x15, 0x1b, 0x21, 0x23, 0x23, 0x21,
+ 0x1f, 0x19, 0x15, 0x0f, 0x09, 0x05, 0x03, 0x00,
+};
+
+/* End of waveform.h */
--- /dev/null
+/* $NetBSD: wd.c,v 1.6 1996/03/28 21:52:52 mark Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
+ *
+ * DMA and multi-sector PIO handling are derived from code contributed by
+ * Onno van der Linden.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/buf.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+#include <sys/syslog.h>
+
+#include <vm/vm.h>
+
+#include <machine/cpu.h>
+
+#include <arm32/mainbus/wdreg.h>
+#include <arm32/mainbus/mainbus.h>
+#include <machine/irqhandler.h>
+#include <machine/io.h>
+#include <machine/katelib.h>
+
+extern int wdresethack;
+
+#define WAITTIME (4 * hz) /* time to wait for a completion */
+#define RECOVERYTIME (hz / 2) /* time to recover from an error */
+
+#define WDCDELAY 100
+#define WDCNDELAY 100000 /* delay = 100us; so 10s for a controller state change */
+#if 0
+/* If you enable this, it will report any delays more than 100us * N long. */
+#define WDCNDELAY_DEBUG 10
+#endif
+
+#define WDIORETRIES 5 /* number of retries before giving up */
+
+#define WDUNIT(dev) DISKUNIT(dev)
+#define WDPART(dev) DISKPART(dev)
+#define MAKEWDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part)
+
+#define WDLABELDEV(dev) (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART))
+
+struct wd_softc {
+ struct device sc_dev;
+ struct disk sc_dk;
+
+ /* Information about the current transfer: */
+ daddr_t sc_blkno; /* starting block number */
+ int sc_bcount; /* byte count left */
+ int sc_skip; /* bytes already transferred */
+ int sc_nblks; /* number of blocks currently transferring */
+ int sc_nbytes; /* number of bytes currently transferring */
+
+ /* Long-term state: */
+ int sc_drive; /* physical unit number */
+ int sc_state; /* control state */
+#define RECAL 0 /* recalibrate */
+#define RECAL_WAIT 1 /* done recalibrating */
+#define GEOMETRY 2 /* upload geometry */
+#define GEOMETRY_WAIT 3 /* done uploading geometry */
+#define MULTIMODE 4 /* set multiple mode */
+#define MULTIMODE_WAIT 5 /* done setting multiple mode */
+#define OPEN 6 /* done with open */
+ int sc_mode; /* transfer mode */
+#define WDM_PIOSINGLE 0 /* single-sector PIO */
+#define WDM_PIOMULTI 1 /* multi-sector PIO */
+#define WDM_DMA 2 /* DMA */
+ int sc_multiple; /* multiple for WDM_PIOMULTI */
+ int sc_flags; /* drive characteistics found */
+#define WDF_LOCKED 0x01
+#define WDF_WANTED 0x02
+#define WDF_WLABEL 0x04 /* label is writable */
+#define WDF_LABELLING 0x08 /* writing label */
+/* XXX Nothing resets this yet, but disk change sensing will when ATAPI is
+ implemented. */
+#define WDF_LOADED 0x10 /* parameters loaded */
+#define WDF_32BIT 0x20 /* can do 32-bit transfer */
+
+ struct wdparams sc_params; /* ESDI/ATA drive parameters */
+ daddr_t sc_badsect[127]; /* 126 plus trailing -1 marker */
+
+ TAILQ_ENTRY(wd_softc) sc_drivechain;
+ struct buf sc_q;
+};
+
+struct wdc_softc {
+ struct device sc_dev;
+ irqhandler_t sc_ih;
+
+ int sc_iobase; /* I/O port base */
+ int sc_drq; /* DMA channel */
+
+ TAILQ_HEAD(drivehead, wd_softc) sc_drives;
+ int sc_flags;
+#define WDCF_ACTIVE 0x01 /* controller is active */
+#define WDCF_SINGLE 0x02 /* sector at a time mode */
+#define WDCF_ERROR 0x04 /* processing a disk error */
+#define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */
+ int sc_errors; /* errors during current transfer */
+ u_char sc_status; /* copy of status register */
+ u_char sc_error; /* copy of error register */
+};
+
+int wdcprobe __P((struct device *, void *, void *));
+void wdcattach __P((struct device *, struct device *, void *));
+
+struct cfattach wdc_ca = {
+ sizeof(struct wdc_softc), wdcprobe, wdcattach
+};
+
+struct cfdriver wdc_cd = {
+ NULL, "wdc", DV_DULL
+};
+
+int wdprobe __P((struct device *, void *, void *));
+void wdattach __P((struct device *, struct device *, void *));
+
+struct cfattach wd_ca = {
+ sizeof(struct wd_softc), wdprobe, wdattach
+};
+
+struct cfdriver wd_cd = {
+ NULL, "wd", DV_DISK
+};
+
+void wdgetdisklabel __P((struct wd_softc *));
+int wd_get_parms __P((struct wd_softc *));
+void wdstrategy __P((struct buf *));
+void wdstart __P((struct wd_softc *));
+
+struct dkdriver wddkdriver = { wdstrategy };
+
+void wdfinish __P((struct wd_softc *, struct buf *));
+int wdcintr __P((void *));
+void wdcstart __P((struct wdc_softc *));
+int wdcommand __P((struct wd_softc *, int, int, int, int, int));
+int wdcommandshort __P((struct wdc_softc *, int, int));
+int wdcontrol __P((struct wd_softc *));
+int wdsetctlr __P((struct wd_softc *));
+static void bad144intern __P((struct wd_softc *));
+int wdcreset __P((struct wdc_softc *));
+void wdcrestart __P((void *arg));
+void wdcunwedge __P((struct wdc_softc *));
+void wdctimeout __P((void *arg));
+void wderror __P((void *, struct buf *, char *));
+int wdcwait __P((struct wdc_softc *, int));
+/* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
+ command is aborted. */
+#define wait_for_drq(d) wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
+#define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC)
+#define wait_for_unbusy(d) wdcwait(d, 0)
+
+int
+wdcprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct wdc_softc *wdc = match;
+ struct mainbus_attach_args *mb = aux;
+ int iobase;
+
+ wdc->sc_iobase = iobase = mb->mb_iobase;
+
+ /* Check if we have registers that work. */
+ outb(iobase+wd_error, 0x5a); /* Error register not writable, */
+ outb(iobase+wd_cyl_lo, 0xa5); /* but all of cyllo are. */
+ if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5)
+ return 0;
+
+ if (wdcreset(wdc) != 0) {
+ delay(500000);
+ if (wdcreset(wdc) != 0)
+ return 0;
+ }
+
+ /* Select drive 0. */
+ outb(iobase+wd_sdh, WDSD_IBM | 0);
+
+ /* Wait for controller to become ready. */
+ if (wait_for_unbusy(wdc) < 0)
+ return 0;
+
+ /* Start drive diagnostics. */
+ outb(iobase+wd_command, WDCC_DIAGNOSE);
+
+ /* Wait for command to complete. */
+ if (wait_for_unbusy(wdc) < 0)
+ return 0;
+
+ mb->mb_iosize = 32;
+ return 1;
+}
+
+struct wdc_attach_args {
+ int wa_drive;
+};
+
+int
+wdprint(aux, wdc)
+ void *aux;
+ char *wdc;
+{
+ struct wdc_attach_args *wa = aux;
+
+ if (!wdc)
+ printf(" drive %d", wa->wa_drive);
+ return QUIET;
+}
+
+void
+wdcattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct wdc_softc *wdc = (void *)self;
+ struct mainbus_attach_args *mb = aux;
+ struct wdc_attach_args wa;
+
+ TAILQ_INIT(&wdc->sc_drives);
+ wdc->sc_drq = mb->mb_drq;
+
+ printf("\n");
+
+ wdc->sc_ih.ih_func = wdcintr;
+ wdc->sc_ih.ih_arg = wdc;
+ wdc->sc_ih.ih_level = IPL_BIO;
+ wdc->sc_ih.ih_name = "wdc";
+ if (irq_claim(mb->mb_irq, &wdc->sc_ih))
+ panic("Cannot claim IRQ %d for wdc%d\n", mb->mb_irq, parent->dv_unit);
+
+ for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
+ (void)config_found(self, (void *)&wa, wdprint);
+}
+
+int
+wdprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct wdc_softc *wdc = (void *)parent;
+ struct cfdata *cf = match;
+ struct wdc_attach_args *wa = aux;
+ int drive = wa->wa_drive;
+
+ if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
+ return 0;
+
+ if (wdcommandshort(wdc, drive, WDCC_RECAL) != 0 ||
+ wait_for_ready(wdc) != 0)
+ return 0;
+
+ return 1;
+}
+
+void
+wdattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct wd_softc *wd = (void *)self;
+ struct wdc_softc *wdc = (void *)parent;
+ struct wdc_attach_args *wa = aux;
+ int i, blank;
+ char buf[41], c, *p, *q;
+
+ wd->sc_drive = wa->wa_drive;
+
+ /*
+ * Initialize and attach the disk structure.
+ */
+ wd->sc_dk.dk_driver = &wddkdriver;
+ wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
+ disk_attach(&wd->sc_dk);
+
+ wd_get_parms(wd);
+ for (blank = 0, p = wd->sc_params.wdp_model, q = buf, i = 0;
+ i < sizeof(wd->sc_params.wdp_model); i++) {
+ c = *p++;
+ if (c == '\0')
+ break;
+ if (c != ' ') {
+ if (blank) {
+ *q++ = ' ';
+ blank = 0;
+ }
+ *q++ = c;
+ } else
+ blank = 1;
+ }
+ *q++ = '\0';
+
+ printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec <%s>\n",
+ wd->sc_params.wdp_cylinders *
+ (wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) /
+ (1048576 / DEV_BSIZE),
+ wd->sc_params.wdp_cylinders,
+ wd->sc_params.wdp_heads,
+ wd->sc_params.wdp_sectors,
+ DEV_BSIZE,
+ buf);
+
+ if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
+ wdc->sc_drq != DRQUNK) {
+ wd->sc_mode = WDM_DMA;
+ } else if (wd->sc_params.wdp_maxmulti > 1) {
+ wd->sc_mode = WDM_PIOMULTI;
+ wd->sc_multiple = min(wd->sc_params.wdp_maxmulti, 16);
+ } else {
+ wd->sc_mode = WDM_PIOSINGLE;
+ wd->sc_multiple = 1;
+ }
+
+ printf("%s: using", wd->sc_dev.dv_xname);
+ if (wd->sc_mode == WDM_DMA)
+ printf(" dma transfers,");
+ else
+ printf(" %d-sector %d-bit pio transfers,",
+ wd->sc_multiple, (wd->sc_flags & WDF_32BIT) == 0 ? 16 : 32);
+ if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
+ printf(" lba addressing\n");
+ else
+ printf(" chs addressing\n");
+}
+
+/*
+ * Read/write routine for a buffer. Validates the arguments and schedules the
+ * transfer. Does not wait for the transfer to complete.
+ */
+void
+wdstrategy(bp)
+ struct buf *bp;
+{
+ struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)];
+ int s;
+
+ /* Valid request? */
+ if (bp->b_blkno < 0 ||
+ (bp->b_bcount % wd->sc_dk.dk_label->d_secsize) != 0 ||
+ (bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+
+ /* If device invalidated (e.g. media change, door open), error. */
+ if ((wd->sc_flags & WDF_LOADED) == 0) {
+ bp->b_error = EIO;
+ goto bad;
+ }
+
+ /* If it's a null transfer, return immediately. */
+ if (bp->b_bcount == 0)
+ goto done;
+
+ /*
+ * Do bounds checking, adjust transfer. if error, process.
+ * If end of partition, just return.
+ */
+ if (WDPART(bp->b_dev) != RAW_PART &&
+ bounds_check_with_label(bp, wd->sc_dk.dk_label,
+ (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
+ goto done;
+
+ /* Queue transfer on drive, activate drive and controller if idle. */
+ s = splbio();
+ disksort(&wd->sc_q, bp);
+ if (!wd->sc_q.b_active)
+ wdstart(wd);
+#if 0
+ else {
+ struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+ if ((wdc->sc_flags & (WDCF_ACTIVE|WDCF_ERROR)) == 0) {
+ printf("wdstrategy: controller inactive\n");
+ wdcstart(wdc);
+ }
+ }
+#endif
+ splx(s);
+ return;
+
+bad:
+ bp->b_flags |= B_ERROR;
+done:
+ /* Toss transfer; we're done early. */
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+}
+
+/*
+ * Queue a drive for I/O.
+ */
+void
+wdstart(wd)
+ struct wd_softc *wd;
+{
+ struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+ int active = wdc->sc_drives.tqh_first != 0;
+
+ /* Link onto controller queue. */
+ wd->sc_q.b_active = 1;
+ TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
+
+ disk_busy(&wd->sc_dk);
+
+ /* If controller not already active, start it. */
+ if (!active)
+ wdcstart(wdc);
+}
+
+/*
+ * Finish an I/O operation. Clean up the drive and controller state, set the
+ * residual count, and inform the upper layers that the operation is complete.
+ */
+void
+wdfinish(wd, bp)
+ struct wd_softc *wd;
+ struct buf *bp;
+{
+ struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+
+ wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR);
+ wdc->sc_errors = 0;
+ /*
+ * Move this drive to the end of the queue to give others a `fair'
+ * chance.
+ */
+ if (wd->sc_drivechain.tqe_next) {
+ TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
+ if (bp->b_actf) {
+ TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
+ } else
+ wd->sc_q.b_active = 0;
+ }
+ bp->b_resid = wd->sc_bcount;
+ wd->sc_skip = 0;
+ wd->sc_q.b_actf = bp->b_actf;
+
+ disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
+
+ if (!wd->sc_q.b_actf) {
+ TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
+ wd->sc_q.b_active = 0;
+ } else
+ disk_busy(&wd->sc_dk);
+
+ biodone(bp);
+}
+
+int
+wdread(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+
+ return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+wdwrite(dev, uio)
+ dev_t dev;
+ struct uio *uio;
+{
+
+ return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+/*
+ * Start I/O on a controller. This does the calculation, and starts a read or
+ * write operation. Called to from wdstart() to start a transfer, from
+ * wdcintr() to continue a multi-sector transfer or start the next transfer, or
+ * wdcrestart() after recovering from an error.
+ */
+void
+wdcstart(wdc)
+ struct wdc_softc *wdc;
+{
+ struct wd_softc *wd;
+ struct buf *bp;
+ struct disklabel *lp;
+ int nblks;
+
+#ifdef DIAGNOSTIC
+ if ((wdc->sc_flags & WDCF_ACTIVE) != 0)
+ panic("wdcstart: controller still active");
+#endif
+
+ /*
+ * XXX
+ * This is a kluge. See comments in wd_get_parms().
+ */
+ if ((wdc->sc_flags & WDCF_WANTED) != 0) {
+ wdc->sc_flags &= ~WDCF_WANTED;
+ wakeup(wdc);
+ return;
+ }
+
+loop:
+ /* Is there a drive for the controller to do a transfer with? */
+ wd = wdc->sc_drives.tqh_first;
+ if (wd == NULL)
+ return;
+
+ /* Is there a transfer to this drive? If not, deactivate drive. */
+ bp = wd->sc_q.b_actf;
+
+ if (wdc->sc_errors >= WDIORETRIES) {
+ wderror(wd, bp, "hard error");
+ bp->b_error = EIO;
+ bp->b_flags |= B_ERROR;
+ wdfinish(wd, bp);
+ goto loop;
+ }
+
+ /* Do control operations specially. */
+ if (wd->sc_state < OPEN) {
+ /*
+ * Actually, we want to be careful not to mess with the control
+ * state if the device is currently busy, but we can assume
+ * that we never get to this point if that's the case.
+ */
+ if (wdcontrol(wd) == 0) {
+ /* The drive is busy. Wait. */
+ return;
+ }
+ }
+
+ /*
+ * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
+ * encountered. If we are in multi-sector mode, then we switch to
+ * single-sector mode and retry the operation from the start.
+ */
+ if (wdc->sc_flags & WDCF_ERROR) {
+ wdc->sc_flags &= ~WDCF_ERROR;
+ if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
+ wdc->sc_flags |= WDCF_SINGLE;
+ wd->sc_skip = 0;
+ }
+ }
+
+ lp = wd->sc_dk.dk_label;
+
+ /* When starting a transfer... */
+ if (wd->sc_skip == 0) {
+ int part = WDPART(bp->b_dev);
+ daddr_t blkno;
+
+#ifdef WDDEBUG
+ printf("\n%s: wdcstart %s %d@%d; map ", wd->sc_dev.dv_xname,
+ (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
+ bp->b_blkno);
+#endif
+ wd->sc_bcount = bp->b_bcount;
+ blkno = bp->b_blkno;
+ if (part != RAW_PART)
+ blkno += lp->d_partitions[part].p_offset;
+ wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
+ } else {
+#ifdef WDDEBUG
+ printf(" %d)%x", wd->sc_skip, inb(wd->sc_iobase+wd_altsts));
+#endif
+ }
+
+ /* When starting a multi-sector transfer, or doing single-sector
+ transfers... */
+ if (wd->sc_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
+ wd->sc_mode == WDM_DMA) {
+ daddr_t blkno = wd->sc_blkno;
+ long cylin, head, sector;
+ int command;
+
+ if ((wdc->sc_flags & WDCF_SINGLE) != 0)
+ nblks = 1;
+ else if (wd->sc_mode != WDM_DMA)
+ nblks = wd->sc_bcount / lp->d_secsize;
+ else
+ nblks = min(wd->sc_bcount / lp->d_secsize, 8);
+
+ /* Check for bad sectors and adjust transfer, if necessary. */
+ if ((lp->d_flags & D_BADSECT) != 0
+#ifdef B_FORMAT
+ && (bp->b_flags & B_FORMAT) == 0
+#endif
+ ) {
+ long blkdiff;
+ int i;
+
+ for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
+ blkdiff -= blkno;
+ if (blkdiff < 0)
+ continue;
+ if (blkdiff == 0) {
+ /* Replace current block of transfer. */
+ blkno =
+ lp->d_secperunit - lp->d_nsectors - i - 1;
+ }
+ if (blkdiff < nblks) {
+ /* Bad block inside transfer. */
+ wdc->sc_flags |= WDCF_SINGLE;
+ nblks = 1;
+ }
+ break;
+ }
+ /* Tranfer is okay now. */
+ }
+
+ if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
+ sector = (blkno >> 0) & 0xff;
+ cylin = (blkno >> 8) & 0xffff;
+ head = (blkno >> 24) & 0xf;
+ head |= WDSD_LBA;
+ } else {
+ sector = blkno % lp->d_nsectors;
+ sector++; /* Sectors begin with 1, not 0. */
+ blkno /= lp->d_nsectors;
+ head = blkno % lp->d_ntracks;
+ blkno /= lp->d_ntracks;
+ cylin = blkno;
+ head |= WDSD_CHS;
+ }
+
+ if (wd->sc_mode == WDM_PIOSINGLE ||
+ (wdc->sc_flags & WDCF_SINGLE) != 0)
+ wd->sc_nblks = 1;
+ else if (wd->sc_mode == WDM_PIOMULTI)
+ wd->sc_nblks = min(nblks, wd->sc_multiple);
+ else
+ wd->sc_nblks = nblks;
+ wd->sc_nbytes = wd->sc_nblks * lp->d_secsize;
+
+#ifdef B_FORMAT
+ if (bp->b_flags & B_FORMAT) {
+ sector = lp->d_gap3;
+ nblks = lp->d_nsectors;
+ command = WDCC_FORMAT;
+ } else
+#endif
+ switch (wd->sc_mode) {
+ case WDM_DMA:
+ command = (bp->b_flags & B_READ) ?
+ WDCC_READDMA : WDCC_WRITEDMA;
+ /* Start the DMA channel and bounce the buffer if
+ necessary. */
+/* isa_dmastart(bp->b_flags & B_READ,
+ bp->b_data + wd->sc_skip,
+ wd->sc_nbytes, wdc->sc_drq);*/
+ panic("wd cannot do DMA yet\n");
+ break;
+ case WDM_PIOMULTI:
+ command = (bp->b_flags & B_READ) ?
+ WDCC_READMULTI : WDCC_WRITEMULTI;
+ break;
+ case WDM_PIOSINGLE:
+ command = (bp->b_flags & B_READ) ?
+ WDCC_READ : WDCC_WRITE;
+ break;
+ }
+
+ /* Initiate command! */
+ if (wdcommand(wd, command, cylin, head, sector, nblks) != 0) {
+ wderror(wd, NULL,
+ "wdcstart: timeout waiting for unbusy");
+ wdcunwedge(wdc);
+ return;
+ }
+
+#ifdef WDDEBUG
+ printf("sector %d cylin %d head %d addr %x sts %x\n", sector,
+ cylin, head, bp->b_data, 0/*inb(wd->sc_iobase+wd_altsts)*/);
+#endif
+ } else if (wd->sc_nblks > 1) {
+ /* The number of blocks in the last stretch may be smaller. */
+ nblks = wd->sc_bcount / lp->d_secsize;
+ if (wd->sc_nblks > nblks) {
+ wd->sc_nblks = nblks;
+ wd->sc_nbytes = wd->sc_bcount;
+ }
+ }
+
+ /* If this was a write and not using DMA, push the data. */
+ if (wd->sc_mode != WDM_DMA &&
+ (bp->b_flags & (B_READ|B_WRITE)) == B_WRITE) {
+ if (wait_for_drq(wdc) < 0) {
+ wderror(wd, NULL, "wdcstart: timeout waiting for drq");
+ wdcunwedge(wdc);
+ return;
+ }
+
+ /* Push out data. */
+ if ((wd->sc_flags & WDF_32BIT) == 0)
+ outsw(wdc->sc_iobase+wd_data, (u_int) bp->b_data + wd->sc_skip,
+ wd->sc_nbytes >> 1);
+ else
+ panic("wd cannot do 32 bit transfers\n");
+/* outsl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
+ wd->sc_nbytes >> 2);*/
+ }
+
+ wdc->sc_flags |= WDCF_ACTIVE;
+ timeout(wdctimeout, wdc, WAITTIME);
+}
+
+/*
+ * Interrupt routine for the controller. Acknowledge the interrupt, check for
+ * errors on the current operation, mark it done if necessary, and start the
+ * next request. Also check for a partially done transfer, and continue with
+ * the next chunk if so.
+ */
+int
+wdcintr(arg)
+ void *arg;
+{
+ struct wdc_softc *wdc = arg;
+ struct wd_softc *wd;
+ struct buf *bp;
+
+ if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
+ /* Clear the pending interrupt and abort. */
+ (void) inb(wdc->sc_iobase+wd_status);
+ return 0;
+ }
+
+ wdc->sc_flags &= ~WDCF_ACTIVE;
+ untimeout(wdctimeout, wdc);
+
+ wd = wdc->sc_drives.tqh_first;
+ bp = wd->sc_q.b_actf;
+
+#ifdef WDDEBUG
+ printf("I%d ", ctrlr);
+#endif
+
+ if (wait_for_unbusy(wdc) < 0) {
+ wderror(wd, NULL, "wdcintr: timeout waiting for unbusy");
+ wdc->sc_status |= WDCS_ERR; /* XXX */
+ }
+
+ /* Is it not a transfer, but a control operation? */
+ if (wd->sc_state < OPEN) {
+ if (wdcontrol(wd) == 0) {
+ /* The drive is busy. Wait. */
+ return 1;
+ }
+ wdcstart(wdc);
+ return 1;
+ }
+
+ /* Turn off the DMA channel and unbounce the buffer. */
+ if (wd->sc_mode == WDM_DMA)
+ panic("wd cannot do DMA\n");
+/* isa_dmadone(bp->b_flags & B_READ, bp->b_data + wd->sc_skip,
+ wd->sc_nbytes, wdc->sc_drq);*/
+
+ /* Have we an error? */
+ if (wdc->sc_status & WDCS_ERR) {
+ lose:
+#ifdef WDDEBUG
+ wderror(wd, NULL, "wdcintr");
+#endif
+ if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
+ wdc->sc_flags |= WDCF_ERROR;
+ goto restart;
+ }
+
+#ifdef B_FORMAT
+ if (bp->b_flags & B_FORMAT)
+ goto bad;
+#endif
+
+ if (++wdc->sc_errors < WDIORETRIES)
+ goto restart;
+ wderror(wd, bp, "hard error");
+
+ bad:
+ bp->b_error = EIO;
+ bp->b_flags |= B_ERROR;
+ goto done;
+ }
+
+ /* If this was a read and not using DMA, fetch the data. */
+ if (wd->sc_mode != WDM_DMA &&
+ (bp->b_flags & (B_READ|B_WRITE)) == B_READ) {
+ if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
+ != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
+ wderror(wd, NULL, "wdcintr: read intr before drq");
+ wdcunwedge(wdc);
+ return 1;
+ }
+
+ /* Pull in data. */
+ if ((wd->sc_flags & WDF_32BIT) == 0)
+ insw(wdc->sc_iobase+wd_data, (u_int) bp->b_data + wd->sc_skip,
+ wd->sc_nbytes >> 1);
+ else
+ panic("wd cannot do 32 bit transfers\n");
+/* insl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
+ wd->sc_nbytes >> 2);*/
+ }
+
+ /* If we encountered any abnormalities, flag it as a soft error. */
+ if (wdc->sc_errors > 0 ||
+ (wdc->sc_status & WDCS_CORR) != 0) {
+ wderror(wd, bp, "soft error (corrected)");
+ wdc->sc_errors = 0;
+ }
+
+ /* Adjust pointers for the next block, if any. */
+ wd->sc_blkno += wd->sc_nblks;
+ wd->sc_skip += wd->sc_nbytes;
+ wd->sc_bcount -= wd->sc_nbytes;
+
+ /* See if this transfer is complete. */
+ if (wd->sc_bcount > 0)
+ goto restart;
+
+done:
+ /* Done with this transfer, with or without error. */
+ wdfinish(wd, bp);
+
+restart:
+ /* Start the next operation, if any. */
+ wdcstart(wdc);
+
+ return 1;
+}
+
+/*
+ * Wait interruptibly for an exclusive lock.
+ *
+ * XXX
+ * Several drivers do this; it should be abstracted and made MP-safe.
+ */
+int
+wdlock(wd)
+ struct wd_softc *wd;
+{
+ int error;
+
+ while ((wd->sc_flags & WDF_LOCKED) != 0) {
+ wd->sc_flags |= WDF_WANTED;
+ if ((error = tsleep(wd, PRIBIO | PCATCH, "wdlck", 0)) != 0)
+ return error;
+ }
+ wd->sc_flags |= WDF_LOCKED;
+ return 0;
+}
+
+/*
+ * Unlock and wake up any waiters.
+ */
+void
+wdunlock(wd)
+ struct wd_softc *wd;
+{
+
+ wd->sc_flags &= ~WDF_LOCKED;
+ if ((wd->sc_flags & WDF_WANTED) != 0) {
+ wd->sc_flags &= ~WDF_WANTED;
+ wakeup(wd);
+ }
+}
+
+int
+wdopen(dev, flag, fmt)
+ dev_t dev;
+ int flag, fmt;
+{
+ struct wd_softc *wd;
+ int unit, part;
+ int error;
+
+ unit = WDUNIT(dev);
+ if (unit >= wd_cd.cd_ndevs)
+ return ENXIO;
+ wd = wd_cd.cd_devs[unit];
+ if (wd == 0)
+ return ENXIO;
+
+ if (error = wdlock(wd))
+ return error;
+
+ if (wd->sc_dk.dk_openmask != 0) {
+ /*
+ * If any partition is open, but the disk has been invalidated,
+ * disallow further opens.
+ */
+ if ((wd->sc_flags & WDF_LOADED) == 0) {
+ error = EIO;
+ goto bad3;
+ }
+ } else {
+ if ((wd->sc_flags & WDF_LOADED) == 0) {
+ wd->sc_flags |= WDF_LOADED;
+
+ /* Load the physical device parameters. */
+ if (wd_get_parms(wd) != 0) {
+ error = ENXIO;
+ goto bad2;
+ }
+
+ /* Load the partition info if not already loaded. */
+ wdgetdisklabel(wd);
+ }
+ }
+
+ part = WDPART(dev);
+
+ /* Check that the partition exists. */
+ if (part != RAW_PART &&
+ (part >= wd->sc_dk.dk_label->d_npartitions ||
+ wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
+ error = ENXIO;
+ goto bad;
+ }
+
+ /* Insure only one open at a time. */
+ switch (fmt) {
+ case S_IFCHR:
+ wd->sc_dk.dk_copenmask |= (1 << part);
+ break;
+ case S_IFBLK:
+ wd->sc_dk.dk_bopenmask |= (1 << part);
+ break;
+ }
+ wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
+
+ wdunlock(wd);
+ return 0;
+
+bad2:
+ wd->sc_flags &= ~WDF_LOADED;
+
+bad:
+ if (wd->sc_dk.dk_openmask == 0) {
+ }
+
+bad3:
+ wdunlock(wd);
+ return error;
+}
+
+int
+wdclose(dev, flag, fmt)
+ dev_t dev;
+ int flag, fmt;
+{
+ struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
+ int part = WDPART(dev);
+ int error;
+
+ if (error = wdlock(wd))
+ return error;
+
+ switch (fmt) {
+ case S_IFCHR:
+ wd->sc_dk.dk_copenmask &= ~(1 << part);
+ break;
+ case S_IFBLK:
+ wd->sc_dk.dk_bopenmask &= ~(1 << part);
+ break;
+ }
+ wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
+
+ if (wd->sc_dk.dk_openmask == 0) {
+ /* XXXX Must wait for I/O to complete! */
+ }
+
+ wdunlock(wd);
+ return 0;
+}
+
+/*
+ * Fabricate a default disk label, and try to read the correct one.
+ */
+void
+wdgetdisklabel(wd)
+ struct wd_softc *wd;
+{
+ struct disklabel *lp = wd->sc_dk.dk_label;
+ char *errstring;
+
+ bzero(lp, sizeof(struct disklabel));
+ bzero(wd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
+
+ lp->d_secsize = DEV_BSIZE;
+ lp->d_ntracks = wd->sc_params.wdp_heads;
+ lp->d_nsectors = wd->sc_params.wdp_sectors;
+ lp->d_ncylinders = wd->sc_params.wdp_cylinders;
+ lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+
+#if 0
+ strncpy(lp->d_typename, "ST506 disk", 16);
+ lp->d_type = DTYPE_ST506;
+#endif
+ strncpy(lp->d_packname, wd->sc_params.wdp_model, 16);
+ lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
+ lp->d_rpm = 3600;
+ lp->d_interleave = 1;
+ lp->d_flags = 0;
+
+ lp->d_partitions[RAW_PART].p_offset = 0;
+ lp->d_partitions[RAW_PART].p_size =
+ lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
+ lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
+ lp->d_npartitions = RAW_PART + 1;
+
+ lp->d_magic = DISKMAGIC;
+ lp->d_magic2 = DISKMAGIC;
+ lp->d_checksum = dkcksum(lp);
+
+ wd->sc_badsect[0] = -1;
+
+ if (wd->sc_state > RECAL)
+ wd->sc_state = RECAL;
+ errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
+ wdstrategy, lp, wd->sc_dk.dk_cpulabel);
+ if (errstring) {
+ /*
+ * This probably happened because the drive's default
+ * geometry doesn't match the DOS geometry. We
+ * assume the DOS geometry is now in the label and try
+ * again. XXX This is a kluge.
+ */
+ if (wd->sc_state > GEOMETRY)
+ wd->sc_state = GEOMETRY;
+ errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
+ wdstrategy, lp, wd->sc_dk.dk_cpulabel);
+ }
+ if (errstring) {
+ printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);
+ return;
+ }
+
+ if (wd->sc_state > GEOMETRY)
+ wd->sc_state = GEOMETRY;
+ if ((lp->d_flags & D_BADSECT) != 0)
+ bad144intern(wd);
+}
+
+/*
+ * Implement operations needed before read/write.
+ * Returns 0 if operation still in progress, 1 if completed.
+ */
+int
+wdcontrol(wd)
+ struct wd_softc *wd;
+{
+ struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+
+ switch (wd->sc_state) {
+ case RECAL: /* Set SDH, step rate, do recal. */
+ if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0) {
+ wderror(wd, NULL, "wdcontrol: recal failed (1)");
+ goto bad;
+ }
+ wd->sc_state = RECAL_WAIT;
+ break;
+
+ case RECAL_WAIT:
+ if (wdc->sc_status & WDCS_ERR) {
+ wderror(wd, NULL, "wdcontrol: recal failed (2)");
+ goto bad;
+ }
+ /* fall through */
+ case GEOMETRY:
+ if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
+ goto multimode;
+ if (wdsetctlr(wd) != 0) {
+ /* Already printed a message. */
+ goto bad;
+ }
+ wd->sc_state = GEOMETRY_WAIT;
+ break;
+
+ case GEOMETRY_WAIT:
+ if (wdc->sc_status & WDCS_ERR) {
+ wderror(wd, NULL, "wdcontrol: geometry failed");
+ goto bad;
+ }
+ /* fall through */
+ case MULTIMODE:
+ multimode:
+ if (wd->sc_mode != WDM_PIOMULTI)
+ goto open;
+ outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple);
+ if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
+ wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
+ goto bad;
+ }
+ wd->sc_state = MULTIMODE_WAIT;
+ break;
+
+ case MULTIMODE_WAIT:
+ if (wdc->sc_status & WDCS_ERR) {
+ wderror(wd, NULL, "wdcontrol: setmulti failed (2)");
+ goto bad;
+ }
+ /* fall through */
+ case OPEN:
+ open:
+ wdc->sc_errors = 0;
+ wd->sc_state = OPEN;
+ /*
+ * The rest of the initialization can be done by normal means.
+ */
+ return 1;
+
+ bad:
+ wdcunwedge(wdc);
+ return 0;
+ }
+
+ wdc->sc_flags |= WDCF_ACTIVE;
+ timeout(wdctimeout, wdc, WAITTIME);
+ return 0;
+}
+
+/*
+ * Wait for the drive to become ready and send a command.
+ * Return -1 if busy for too long or 0 otherwise.
+ * Assumes interrupts are blocked.
+ */
+int
+wdcommand(wd, command, cylin, head, sector, count)
+ struct wd_softc *wd;
+ int command;
+ int cylin, head, sector, count;
+{
+ struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+ int iobase = wdc->sc_iobase;
+ int stat;
+
+ /* Select drive, head, and addressing mode. */
+ outb(iobase+wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head);
+
+ /* Wait for it to become ready to accept a command. */
+ if (command == WDCC_IDP)
+ stat = wait_for_unbusy(wdc);
+ else
+ stat = wdcwait(wdc, WDCS_DRDY);
+ if (stat < 0)
+ return -1;
+
+ /* Load parameters. */
+ if (wd->sc_dk.dk_label->d_type == DTYPE_ST506)
+ outb(iobase+wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4);
+ else
+ outb(iobase+wd_features, 0);
+ outb(iobase+wd_cyl_lo, cylin);
+ outb(iobase+wd_cyl_hi, cylin >> 8);
+ outb(iobase+wd_sector, sector);
+ outb(iobase+wd_seccnt, count);
+
+ /* Send command. */
+ outb(iobase+wd_command, command);
+
+ return 0;
+}
+
+/*
+ * Simplified version of wdcommand().
+ */
+int
+wdcommandshort(wdc, drive, command)
+ struct wdc_softc *wdc;
+ int drive;
+ int command;
+{
+ int iobase = wdc->sc_iobase;
+
+ /* Select drive. */
+ outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
+
+ if (wdcwait(wdc, WDCS_DRDY) < 0)
+ return -1;
+
+ outb(iobase+wd_command, command);
+
+ return 0;
+}
+
+/*
+ * Tell the drive what geometry to use.
+ */
+int
+wdsetctlr(wd)
+ struct wd_softc *wd;
+{
+ struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+
+#ifdef WDDEBUG
+ printf("wd(%d,%d) C%dH%dS%d\n", wd->sc_dev.dv_unit, wd->sc_drive,
+ wd->sc_dk.dk_label->d_ncylinders, wd->sc_dk.dk_label->d_ntracks,
+ wd->sc_dk.dk_label->d_nsectors);
+#endif
+
+ if (wdcommand(wd, WDCC_IDP, wd->sc_dk.dk_label->d_ncylinders,
+ wd->sc_dk.dk_label->d_ntracks - 1, 0,
+ wd->sc_dk.dk_label->d_nsectors) != 0) {
+ wderror(wd, NULL, "wdsetctlr: geometry upload failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
+ */
+int
+wd_get_parms(wd)
+ struct wd_softc *wd;
+{
+ struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
+ int i;
+ char tb[DEV_BSIZE];
+ int s, error;
+
+ /*
+ * XXX
+ * The locking done here, and the length of time this may keep the rest
+ * of the system suspended, is a kluge. This should be rewritten to
+ * set up a transfer and queue it through wdstart(), but it's called
+ * infrequently enough that this isn't a pressing matter.
+ */
+
+ s = splbio();
+
+ while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
+ wdc->sc_flags |= WDCF_WANTED;
+ if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) {
+ splx(s);
+ return error;
+ }
+ }
+
+ if (wdcommandshort(wdc, wd->sc_drive, WDCC_IDENTIFY) != 0 ||
+ wait_for_drq(wdc) != 0) {
+ /*
+ * We `know' there's a drive here; just assume it's old.
+ * This geometry is only used to read the MBR and print a
+ * (false) attach message.
+ */
+ strncpy(wd->sc_dk.dk_label->d_typename, "ST506",
+ sizeof wd->sc_dk.dk_label->d_typename);
+ wd->sc_dk.dk_label->d_type = DTYPE_ST506;
+
+ strncpy(wd->sc_params.wdp_model, "unknown",
+ sizeof wd->sc_params.wdp_model);
+ wd->sc_params.wdp_config = WD_CFG_FIXED;
+ wd->sc_params.wdp_cylinders = 1024;
+ wd->sc_params.wdp_heads = 8;
+ wd->sc_params.wdp_sectors = 17;
+ wd->sc_params.wdp_maxmulti = 0;
+ wd->sc_params.wdp_usedmovsd = 0;
+ wd->sc_params.wdp_capabilities = 0;
+ } else {
+ strncpy(wd->sc_dk.dk_label->d_typename, "ESDI/IDE",
+ sizeof wd->sc_dk.dk_label->d_typename);
+ wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
+
+ /* Read in parameter block. */
+ insw(wdc->sc_iobase+wd_data, (u_int)tb, sizeof(tb) / sizeof(short));
+ bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
+
+ /* Shuffle string byte order. */
+ for (i = 0; i < sizeof(wd->sc_params.wdp_model); i += 2) {
+ u_short *p;
+ p = (u_short *)(wd->sc_params.wdp_model + i);
+ *p = ntohs(*p);
+ }
+ }
+
+ /* Clear any leftover interrupt. */
+ (void) inb(wdc->sc_iobase+wd_status);
+
+ /* Restart the queue. */
+ wdcstart(wdc);
+
+ splx(s);
+ return 0;
+}
+
+int
+wdioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t addr;
+ int flag;
+ struct proc *p;
+{
+ struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
+ int error;
+
+ if ((wd->sc_flags & WDF_LOADED) == 0)
+ return EIO;
+
+ switch (cmd) {
+ case DIOCSBAD:
+ if ((flag & FWRITE) == 0)
+ return EBADF;
+ wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
+ wd->sc_dk.dk_label->d_flags |= D_BADSECT;
+ bad144intern(wd);
+ return 0;
+
+ case DIOCGDINFO:
+ *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
+ return 0;
+
+ case DIOCGPART:
+ ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
+ ((struct partinfo *)addr)->part =
+ &wd->sc_dk.dk_label->d_partitions[WDPART(dev)];
+ return 0;
+
+ case DIOCWDINFO:
+ case DIOCSDINFO:
+ if ((flag & FWRITE) == 0)
+ return EBADF;
+
+ if (error = wdlock(wd))
+ return error;
+ wd->sc_flags |= WDF_LABELLING;
+
+ error = setdisklabel(wd->sc_dk.dk_label,
+ (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0,
+ wd->sc_dk.dk_cpulabel);
+ if (error == 0) {
+ if (wd->sc_state > GEOMETRY)
+ wd->sc_state = GEOMETRY;
+ if (cmd == DIOCWDINFO)
+ error = writedisklabel(WDLABELDEV(dev),
+ wdstrategy, wd->sc_dk.dk_label,
+ wd->sc_dk.dk_cpulabel);
+ }
+
+ wd->sc_flags &= ~WDF_LABELLING;
+ wdunlock(wd);
+ return error;
+
+ case DIOCWLABEL:
+ if ((flag & FWRITE) == 0)
+ return EBADF;
+ if (*(int *)addr)
+ wd->sc_flags |= WDF_WLABEL;
+ else
+ wd->sc_flags &= ~WDF_WLABEL;
+ return 0;
+
+#ifdef notyet
+ case DIOCWFORMAT:
+ if ((flag & FWRITE) == 0)
+ return EBADF;
+ {
+ register struct format_op *fop;
+ struct iovec aiov;
+ struct uio auio;
+
+ fop = (struct format_op *)addr;
+ aiov.iov_base = fop->df_buf;
+ aiov.iov_len = fop->df_count;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_resid = fop->df_count;
+ auio.uio_segflg = 0;
+ auio.uio_offset =
+ fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
+ auio.uio_procp = p;
+ error = physio(wdformat, NULL, dev, B_WRITE, minphys,
+ &auio);
+ fop->df_count -= auio.uio_resid;
+ fop->df_reg[0] = wdc->sc_status;
+ fop->df_reg[1] = wdc->sc_error;
+ return error;
+ }
+#endif
+
+ default:
+ return ENOTTY;
+ }
+
+#ifdef DIAGNOSTIC
+ panic("wdioctl: impossible");
+#endif
+}
+
+#ifdef B_FORMAT
+int
+wdformat(struct buf *bp)
+{
+
+ bp->b_flags |= B_FORMAT;
+ return wdstrategy(bp);
+}
+#endif
+
+int
+wdsize(dev)
+ dev_t dev;
+{
+ struct wd_softc *wd;
+ int part;
+ int size;
+
+ if (wdopen(dev, 0, S_IFBLK) != 0)
+ return -1;
+ wd = wd_cd.cd_devs[WDUNIT(dev)];
+ part = WDPART(dev);
+ if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
+ size = -1;
+ else
+ size = wd->sc_dk.dk_label->d_partitions[part].p_size;
+ if (wdclose(dev, 0, S_IFBLK) != 0)
+ return -1;
+ return size;
+}
+
+
+#ifndef __BDEVSW_DUMP_OLD_TYPE
+/* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
+static int wddoingadump;
+static int wddumprecalibrated;
+
+/*
+ * Dump core after a system crash.
+ */
+int
+wddump(dev, blkno, va, size)
+ dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
+{
+ struct wd_softc *wd; /* disk unit to do the I/O */
+ struct wdc_softc *wdc; /* disk controller to do the I/O */
+ struct disklabel *lp; /* disk's disklabel */
+ int unit, part;
+ int nblks; /* total number of sectors left to write */
+
+ /* Check if recursive dump; if so, punt. */
+ if (wddoingadump)
+ return EFAULT;
+ wddoingadump = 1;
+
+ unit = WDUNIT(dev);
+ if (unit >= wd_cd.cd_ndevs)
+ return ENXIO;
+ wd = wd_cd.cd_devs[unit];
+ if (wd == 0)
+ return ENXIO;
+
+ part = WDPART(dev);
+
+ /* Make sure it was initialized. */
+ if (wd->sc_state < OPEN)
+ return ENXIO;
+
+ wdc = (void *)wd->sc_dev.dv_parent;
+
+ /* Convert to disk sectors. Request must be a multiple of size. */
+ lp = wd->sc_dk.dk_label;
+ if ((size % lp->d_secsize) != 0)
+ return EFAULT;
+ nblks = size / lp->d_secsize;
+ blkno = blkno / (lp->d_secsize / DEV_BSIZE);
+
+ /* Check transfer bounds against partition size. */
+ if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
+ return EINVAL;
+
+ /* Offset block number to start of partition. */
+ blkno += lp->d_partitions[part].p_offset;
+
+ /* Recalibrate, if first dump transfer. */
+ if (wddumprecalibrated == 0) {
+ wddumprecalibrated = 1;
+ if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0 ||
+ wait_for_ready(wdc) != 0 || wdsetctlr(wd) != 0 ||
+ wait_for_ready(wdc) != 0) {
+ wderror(wd, NULL, "wddump: recal failed");
+ return EIO;
+ }
+ }
+
+ while (nblks > 0) {
+ daddr_t xlt_blkno = blkno;
+ long cylin, head, sector;
+
+ if ((lp->d_flags & D_BADSECT) != 0) {
+ long blkdiff;
+ int i;
+
+ for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
+ blkdiff -= xlt_blkno;
+ if (blkdiff < 0)
+ continue;
+ if (blkdiff == 0) {
+ /* Replace current block of transfer. */
+ xlt_blkno = lp->d_secperunit -
+ lp->d_nsectors - i - 1;
+ }
+ break;
+ }
+ /* Tranfer is okay now. */
+ }
+
+ if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
+ sector = (xlt_blkno >> 0) & 0xff;
+ cylin = (xlt_blkno >> 8) & 0xffff;
+ head = (xlt_blkno >> 24) & 0xf;
+ head |= WDSD_LBA;
+ } else {
+ sector = xlt_blkno % lp->d_nsectors;
+ sector++; /* Sectors begin with 1, not 0. */
+ xlt_blkno /= lp->d_nsectors;
+ head = xlt_blkno % lp->d_ntracks;
+ xlt_blkno /= lp->d_ntracks;
+ cylin = xlt_blkno;
+ head |= WDSD_CHS;
+ }
+
+#ifndef WD_DUMP_NOT_TRUSTED
+ if (wdcommand(wd, WDCC_WRITE, cylin, head, sector, 1) != 0 ||
+ wait_for_drq(wdc) != 0) {
+ wderror(wd, NULL, "wddump: write failed");
+ return EIO;
+ }
+
+ outsw(wdc->sc_iobase+wd_data, (u_int)va, lp->d_secsize >> 1);
+
+ /* Check data request (should be done). */
+ if (wait_for_ready(wdc) != 0) {
+ wderror(wd, NULL, "wddump: timeout waiting for ready");
+ return EIO;
+ }
+#else /* WD_DUMP_NOT_TRUSTED */
+ /* Let's just talk about this first... */
+ printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
+ unit, va, cylin, head, sector);
+ delay(500 * 1000); /* half a second */
+#endif
+
+ /* update block count */
+ nblks -= 1;
+ blkno += 1;
+ va += lp->d_secsize;
+ }
+
+ wddoingadump = 0;
+ return 0;
+}
+#else /* __BDEVSW_DUMP_NEW_TYPE */
+int
+wddump(dev, blkno, va, size)
+ dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
+{
+
+ /* Not implemented. */
+ return ENXIO;
+}
+#endif /* __BDEVSW_DUMP_NEW_TYPE */
+
+/*
+ * Internalize the bad sector table.
+ */
+void
+bad144intern(wd)
+ struct wd_softc *wd;
+{
+ struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
+ struct disklabel *lp = wd->sc_dk.dk_label;
+ int i = 0;
+
+ for (; i < 126; i++) {
+ if (bt->bt_bad[i].bt_cyl == 0xffff)
+ break;
+ wd->sc_badsect[i] =
+ bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
+ (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
+ (bt->bt_bad[i].bt_trksec & 0xff);
+ }
+ for (; i < 127; i++)
+ wd->sc_badsect[i] = -1;
+}
+
+int
+wdcreset(wdc)
+ struct wdc_softc *wdc;
+{
+ int iobase = wdc->sc_iobase;
+
+ /* Reset the device. */
+ if (wdresethack) {
+ outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
+ delay(1000);
+ outb(iobase+wd_ctlr, WDCTL_IDS);
+ delay(1000);
+ (void) inb(iobase+wd_error);
+ outb(iobase+wd_ctlr, WDCTL_4BIT);
+ }
+
+ if (wait_for_unbusy(wdc) < 0) {
+ printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+wdcrestart(arg)
+ void *arg;
+{
+ struct wdc_softc *wdc = arg;
+ int s;
+
+ s = splbio();
+ wdcstart(wdc);
+ splx(s);
+}
+
+/*
+ * Unwedge the controller after an unexpected error. We do this by resetting
+ * it, marking all drives for recalibration, and stalling the queue for a short
+ * period to give the reset time to finish.
+ * NOTE: We use a timeout here, so this routine must not be called during
+ * autoconfig or dump.
+ */
+void
+wdcunwedge(wdc)
+ struct wdc_softc *wdc;
+{
+ int unit;
+
+ untimeout(wdctimeout, wdc);
+ (void) wdcreset(wdc);
+
+ /* Schedule recalibrate for all drives on this controller. */
+ for (unit = 0; unit < wd_cd.cd_ndevs; unit++) {
+ struct wd_softc *wd = wd_cd.cd_devs[unit];
+ if (!wd || (void *)wd->sc_dev.dv_parent != wdc)
+ continue;
+ if (wd->sc_state > RECAL)
+ wd->sc_state = RECAL;
+ }
+
+ wdc->sc_flags |= WDCF_ERROR;
+ ++wdc->sc_errors;
+
+ /* Wake up in a little bit and restart the operation. */
+ timeout(wdcrestart, wdc, RECOVERYTIME);
+}
+
+int
+wdcwait(wdc, mask)
+ struct wdc_softc *wdc;
+ int mask;
+{
+ int iobase = wdc->sc_iobase;
+ int timeout = 0;
+ u_char status;
+ extern int cold;
+
+ for (;;) {
+ wdc->sc_status = status = inb(iobase+wd_status);
+ if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
+ break;
+ if (++timeout > WDCNDELAY)
+ return -1;
+ delay(WDCDELAY);
+ }
+ if (status & WDCS_ERR) {
+ wdc->sc_error = inb(iobase+wd_error);
+ return WDCS_ERR;
+ }
+#ifdef WDCNDELAY_DEBUG
+ /* After autoconfig, there should be no long delays. */
+ if (!cold && timeout > WDCNDELAY_DEBUG)
+ printf("%s: warning: busy-wait took %dus\n",
+ wdc->sc_dev.dv_xname, WDCDELAY * timeout);
+#endif
+ return 0;
+}
+
+void
+wdctimeout(arg)
+ void *arg;
+{
+ struct wdc_softc *wdc = (struct wdc_softc *)arg;
+ int s;
+
+ s = splbio();
+ if ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
+ struct wd_softc *wd = wdc->sc_drives.tqh_first;
+ struct buf *bp = wd->sc_q.b_actf;
+
+ wdc->sc_flags &= ~WDCF_ACTIVE;
+ wderror(wdc, NULL, "lost interrupt");
+ printf("%s: lost interrupt: %sing %d@%s:%d\n",
+ wdc->sc_dev.dv_xname,
+ (bp->b_flags & B_READ) ? "read" : "writ",
+ wd->sc_nblks, wd->sc_dev.dv_xname, wd->sc_blkno);
+ wdcunwedge(wdc);
+ } else
+ wderror(wdc, NULL, "missing untimeout");
+ splx(s);
+}
+
+void
+wderror(dev, bp, msg)
+ void *dev;
+ struct buf *bp;
+ char *msg;
+{
+ struct wd_softc *wd = dev;
+ struct wdc_softc *wdc = dev;
+
+ if (bp) {
+ diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE,
+ wd->sc_dk.dk_label);
+ printf("\n");
+ } else
+ printf("%s: %s: status %b error %b\n", wdc->sc_dev.dv_xname,
+ msg, wdc->sc_status, WDCS_BITS, wdc->sc_error, WDERR_BITS);
+}
--- /dev/null
+/* $NetBSD: wdreg.h,v 1.1 1996/01/31 23:25:18 mark Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)wdreg.h 7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * Disk Controller register definitions.
+ */
+#define wd_data 0x000 /* data register (R/W - 16 bits) */
+#define wd_error 0x004 /* error register (R) */
+#define wd_precomp 0x004 /* write precompensation (W) */
+#define wd_features 0x004 /* features (W) */
+#define wd_seccnt 0x008 /* sector count (R/W) */
+#define wd_sector 0x00c /* first sector number (R/W) */
+#define wd_cyl_lo 0x010 /* cylinder address, low byte (R/W) */
+#define wd_cyl_hi 0x014 /* cylinder address, high byte (R/W) */
+#define wd_sdh 0x018 /* sector size/drive/head (R/W) */
+#define wd_command 0x01c /* command register (W) */
+#define wd_status 0x01c /* immediate status (R) */
+
+#define wd_altsts 0x818 /* alternate fixed disk status (via 1015) (R) */
+#define wd_ctlr 0x818 /* fixed disk controller control (via 1015) (W) */
+#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */
+#define WDCTL_RST 0x04 /* reset the controller */
+#define WDCTL_IDS 0x02 /* disable controller interrupts */
+#define wd_digin 0x81c /* disk controller input (via 1015) (R) */
+
+/*
+ * Status bits.
+ */
+#define WDCS_BSY 0x80 /* busy */
+#define WDCS_DRDY 0x40 /* drive ready */
+#define WDCS_DWF 0x20 /* drive write fault */
+#define WDCS_DSC 0x10 /* drive seek complete */
+#define WDCS_DRQ 0x08 /* data request */
+#define WDCS_CORR 0x04 /* corrected data */
+#define WDCS_IDX 0x02 /* index */
+#define WDCS_ERR 0x01 /* error */
+#define WDCS_BITS "\020\010bsy\007drdy\006dwf\005dsc\004drq\003corr\002idx\001err"
+
+/*
+ * Error bits.
+ */
+#define WDCE_BBK 0x80 /* bad block detected */
+#define WDCE_UNC 0x40 /* uncorrectable data error */
+#define WDCE_MC 0x20 /* media changed */
+#define WDCE_IDNF 0x10 /* id not found */
+#define WDCE_ABRT 0x08 /* aborted command */
+#define WDCE_MCR 0x04 /* media change requested */
+#define WDCE_TK0NF 0x02 /* track 0 not found */
+#define WDCE_AMNF 0x01 /* address mark not found */
+#define WDERR_BITS "\020\010bbk\007unc\006mc\005idnf\004mcr\003abrt\002tk0nf\001amnf"
+
+/*
+ * Commands for Disk Controller.
+ */
+#define WDCC_RECAL 0x10 /* disk restore code -- resets cntlr */
+
+#define WDCC_READ 0x20 /* disk read code */
+#define WDCC_WRITE 0x30 /* disk write code */
+#define WDCC__LONG 0x02 /* modifier -- access ecc bytes */
+#define WDCC__NORETRY 0x01 /* modifier -- no retrys */
+
+#define WDCC_FORMAT 0x50 /* disk format code */
+#define WDCC_DIAGNOSE 0x90 /* controller diagnostic */
+#define WDCC_IDP 0x91 /* initialize drive parameters */
+
+#define WDCC_READMULTI 0xc4 /* read multiple */
+#define WDCC_WRITEMULTI 0xc5 /* write multiple */
+#define WDCC_SETMULTI 0xc6 /* set multiple mode */
+
+#define WDCC_READDMA 0xc8 /* read with DMA */
+#define WDCC_WRITEDMA 0xca /* write with DMA */
+
+#define WDCC_ACKMC 0xdb /* acknowledge media change */
+#define WDCC_LOCK 0xde /* lock drawer */
+#define WDCC_UNLOCK 0xdf /* unlock drawer */
+
+#define WDCC_IDENTIFY 0xec /* read parameters from controller */
+#define WDCC_CACHEC 0xef /* cache control */
+
+#define WDSD_IBM 0xa0 /* forced to 512 byte sector, ecc */
+#define WDSD_CHS 0x00 /* cylinder/head/sector addressing */
+#define WDSD_LBA 0x40 /* logical block addressing */
+
+
+#ifdef _KERNEL
+/*
+ * read parameters command returns this:
+ */
+struct wdparams {
+ /* drive info */
+ short wdp_config; /* general configuration */
+#define WD_CFG_REMOVABLE 0x0080
+#define WD_CFG_FIXED 0x0040
+ short wdp_cylinders; /* number of non-removable cylinders */
+ char __reserved1[2];
+ short wdp_heads; /* number of heads */
+ short wdp_unfbytespertrk; /* number of unformatted bytes/track */
+ short wdp_unfbytespersec; /* number of unformatted bytes/sector */
+ short wdp_sectors; /* number of sectors */
+ char wdp_vendor1[6];
+ /* controller info */
+ char wdp_serial[20]; /* serial number */
+ short wdp_buftype; /* buffer type */
+#define WD_BUF_SINGLEPORTSECTOR 1 /* single port, single sector buffer */
+#define WD_BUF_DUALPORTMULTI 2 /* dual port, multiple sector buffer */
+#define WD_BUF_DUALPORTMULTICACHE 3 /* above plus track cache */
+ short wdp_bufsize; /* buffer size, in 512-byte units */
+ short wdp_eccbytes; /* ecc bytes appended */
+ char wdp_revision[8]; /* firmware revision */
+ char wdp_model[40]; /* model name */
+ u_char wdp_maxmulti; /* maximum sectors per interrupt */
+ char wdp_vendor2[1];
+ short wdp_usedmovsd; /* can use double word read/write? */
+ char wdp_vendor3[1];
+ char wdp_capabilities; /* capability flags */
+#define WD_CAP_LBA 0x02
+#define WD_CAP_DMA 0x01
+ char __reserved2[2];
+ char wdp_vendor4[1];
+ char wdp_piotiming; /* PIO timing mode */
+ char wdp_vendor5[1];
+ char wdp_dmatiming; /* DMA timing mode */
+};
+#endif /* _KERNEL */
--- /dev/null
+/* $NetBSD: asc.c,v 1.5 1996/04/19 20:13:56 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from:ahsc.c
+ */
+
+/*
+ * Ok this driver is not wonderful yet. It only supports POLLING mode
+ * The Acorn SCSI card (or any WD3393 based card) does not support
+ * DMA so the DMA section of this driver and the sbic driver needs
+ * to be rewritten.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/sbicreg.h>
+#include <arm32/podulebus/sbicvar.h>
+#include <arm32/podulebus/ascreg.h>
+#include <arm32/podulebus/ascvar.h>
+
+int ascprint __P((void *auxp, char *));
+void ascattach __P((struct device *, struct device *, void *));
+int ascmatch __P((struct device *, void *, void *));
+
+void asc_enintr __P((struct sbic_softc *));
+void asc_dmastop __P((struct sbic_softc *));
+int asc_dmanext __P((struct sbic_softc *));
+int asc_dmaintr __P((struct sbic_softc *));
+int asc_dmago __P((struct sbic_softc *, char *, int, int));
+int asc_scsicmd __P((struct scsi_xfer *xs));
+int asc_intr __P((struct asc_softc *));
+
+char *strstr __P((char */*s1*/, char */*s2*/));
+
+struct scsi_adapter asc_scsiswitch = {
+ asc_scsicmd,
+ sbic_minphys,
+ 0, /* no lun support */
+ 0, /* no lun support */
+};
+
+struct scsi_device asc_scsidev = {
+ NULL, /* use default error handler */
+ NULL, /* do not have a start functio */
+ NULL, /* have no async handler */
+ NULL, /* Use default done routine */
+};
+
+
+#ifdef DEBUG
+int asc_dmadebug = 0;
+#endif
+
+struct cfattach asc_ca = {
+ sizeof(struct asc_softc), ascmatch, ascattach
+};
+
+struct cfdriver asc_cd = {
+ NULL, "asc", DV_DULL, NULL, 0
+};
+
+u_long scsi_nosync;
+int shift_nosync;
+
+#if ASC_POLL > 0
+int asc_poll = 1;
+
+extern char *boot_args;
+#endif
+
+int
+ascmatch(pdp, match, auxp)
+ struct device *pdp;
+ void *match, *auxp;
+{
+ struct podule_attach_args *pa = (struct podule_attach_args *)auxp;
+ int podule;
+
+ podule = findpodule(0x00, 0x02, pa->pa_podule_number);
+
+ if (podule == -1)
+ return(0);
+
+ pa->pa_podule_number = podule;
+ pa->pa_podule = &podules[podule];
+
+ return(1);
+}
+
+void
+ascattach(pdp, dp, auxp)
+ struct device *pdp, *dp;
+ void *auxp;
+{
+ volatile struct sdmac *rp;
+ struct asc_softc *sc;
+ struct sbic_softc *sbic;
+ struct podule_attach_args *pa;
+
+ sc = (struct asc_softc *)dp;
+
+ pa = (struct podule_attach_args *)auxp;
+ sc->sc_podule_number = pa->pa_podule_number;
+ if (sc->sc_podule_number == -1)
+ panic("Podule has disappeared !");
+
+ sc->sc_podule = &podules[sc->sc_podule_number];
+ podules[sc->sc_podule_number].attached = 1;
+
+#if ASC_POLL > 0
+ if (boot_args) {
+ char *ptr;
+
+ ptr = strstr(boot_args, "noascpoll");
+ if (ptr)
+ asc_poll = 0;
+ }
+
+ if (asc_poll)
+ printf(" polling");
+ else
+ printf(" using interrupts");
+#endif
+ printf("\n");
+
+ sbic = &sc->sc_softc;
+
+ sbic->sc_enintr = asc_enintr;
+ sbic->sc_dmago = asc_dmago;
+ sbic->sc_dmanext = asc_dmanext;
+ sbic->sc_dmastop = asc_dmastop;
+ sbic->sc_dmacmd = 0;
+
+ /*
+ * eveything is a valid dma address
+ */
+ sbic->sc_dmamask = 0;
+ sbic->sc_sbicp = (sbic_regmap_p) (sc->sc_podule->mod_base + ASC_SBIC);
+ sbic->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 143;
+
+ sbic->sc_link.adapter_softc = sbic;
+ sbic->sc_link.adapter_target = 7;
+ sbic->sc_link.adapter = &asc_scsiswitch;
+ sbic->sc_link.device = &asc_scsidev;
+ sbic->sc_link.openings = 1; /* was 2 */
+
+ sc->sc_pagereg = sc->sc_podule->fast_base + ASC_PAGEREG;
+ sc->sc_intstat = sc->sc_podule->fast_base + ASC_INTSTATUS;
+
+ /* Reset the card */
+
+ WriteByte(sc->sc_pagereg, 0x80);
+ DELAY(500000);
+ WriteByte(sc->sc_pagereg, 0x00);
+ DELAY(250000);
+
+ sbicinit(sbic);
+
+/* If we are polling only then we don't need a interrupt handler */
+
+ sc->sc_ih.ih_func = asc_intr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_BIO;
+ sc->sc_ih.ih_name = "asc";
+
+#ifdef ASC_POLL
+ if (!asc_poll)
+#endif
+ if (irq_claim(IRQ_PODULE, &sc->sc_ih))
+ panic("asc: Cannot claim podule IRQ\n");
+
+ /*
+ * attach all scsi units on us
+ */
+ config_found(dp, &sbic->sc_link, ascprint);
+}
+
+/*
+ * print diag if pnp is NULL else just extra
+ */
+int
+ascprint(auxp, pnp)
+ void *auxp;
+ char *pnp;
+{
+ if (pnp == NULL)
+ return(UNCONF);
+ return(QUIET);
+}
+
+
+void
+asc_enintr(sbicsc)
+ struct sbic_softc *sbicsc;
+{
+ struct asc_softc *sc = (struct asc_softc *)sbicsc;
+/* printf("asc_enintr\n");*/
+/*
+ volatile struct sdmac *sdp;
+
+ sdp = dev->sc_cregs;
+
+ dev->sc_flags |= SBICF_INTR;
+ sdp->CNTR = CNTR_PDMD | CNTR_INTEN;
+*/
+ sbicsc->sc_flags |= SBICF_INTR;
+ WriteByte(sc->sc_pagereg, 0x40);
+}
+
+
+int
+asc_dmago(dev, addr, count, flags)
+ struct sbic_softc *dev;
+ char *addr;
+ int count, flags;
+{
+ printf("asc_dmago\n");
+#ifdef DDB
+ Debugger();
+#else
+ panic("Hit a brick wall\n");
+#endif
+#if 0
+ volatile struct sdmac *sdp;
+
+ sdp = dev->sc_cregs;
+ /*
+ * Set up the command word based on flags
+ */
+ dev->sc_dmacmd = CNTR_PDMD | CNTR_INTEN;
+ if ((flags & DMAGO_READ) == 0)
+ dev->sc_dmacmd |= CNTR_DDIR;
+#ifdef DEBUG
+ if (ahsc_dmadebug & DDB_IO)
+ printf("ahsc_dmago: cmd %x\n", dev->sc_dmacmd);
+#endif
+
+ dev->sc_flags |= SBICF_INTR;
+ sdp->CNTR = dev->sc_dmacmd;
+ sdp->ACR = (u_int) dev->sc_cur->dc_addr;
+ sdp->ST_DMA = 1;
+
+ return(dev->sc_tcnt);
+#endif
+}
+
+void
+asc_dmastop(dev)
+ struct sbic_softc *dev;
+{
+/* printf("asc_dmastop\n");*/
+#if 0
+ volatile struct sdmac *sdp;
+ int s;
+
+ sdp = dev->sc_cregs;
+
+#ifdef DEBUG
+ if (ahsc_dmadebug & DDB_FOLLOW)
+ printf("ahsc_dmastop()\n");
+#endif
+ if (dev->sc_dmacmd) {
+ s = splbio();
+ if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
+ /*
+ * only FLUSH if terminal count not enabled,
+ * and reading from peripheral
+ */
+ sdp->FLUSH = 1;
+ while ((sdp->ISTR & ISTR_FE_FLG) == 0)
+ ;
+ }
+ /*
+ * clear possible interrupt and stop dma
+ */
+ sdp->CINT = 1;
+ sdp->SP_DMA = 1;
+ dev->sc_dmacmd = 0;
+ splx(s);
+ }
+#endif
+}
+
+int
+asc_dmaintr(dev)
+ struct sbic_softc *dev;
+{
+ panic("asc_dmaintr");
+#if 0
+ volatile struct sdmac *sdp;
+ int stat, found;
+
+ sdp = dev->sc_cregs;
+ stat = sdp->ISTR;
+
+ if ((stat & (ISTR_INT_F|ISTR_INT_P)) == 0)
+ return (0);
+
+#ifdef DEBUG
+ if (ahsc_dmadebug & DDB_FOLLOW)
+ printf("%s: dmaintr 0x%x\n", dev->sc_dev.dv_xname, stat);
+#endif
+
+ /*
+ * both, SCSI and DMA interrupts arrive here. I chose
+ * arbitrarily that DMA interrupts should have higher
+ * precedence than SCSI interrupts.
+ */
+ found = 0;
+ if (stat & ISTR_E_INT) {
+ ++found;
+
+ sdp->CINT = 1; /* clear possible interrupt */
+
+ /*
+ * check for SCSI ints in the same go and
+ * eventually save an interrupt
+ */
+ }
+
+ if (dev->sc_flags & SBICF_INTR && stat & ISTR_INTS)
+ found += sbicintr(dev);
+ return(found);
+#endif
+}
+
+
+int
+asc_dmanext(dev)
+ struct sbic_softc *dev;
+{
+ printf("asc_dmanext\n");
+#ifdef DDB
+ Debugger();
+#else
+ panic("Hit a brick wall\n");
+#endif
+#if 0
+ volatile struct sdmac *sdp;
+ int i, stat;
+
+ sdp = dev->sc_cregs;
+
+ if (dev->sc_cur > dev->sc_last) {
+ /* shouldn't happen !! */
+ printf("ahsc_dmanext at end !!!\n");
+ asc_dmastop(dev);
+ return(0);
+ }
+ if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) {
+ /*
+ * only FLUSH if terminal count not enabled,
+ * and reading from peripheral
+ */
+ sdp->FLUSH = 1;
+ while ((sdp->ISTR & ISTR_FE_FLG) == 0)
+ ;
+ }
+ /*
+ * clear possible interrupt and stop dma
+ */
+ sdp->CINT = 1; /* clear possible interrupt */
+ sdp->SP_DMA = 1; /* stop dma */
+ sdp->CNTR = dev->sc_dmacmd;
+ sdp->ACR = (u_int)dev->sc_cur->dc_addr;
+ sdp->ST_DMA = 1;
+
+ dev->sc_tcnt = dev->sc_cur->dc_count << 1;
+ return(dev->sc_tcnt);
+#endif
+}
+
+void
+asc_dump()
+{
+ int i;
+
+ for (i = 0; i < asc_cd.cd_ndevs; ++i)
+ if (asc_cd.cd_devs[i])
+ sbic_dump(asc_cd.cd_devs[i]);
+}
+
+int
+asc_scsicmd(xs)
+ struct scsi_xfer *xs;
+{
+ struct scsi_link *sc_link = xs->sc_link;
+
+ /* ensure command is polling for the moment */
+#if ASC_POLL > 0
+ if (asc_poll)
+ xs->flags |= SCSI_POLL;
+#endif
+
+/* printf("id=%d lun=%dcmdlen=%d datalen=%d opcode=%02x flags=%08x status=%02x blk=%02x %02x\n",
+ sc_link->target, sc_link->lun, xs->cmdlen, xs->datalen, xs->cmd->opcode,
+ xs->flags, xs->status, xs->cmd->bytes[0], xs->cmd->bytes[1]);*/
+
+ return(sbic_scsicmd(xs));
+}
+
+
+int
+asc_intr(sc)
+ struct asc_softc *sc;
+{
+ int intr;
+
+/* printf("ascintr:");*/
+ intr = ReadByte(sc->sc_intstat);
+/* printf("%02x\n", intr);*/
+
+ if (intr & IS_SBIC_IRQ)
+ sbicintr((struct sbic_softc *)sc);
+ return(0);
+}
+
+
+int kvtop()
+{
+ printf("kvtop\n");
+#ifdef DDB
+ Debugger();
+#else
+ panic("Hit a brick wall\n");
+#endif
+ return(0);
+}
+
+void alloc_z2mem()
+{
+ panic("allocz2mem");
+}
+
+void isztwomem()
+{
+ panic("isz2mem");
+}
+
+void PREP_DMA_MEM()
+{
+ panic("PREP_DMA_MEM");
+}
--- /dev/null
+/* $NetBSD: ascreg.h,v 1.4 1996/03/07 23:54:29 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ * Copyright (c) 1994 Christian E. Hopps
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from:ahscreg.h,v 1.2 1994/10/26 02:02:46
+ */
+
+#ifndef _ASCREG_H_
+#define _ASCREG_H_
+
+/*
+ * Hardware layout of the A3000 SDMAC. This also contains the
+ * registers for the sbic chip, but in favor of separating DMA and
+ * scsi, the scsi-driver doesn't make use of this dependency
+ */
+
+#define v_char volatile char
+#define v_int volatile int
+#define vu_char volatile u_char
+#define vu_short volatile u_short
+#define vu_int volatile u_int
+
+struct sdmac {
+ short pad0;
+ vu_short DAWR; /* DACK Width Register WO */
+ vu_int WTC; /* Word Transfer Count Register RW */
+ short pad1;
+ vu_short CNTR; /* Control Register RW */
+ vu_int ACR; /* Address Count Register RW */
+ short pad2;
+ vu_short ST_DMA; /* Start DMA Transfers RW-Strobe */
+ short pad3;
+ vu_short FLUSH; /* Flush FIFO RW-Strobe */
+ short pad4;
+ vu_short CINT; /* Clear Interrupts RW-Strobe */
+ short pad5;
+ vu_short ISTR; /* Interrupt Status Register RO */
+ int pad6[7];
+ short pad7;
+ vu_short SP_DMA; /* Stop DMA Transfers RW-Strobe */
+ char pad8;
+ vu_char SASR; /* sbic asr */
+ char pad9;
+ vu_char SCMD; /* sbic data */
+};
+
+/*
+ * value to go into DAWR
+ */
+#define DAWR_AHSC 3 /* according to A3000T service-manual */
+
+/*
+ * bits defined for CNTR
+ */
+#define CNTR_TCEN (1<<5) /* Terminal Count Enable */
+#define CNTR_PREST (1<<4) /* Perp Reset (not implemented :-((( ) */
+#define CNTR_PDMD (1<<3) /* Perp Device Mode Select (1=SCSI,0=XT/AT) */
+#define CNTR_INTEN (1<<2) /* Interrupt Enable */
+#define CNTR_DDIR (1<<1) /* Device Direction. 1==rd host, wr perp */
+#define CNTR_IO_DX (1<<0) /* IORDY & CSX1 Polarity Select */
+
+/*
+ * bits defined for ISTR
+ */
+#define ISTR_INTX (1<<8) /* XT/AT Interrupt pending */
+#define ISTR_INT_F (1<<7) /* Interrupt Follow */
+#define ISTR_INTS (1<<6) /* SCSI Peripheral Interrupt */
+#define ISTR_E_INT (1<<5) /* End-Of-Process Interrupt */
+#define ISTR_INT_P (1<<4) /* Interrupt Pending */
+#define ISTR_UE_INT (1<<3) /* Under-Run FIFO Error Interrupt */
+#define ISTR_OE_INT (1<<2) /* Over-Run FIFO Error Interrupt */
+#define ISTR_FF_FLG (1<<1) /* FIFO-Full Flag */
+#define ISTR_FE_FLG (1<<0) /* FIFO-Empty Flag */
+
+#define DMAGO_READ 0x01
+
+
+/* Addresses relative to podule base */
+
+#define ASC_INTSTATUS 0x2000
+#define ASC_CLRINT 0x2000
+#define ASC_PAGEREG 0x3000
+
+/* Addresses relative to module base */
+
+#define ASC_DMAC 0x3000
+#define ASC_SBIC 0x2000
+#define ASC_SRAM 0x0000
+
+#define ASC_SRAM_BLKSIZE 0x1000
+
+#define IS_IRQREQ 0x01
+#define IS_DMAC_IRQ 0x02
+#define IS_SBIC_IRQ 0x08
+
+#if 0
+/* SBIC Commands */
+
+#define SBIC_CMD_Reset 0x00 /* Reset the SBIC */
+#define SBIC_Abort 0x01 /* Abort command */
+#define SBIC_Sel_tx_wATN 0x08 /* Select and Transfer with ATN */
+#define SBIC_Sel_tx_woATN 0x09 /* Select and Transfer without ATN */
+
+/* SBIC status codes */
+
+#define SBIC_ResetOk 0x00
+#define SBIC_ResetAFOk 0x01
+
+/* SBIC registers bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 */
+
+#define SBIC_OWNID 0x00 /* RW FS1 FS0 0 EHP EAF ID2 ID1 ID0 */
+#define SBIC_CONTROL 0x01 /* RW DM2 DM1 DM0 HHP EDI IDI HA HSP */
+#define SBIC_TIMEREG 0x02 /* RW timeout period value = Tper*Ficlk/80d */
+#define SBIC_CDB1TSECT 0x03 /* RW CDB byte 1 & Total sectors per track */
+#define SBIC_CDB2THEAD 0x04 /* RW CDB byte 2 & Total number of heads */
+#define SBIC_CDB3TCYL1 0x05 /* RW CDB byte 3 & Total no. of cylinders MSB */
+#define SBIC_CDB4TCYL2 0x06 /* RW CDB byte 4 & Total no. of cylinders LSB */
+#define SBIC_CDB5LADR1 0x07 /* RW CDB byte 5 & Logical addr to translate */
+#define SBIC_CBD6LADR2 0x08 /* RW CDB byte 6 & Logical addr to translate */
+#define SBIC_CDB7LADR3 0x09 /* RW CDB byte 7 & Logical addr to translate */
+#define SBIC_CDB8LADR4 0x0A /* RW CDB byte 8 & Logical addr to translate */
+#define SBIC_CDB9SECT 0x0B /* RW CDB byte 9 & Translation sector result */
+#define SBIC_CDB10HEAD 0x0C /* RW CDB byte 10 & Translation head result */
+#define SBIC_CDB11CYL1 0x0D /* RW CDB byte 11 & Translation cyl result MSB*/
+#define SBIC_CDB12CYL2 0x0E /* RW CDB byte 12 & Translation cyl result LSB*/
+#define SBIC_TARGETLUN 0x0F /* RW TLV DOK 0 0 0 TL2 TL1 TL0 */
+#define SBIC_COMPHASE 0x10 /* RW Command Phase Register for multi-phase */
+#define SBIC_SYNCTX 0x11 /* RW 0 TP2 TP1 TP0 OF3 OF2 OF1 OF0 */
+#define SBIC_TXCOUNT1 0x12 /* RW Transfer count MSB */
+#define SBIC_TXCOUNT2 0x13 /* RW Transfer count */
+#define SBIC_TXCOUNT3 0x14 /* RW Transfer count LSB */
+#define SBIC_DESTID 0x15 /* RW SCC DPD 0 0 0 DI2 DI1 DI0 */
+#define SBIC_SOURCEID 0x16 /* RW ER ES DSP 0 SIV SI2 SI1 SI0 */
+#define SBIC_SCSISTAT 0x17 /* RO **Interrupt type*** **Int. qualifier** */
+#define SBIC_COMMAND 0x18 /* RW SBT *********Command code************* */
+#define SBIC_DATA 0x19 /* RW Access to data i/o FIFO for polled use */
+
+#define SBIC_ADDRREG 0x00
+#define SBIC_DATAREG 0x04
+#define SBIC_AUX_STATUS 0x00
+
+/*
+ * My ID register, and/or CDB Size
+ */
+
+#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */
+ /* 11 Mhz is invalid */
+#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */
+#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */
+#define SBIC_ID_EHP 0x10 /* Enable host parity */
+#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */
+#define SBIC_ID_MASK 0x07
+#define SBIC_ID_CBDSIZE_MASK 0x0f /* if unk SCSI cmd group */
+
+/*
+ * Control register
+*/
+
+#define SBIC_CTL_DMA 0x80 /* Single byte dma */
+#define SBIC_CTL_DBA_DMA 0x40 /* direct buffer acces (bus master)*/
+#define SBIC_CTL_BURST_DMA 0x20 /* continuous mode (8237) */
+#define SBIC_CTL_NO_DMA 0x00 /* Programmed I/O */
+#define SBIC_CTL_HHP 0x10 /* Halt on host parity error */
+#define SBIC_CTL_EDI 0x08 /* Ending disconnect interrupt */
+#define SBIC_CTL_IDI 0x04 /* Intermediate disconnect interrupt*/
+#define SBIC_CTL_HA 0x02 /* Halt on ATN */
+#define SBIC_CTL_HSP 0x01 /* Halt on SCSI parity error */
+
+/*
+ * Destination ID register
+ */
+
+#define SBIC_DID_DPD 0x40 /* Data Phase Direction */
+
+/*
+ * Auxiliary Status Register
+ */
+
+#define SBIC_ASR_INT 0x80 /* Interrupt pending */
+#define SBIC_ASR_LCI 0x40 /* Last command ignored */
+#define SBIC_ASR_BSY 0x20 /* Busy, only cmd/data/asr readable */
+#define SBIC_ASR_CIP 0x10 /* Busy, cmd unavail also */
+#define SBIC_ASR_xxx 0x0c
+#define SBIC_ASR_PE 0x02 /* Parity error (even) */
+#define SBIC_ASR_DBR 0x01 /* Data Buffer Ready */
+
+/* DMAC constants */
+
+#define DMAC_Bits 0x01
+#define DMAC_Ctrl1 0x60
+#define DMAC_Ctrl2 0x01
+#define DMAC_CLEAR_MASK 0x0E
+#define DMAC_SET_MASK 0x0F
+#define DMAC_DMA_RD_MODE 0x04
+#define DMAC_DMA_WR_MODE 0x08
+
+/* DMAC registers */
+
+#define DMAC_INITIALISE 0x0000 /* WO ---- ---- ---- ---- ---- ---- 16B RES */
+#define DMAC_CHANNEL 0x0200 /* R ---- ---- ---- BASE SEL3 SEL2 SEL1 SEL0 */
+ /* W ---- ---- ---- ---- ---- BASE *SELECT** */
+#define DMAC_TXCNTLO 0x0004 /* RW C7 C6 C5 C4 C3 C2 C1 C0 */
+#define DMAC_TXCNTHI 0x0204 /* RW C15 C14 C13 C12 C11 C10 C9 C8 */
+#define DMAC_TXADRLO 0x0008 /* RW A7 A6 A5 A4 A3 A2 A1 A0 */
+#define DMAC_TXADRMD 0x0208 /* RW A15 A14 A13 A12 A11 A10 A9 A8 */
+#define DMAC_TXADRHI 0x000C /* RW A23 A22 A21 A20 A19 A18 A17 A16 */
+#define DMAC_DEVCON1 0x0010 /* RW AKL RQL EXW ROT CMP DDMA AHLD MTM */
+#define DMAC_DEVCON2 0x0210 /* RW ---- ---- ---- ---- ---- ---- WEV BHLD */
+#define DMAC_MODECON 0x0014 /* RW **TMODE** ADIR AUTI **TDIR*** ---- WORD */
+#define DMAC_STATUS 0x0214 /* RO RQ3 RQ2 RQ1 RQ0 TC3 TC2 TC1 TC0 */
+#if 0
+templo = dmac + 0x0018;/* RO T7 T6 T5 T4 T3 T2 T1 T0 */
+temphi = dmac + 0x0218;/* RO T15 T14 T13 T12 T11 T10 T9 T8 */
+#endif
+#define DMAC_REQREG 0x001C /* RW ---- ---- ---- ---- SRQ3 SRQ2 SRQ1 SRQ0 */
+#define DMAC_MASKREG 0x021C /* RW ---- ---- ---- ---- M3 M2 M1 M0 */
+
+#ifndef _LOCORE
+#define WriteSBIC(a, d) \
+ WriteByte(sbic_base + SBIC_ADDRREG, a); \
+ WriteByte(sbic_base + SBIC_DATAREG, d);
+
+/*
+#define ReadSBIC(a) \
+ (WriteByte(sbic_base, a), ReadWord(sbic_base + 4) & 0xff)
+*/
+#define ReadSBIC(a) \
+ ReadSBIC1(sbic_base, a)
+
+
+static inline int
+ReadSBIC1(sbic_base, a)
+ u_int sbic_base;
+ int a;
+{
+ WriteByte(sbic_base + SBIC_ADDRREG, a);
+ return(ReadByte(sbic_base + SBIC_DATAREG));
+}
+
+
+#define WriteDMAC(a, d) WriteByte(dmac_base + a, d)
+#define ReadDMAC(a) ReadByte(dmac_base + a)
+#endif
+
+
+#endif
+#endif /* _ASCREG_H_ */
--- /dev/null
+/* $NetBSD: ascvar.h,v 1.1 1996/03/07 23:54:31 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASCVAR_H_
+#define _ASCVAR_H_
+
+#include <arm32/podulebus/sbicvar.h>
+#include <arm32/podulebus/ascreg.h>
+
+#define ASC_POLL 1
+
+struct asc_softc {
+ struct sbic_softc sc_softc;
+
+ podule_t *sc_podule;
+ int sc_podule_number;
+ irqhandler_t sc_ih;
+
+ vu_int sc_pagereg;
+ vu_int sc_intstat;
+ };
+
+#endif /* _ASCVAR_H_ */
--- /dev/null
+/* $NetBSD: if_ea.c,v 1.4 1996/03/27 21:49:26 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * if_ea.c
+ *
+ * Ether3 device driver
+ *
+ * Created : 08/07/95
+ */
+
+/*
+ * SEEQ 8005 device driver
+ */
+
+/*
+ * Bugs/possible improvements:
+ * - Does not currently support DMA
+ * - Does not currently support multicasts
+ * - Does not transmit multiple packets in one go
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+
+#include <arm32/podulebus/if_eareg.h>
+#include <arm32/podulebus/podulebus.h>
+
+#define ETHER_MIN_LEN 64
+#define ETHER_MAX_LEN 1514
+#define ETHER_ADDR_LEN 6
+
+#ifndef EA_TIMEOUT
+#define EA_TIMEOUT 60
+#endif
+
+/*#define EA_TX_DEBUG*/
+/*#define EA_RX_DEBUG*/
+/*#define EA_DEBUG*/
+/*#define EA_PACKET_DEBUG*/
+
+/* for debugging convenience */
+#ifdef EA_DEBUG
+#define dprintf(x) printf x
+#else
+#define dprintf(x)
+#endif
+
+#define MY_MANUFACTURER 0x11
+#define MY_PODULE 0xa4
+
+/*
+ * per-line info and status
+ */
+
+struct ea_softc {
+ struct device sc_dev;
+ irqhandler_t sc_ih;
+ int sc_irq; /* IRQ number */
+ podule_t *sc_podule; /* Our podule */
+ int sc_podule_number; /* Our podule number */
+ u_int sc_iobase; /* base I/O addr */
+ struct arpcom sc_arpcom; /* ethernet common */
+ char sc_pktbuf[EA_BUFSIZ]; /* frame buffer */
+ int sc_config1; /* Current config1 bits */
+ int sc_config2; /* Current config2 bits */
+ int sc_command; /* Current command bits */
+ int sc_irqclaimed; /* Whether we have an IRQ claimed */
+ int sc_rx_ptr; /* Receive buffer pointer */
+ int sc_tx_ptr; /* Transmit buffer pointer */
+};
+
+/*
+ * prototypes
+ */
+
+static int eaintr __P((void *));
+static int ea_init __P((struct ea_softc *));
+static int ea_ioctl __P((struct ifnet *, u_long, caddr_t));
+static void ea_start __P((struct ifnet *));
+static void ea_watchdog __P((int));
+static void ea_reinit __P((struct ea_softc *));
+static void ea_chipreset __P((struct ea_softc *));
+static void ea_ramtest __P((struct ea_softc *));
+static int ea_stoptx __P((struct ea_softc *));
+static int ea_stoprx __P((struct ea_softc *));
+static void ea_stop __P((struct ea_softc *));
+static void ea_writebuf __P((struct ea_softc *, u_char *, int, int));
+static void ea_readbuf __P((struct ea_softc *, u_char *, int, int));
+static void earead __P((struct ea_softc *, caddr_t, int));
+static struct mbuf *eaget __P((caddr_t, int, struct ifnet *));
+static void ea_hardreset __P((struct ea_softc *));
+static void eagetpackets __P((struct ea_softc *));
+static void eatxpacket __P((struct ea_softc *));
+
+int eaprobe __P((struct device *, void *, void *));
+void eaattach __P((struct device *, struct device *, void *));
+
+/* driver structure for autoconf */
+
+struct cfattach ea_ca = {
+ sizeof(struct ea_softc), eaprobe, eaattach
+};
+
+struct cfdriver ea_cd = {
+ NULL, "ea", DV_IFNET
+};
+
+#if 0
+
+/*
+ * Dump the chip registers
+ */
+
+void
+eadump(iobase)
+ u_int iobase;
+{
+ dprintf(("%08x: %04x %04x %04x %04x %04x %04x %04x %04x\n", iobase,
+ ReadShort(iobase + 0x00), ReadShort(iobase + 0x40),
+ ReadShort(iobase + 0x80), ReadShort(iobase + 0xc0),
+ ReadShort(iobase + 0x100), ReadShort(iobase + 0x140),
+ ReadShort(iobase + 0x180), ReadShort(iobase + 0x1c0)));
+}
+#endif
+
+/*
+ * Dump the interface buffer
+ */
+
+void
+ea_dump_buffer(sc, offset)
+ struct ea_softc *sc;
+ int offset;
+{
+#ifdef EA_PACKET_DEBUG
+ u_int iobase = sc->sc_iobase;
+ int addr;
+ int loop;
+ int size;
+ int ctrl;
+ int ptr;
+
+ addr = offset;
+
+ do {
+ WriteShort(sc->sc_iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_READ);
+ WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_LOCAL_MEM);
+ WriteShort(iobase + EA_8005_DMA_ADDR, addr);
+
+ ptr = ReadShort(iobase + EA_8005_BUFWIN);
+ ctrl = ReadShort(iobase + EA_8005_BUFWIN);
+ ptr = ((ptr & 0xff) << 8) | ((ptr >> 8) & 0xff);
+
+ if (ptr == 0) break;
+ size = ptr - addr;
+
+ printf("addr=%04x size=%04x ", addr, size);
+ printf("cmd=%02x st=%02x\n", ctrl & 0xff, ctrl >> 8);
+
+ for (loop = 0; loop < size - 4; loop += 2)
+ printf("%04x ", ReadShort(iobase + EA_8005_BUFWIN));
+ printf("\n");
+ addr = ptr;
+ } while (size != 0);
+#endif
+}
+
+/*
+ * Probe routine.
+ */
+
+/*
+ * int eaprobe(struct device *parent, void *match, void *aux)
+ *
+ * Probe for the ether3 podule.
+ */
+
+int
+eaprobe(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ struct podule_attach_args *pa = (void *)aux;
+ int podule;
+ u_int iobase;
+
+/* dprintf(("Probing for SEEQ 8005... \n"));*/
+
+/* Look for a network slot interface */
+
+ podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+/* Fail if we did not find it */
+
+ if (podule == -1)
+ return(0);
+
+ iobase = podules[podule].mod_base + EA_8005_BASE;
+
+/* Reset it - Why here ? */
+
+ WriteShort(iobase + EA_8005_CONFIG2, EA_CFG2_RESET);
+ delay(100);
+
+/* We found it */
+
+ pa->pa_podule_number = podule;
+ pa->pa_podule = &podules[podule];
+
+ return(1);
+}
+
+
+/*
+ * void eaattach(struct device *parent, struct device *dev, void *aux)
+ *
+ * Attach podule.
+ */
+
+void
+eaattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct ea_softc *sc = (void *)self;
+ struct podule_attach_args *pa = (void *)aux;
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ int loop;
+ int sum;
+
+/* dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));*/
+
+/* Note the podule number and validate */
+
+ sc->sc_podule_number = pa->pa_podule_number;
+ if (sc->sc_podule_number == -1)
+ panic("Podule has disappeared !");
+
+ sc->sc_podule = &podules[sc->sc_podule_number];
+ podules[sc->sc_podule_number].attached = 1;
+
+/* Set the address of the controller for easy access */
+
+ sc->sc_iobase = sc->sc_podule->mod_base + EA_8005_BASE;
+
+ sc->sc_irqclaimed = 0;
+
+/* Set up the interrupt structure */
+
+ sc->sc_ih.ih_func = eaintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_NET;
+ sc->sc_ih.ih_name = "net: ea";
+
+/* Claim either a network slot interrupt or a podule interrupt */
+
+ if (sc->sc_podule_number >= MAX_PODULES)
+ sc->sc_irq = IRQ_NETSLOT;
+ else
+ sc->sc_irq = IRQ_PODULE /*+ sc->sc_podule_number*/;
+
+ /* Stop the board. */
+
+ ea_chipreset(sc);
+ ea_stoptx(sc);
+ ea_stoprx(sc);
+
+ /* Initialise ifnet structure. */
+
+ ifp->if_unit = sc->sc_dev.dv_unit;
+ ifp->if_name = ea_cd.cd_name;
+ ifp->if_start = ea_start;
+ ifp->if_ioctl = ea_ioctl;
+ ifp->if_watchdog = ea_watchdog;
+ ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
+
+ /* Now we can attach the interface. */
+
+/* dprintf(("Attaching interface...\n"));*/
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+/* Read the station address - the receiver must be off */
+
+ WriteShort(sc->sc_iobase + EA_8005_CONFIG1, EA_BUFCODE_STATION_ADDR0);
+
+ for (sum = 0, loop = 0; loop < ETHER_ADDR_LEN; ++loop) {
+ sc->sc_arpcom.ac_enaddr[loop] =
+ ReadByte(sc->sc_iobase + EA_8005_BUFWIN);
+ sum += sc->sc_arpcom.ac_enaddr[loop];
+ }
+
+/*
+ * Hard code the ether address if we don't have one.
+ * Need to work out how I get the real address
+ */
+
+ if (sum == 0) {
+ sc->sc_arpcom.ac_enaddr[0] = 0x00;
+ sc->sc_arpcom.ac_enaddr[1] = 0x00;
+ sc->sc_arpcom.ac_enaddr[2] = 0xa4;
+ sc->sc_arpcom.ac_enaddr[3] = 0x10;
+ sc->sc_arpcom.ac_enaddr[4] = 0x02;
+ sc->sc_arpcom.ac_enaddr[5] = 0x87;
+ }
+
+ /* Print out some information for the user. */
+
+ printf(" SEEQ8005 address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));
+
+ /* Finally, attach to bpf filter if it is present. */
+
+#if NBPFILTER > 0
+/* dprintf(("Attaching to BPF...\n"));*/
+ bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+
+ /* Should test the RAM */
+
+ ea_ramtest(sc);
+
+/* dprintf(("eaattach() finished.\n"));*/
+}
+
+
+/*
+ * Test the RAM on the ethernet card. This does not work yet
+ */
+
+void
+ea_ramtest(sc)
+ struct ea_softc *sc;
+{
+ register u_int iobase = sc->sc_iobase;
+ register int loop;
+ register u_int sum = 0;
+
+/* dprintf(("ea_ramtest()\n"));*/
+
+ /*
+ * Test the buffer memory on the board.
+ * Write simple pattens to it and read them back.
+ */
+
+ /* Set up the whole buffer RAM for writing */
+
+ WriteShort(iobase + EA_8005_CONFIG1, EA_BUFCODE_TX_EAP);
+ WriteShort(iobase + EA_8005_BUFWIN, ((EA_BUFFER_SIZE >> 8) - 1));
+ WriteShort(iobase + EA_8005_TX_PTR, 0x0000);
+ WriteShort(iobase + EA_8005_RX_PTR, EA_BUFFER_SIZE - 2);
+
+ /* Set the write start address and write a pattern */
+
+ ea_writebuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+ WriteShort(iobase + EA_8005_BUFWIN, loop);
+
+ /* Set the read start address and verify the pattern */
+
+ ea_readbuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+ if (ReadShort(iobase + EA_8005_BUFWIN) != loop)
+ ++sum;
+
+ if (sum != 0)
+ dprintf(("sum=%d\n", sum));
+
+ /* Set the write start address and write a pattern */
+
+ ea_writebuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+ WriteShort(iobase + EA_8005_BUFWIN, loop ^ (EA_BUFFER_SIZE - 1));
+
+ /* Set the read start address and verify the pattern */
+
+ ea_readbuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+ if (ReadShort(iobase + EA_8005_BUFWIN) != (loop ^ (EA_BUFFER_SIZE - 1)))
+ ++sum;
+
+ if (sum != 0)
+ dprintf(("sum=%d\n", sum));
+
+ /* Set the write start address and write a pattern */
+
+ ea_writebuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+ WriteShort(iobase + EA_8005_BUFWIN, 0xaa55);
+
+ /* Set the read start address and verify the pattern */
+
+ ea_readbuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+ if (ReadShort(iobase + EA_8005_BUFWIN) != 0xaa55)
+ ++sum;
+
+ if (sum != 0)
+ dprintf(("sum=%d\n", sum));
+
+ /* Set the write start address and write a pattern */
+
+ ea_writebuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+ WriteShort(iobase + EA_8005_BUFWIN, 0x55aa);
+
+ /* Set the read start address and verify the pattern */
+
+ ea_readbuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2)
+ if (ReadShort(iobase + EA_8005_BUFWIN) != 0x55aa)
+ ++sum;
+
+ if (sum != 0)
+ dprintf(("sum=%d\n", sum));
+
+ /* Report */
+
+ if (sum == 0)
+ printf(" %dK buffer RAM\n", EA_BUFFER_SIZE / 1024);
+ else
+ printf(" buffer RAM failed self test, %d faults\n", sum);
+}
+
+
+/* Claim an irq for the board */
+
+void
+ea_claimirq(sc)
+ struct ea_softc *sc;
+{
+/* Have we claimed one already ? */
+
+ if (sc->sc_irqclaimed) return;
+
+/* Claim it */
+
+ dprintf(("ea_claimirq(%d)\n", sc->sc_irq));
+ if (irq_claim(sc->sc_irq, &sc->sc_ih))
+ panic("Cannot install IRQ handler for IRQ %d\n", sc->sc_irq);
+
+ sc->sc_irqclaimed = 1;
+}
+
+
+/* Release an irq */
+
+void
+ea_releaseirq(sc)
+ struct ea_softc *sc;
+{
+/* Have we claimed one ? */
+
+ if (!sc->sc_irqclaimed) return;
+
+ dprintf(("ea_releaseirq(%d)\n", sc->sc_irq));
+ if (irq_release(sc->sc_irq, &sc->sc_ih))
+ panic("Cannot release IRQ handler for IRQ %d\n", sc->sc_irq);
+
+ sc->sc_irqclaimed = 0;
+}
+
+
+/*
+ * Stop and reinitialise the interface.
+ */
+
+static void
+ea_reinit(sc)
+ struct ea_softc *sc;
+{
+ int s;
+
+ dprintf(("eareinit()\n"));
+
+/* Stop and reinitialise the interface */
+
+ s = splimp();
+ ea_stop(sc);
+ ea_init(sc);
+ (void)splx(s);
+}
+
+
+/*
+ * Stop the tx interface.
+ *
+ * Returns 0 if the tx was already stopped or 1 if it was active
+ */
+
+static int
+ea_stoptx(sc)
+ struct ea_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ int timeout;
+ int status;
+
+ dprintf(("ea_stoptx()\n"));
+
+ status = ReadShort(iobase + EA_8005_STATUS);
+ if (!(status & EA_STATUS_TX_ON))
+ return(0);
+
+/* Stop any tx and wait for confirmation */
+
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_TX_OFF);
+
+ timeout = 20000;
+ do {
+ status = ReadShort(iobase + EA_8005_STATUS);
+ } while ((status & EA_STATUS_TX_ON) && --timeout > 0);
+ if (timeout == 0)
+ dprintf(("ea_stoptx: timeout waiting for tx termination\n"));
+
+/* Clear any pending tx interrupt */
+
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_TX_INTACK);
+ return(1);
+}
+
+
+/*
+ * Stop the rx interface.
+ *
+ * Returns 0 if the tx was already stopped or 1 if it was active
+ */
+
+static int
+ea_stoprx(sc)
+ struct ea_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ int timeout;
+ int status;
+
+ dprintf(("ea_stoprx()\n"));
+
+ status = ReadShort(iobase + EA_8005_STATUS);
+ if (!(status & EA_STATUS_RX_ON))
+ return(0);
+
+/* Stop any rx and wait for confirmation */
+
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_RX_OFF);
+
+ timeout = 20000;
+ do {
+ status = ReadShort(iobase + EA_8005_STATUS);
+ } while ((status & EA_STATUS_RX_ON) && --timeout > 0);
+ if (timeout == 0)
+ dprintf(("ea_stoprx: timeout waiting for rx termination\n"));
+
+/* Clear any pending rx interrupt */
+
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_RX_INTACK);
+ return(1);
+}
+
+
+/*
+ * Stop interface.
+ * Stop all IO and shut the interface down
+ */
+
+static void
+ea_stop(sc)
+ struct ea_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+
+ dprintf(("ea_stop()\n"));
+
+/* Stop all IO */
+
+ ea_stoptx(sc);
+ ea_stoprx(sc);
+
+/* Disable rx and tx interrupts */
+
+ sc->sc_command &= (EA_CMD_RX_INTEN | EA_CMD_TX_INTEN);
+
+/* Clear any pending interrupts */
+
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+ | EA_CMD_RX_INTACK | EA_CMD_TX_INTACK | EA_CMD_DMA_INTACK
+ | EA_CMD_BW_INTACK);
+ dprintf(("st=%08x", ReadShort(iobase + EA_8005_STATUS)));
+
+/* Release the irq */
+
+ ea_releaseirq(sc);
+
+ /* Cancel any watchdog timer */
+
+ sc->sc_arpcom.ac_if.if_timer = 0;
+}
+
+
+/*
+ * Reset the chip
+ * Following this the software registers are reset
+ */
+
+static void
+ea_chipreset(sc)
+ struct ea_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+
+ dprintf(("ea_chipreset()\n"));
+
+/* Reset the controller. Min of 4us delay here */
+
+ WriteShort(iobase + EA_8005_CONFIG2, EA_CFG2_RESET);
+ delay(100);
+
+ sc->sc_command = 0;
+ sc->sc_config1 = 0;
+ sc->sc_config2 = 0;
+}
+
+
+/*
+ * Do a hardware reset of the board, and upload the ethernet address again in
+ * case the board forgets.
+ */
+
+static void
+ea_hardreset(sc)
+ struct ea_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ int loop;
+
+ dprintf(("ea_hardreset()\n"));
+
+/* Stop any activity */
+
+ ea_stoptx(sc);
+ ea_stoprx(sc);
+
+ ea_chipreset(sc);
+
+/* Set up defaults for the registers */
+
+ sc->sc_config2 = 0;
+ WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+ sc->sc_command = 0x00;
+ sc->sc_config1 = EA_CFG1_STATION_ADDR0 | EA_CFG1_DMA_BSIZE_1 | EA_CFG1_DMA_BURST_CONT;
+ WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1);
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command);
+
+ WriteShort(iobase + EA_8005_CONFIG1, EA_BUFCODE_TX_EAP);
+ WriteShort(iobase + EA_8005_BUFWIN, ((EA_TX_BUFFER_SIZE >> 8) - 1));
+
+/* Write the station address - the receiver must be off */
+
+ WriteShort(sc->sc_iobase + EA_8005_CONFIG1,
+ sc->sc_config1 | EA_BUFCODE_STATION_ADDR0);
+ for (loop = 0; loop < ETHER_ADDR_LEN; ++loop) {
+ WriteByte(sc->sc_iobase + EA_8005_BUFWIN, sc->sc_arpcom.ac_enaddr[loop]);
+ }
+}
+
+
+/*
+ * write to the buffer memory on the interface
+ *
+ * If addr is within range for the interface buffer then the buffer
+ * address is set to addr.
+ * If len != 0 then data is copied from the address starting at buf
+ * to the interface buffer.
+ */
+
+static void
+ea_writebuf(sc, buf, addr, len)
+ struct ea_softc *sc;
+ u_char *buf;
+ int addr;
+ int len;
+{
+ u_int iobase = sc->sc_iobase;
+ int loop;
+ int timeout;
+
+ dprintf(("writebuf: st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));
+
+/* If we have a valid buffer address set the buffer pointer and direction */
+
+ if (addr >= 0 && addr < EA_BUFFER_SIZE) {
+ WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_LOCAL_MEM);
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_WRITE);
+
+ /* Should wait here of FIFO empty flag */
+
+ timeout = 20000;
+ while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+
+
+ WriteShort(iobase + EA_8005_DMA_ADDR, addr);
+ }
+
+ for (loop = 0; loop < len; loop += 2)
+ WriteShort(iobase + EA_8005_BUFWIN, buf[loop] | buf[loop + 1] << 8);
+
+/* if (len > 0)
+ outsw(iobase + EA_8005_BUFWIN, buf, len / 2);*/
+}
+
+
+/*
+ * read from the buffer memory on the interface
+ *
+ * If addr is within range for the interface buffer then the buffer
+ * address is set to addr.
+ * If len != 0 then data is copied from the interface buffer to the
+ * address starting at buf.
+ */
+
+static void
+ea_readbuf(sc, buf, addr, len)
+ struct ea_softc *sc;
+ u_char *buf;
+ int addr;
+ int len;
+{
+ u_int iobase = sc->sc_iobase;
+ int loop;
+ int word;
+ int timeout;
+
+ dprintf(("readbuf: st=%04x addr=%04x len=%d\n", ReadShort(iobase + EA_8005_STATUS), addr, len));
+
+/* If we have a valid buffer address set the buffer pointer and direction */
+
+ if (addr >= 0 && addr < EA_BUFFER_SIZE) {
+ if ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_DIR) == 0) {
+ /* Should wait here of FIFO empty flag */
+
+ timeout = 20000;
+ while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+ }
+ WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_LOCAL_MEM);
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_WRITE);
+
+ /* Should wait here of FIFO empty flag */
+
+ timeout = 20000;
+ while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+
+ WriteShort(iobase + EA_8005_DMA_ADDR, addr);
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_READ);
+
+ /* Should wait here of FIFO full flag */
+
+ timeout = 20000;
+ while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_FULL) == 0 && --timeout > 0);
+
+
+ }
+
+ for (loop = 0; loop < len; loop += 2) {
+ word = ReadShort(iobase + EA_8005_BUFWIN);
+ buf[loop] = word & 0xff;
+ buf[loop + 1] = word >> 8;
+ }
+}
+
+
+/*
+ * Initialize interface.
+ *
+ * This should leave the interface in a state for packet reception and transmission
+ */
+
+static int
+ea_init(sc)
+ struct ea_softc *sc;
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ u_int iobase = sc->sc_iobase;
+ int s;
+
+ dprintf(("ea_init()\n"));
+
+ s = splimp();
+
+/* Grab an irq */
+
+ ea_claimirq(sc);
+
+ /* First, reset the board. */
+
+ ea_hardreset(sc);
+
+/* Configure rx. */
+
+ dprintf(("Configuring rx...\n"));
+ if (ifp->if_flags & IFF_PROMISC)
+ sc->sc_config1 = EA_CFG1_PROMISCUOUS;
+ else
+ sc->sc_config1 = EA_CFG1_BROADCAST;
+
+ sc->sc_config1 |= EA_CFG1_DMA_BSIZE_8 | EA_CFG1_STATION_ADDR0 | EA_CFG1_DMA_BURST_CONT;
+ WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1);
+
+/* Configure TX. */
+
+ dprintf(("Configuring tx...\n"));
+
+ WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_TX_EAP);
+ WriteShort(iobase + EA_8005_BUFWIN, ((EA_TX_BUFFER_SIZE >> 8) - 1));
+ WriteShort(iobase + EA_8005_TX_PTR, 0x0000);
+
+ sc->sc_config2 |= EA_CFG2_OUTPUT;
+ WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+
+/* Place a NULL header at the beginning of the transmit area */
+
+ ea_writebuf(sc, NULL, 0x0000, 0);
+
+ WriteShort(iobase + EA_8005_BUFWIN, 0x0000);
+ WriteShort(iobase + EA_8005_BUFWIN, 0x0000);
+
+ sc->sc_command |= EA_CMD_TX_INTEN;
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command);
+
+/* Setup the Rx pointers */
+
+ sc->sc_rx_ptr = EA_TX_BUFFER_SIZE;
+
+ WriteShort(iobase + EA_8005_RX_PTR, sc->sc_rx_ptr);
+ WriteShort(iobase + EA_8005_RX_END, (sc->sc_rx_ptr >> 8));
+
+/* Place a NULL header at the beginning of the receive area */
+
+ ea_writebuf(sc, NULL, sc->sc_rx_ptr, 0);
+
+ WriteShort(iobase + EA_8005_BUFWIN, 0x0000);
+ WriteShort(iobase + EA_8005_BUFWIN, 0x0000);
+
+/* Turn on Rx */
+
+ sc->sc_command |= EA_CMD_RX_INTEN;
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_RX_ON);
+
+ /* Set flags appropriately. */
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ dprintf(("init: st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));
+
+ /* And start output. */
+ ea_start(ifp);
+
+ (void)splx(s);
+ return(0);
+}
+
+
+/*
+ * Start output on interface. Get datagrams from the queue and output them,
+ * giving the receiver a chance between datagrams. Call only from splimp or
+ * interrupt level!
+ */
+
+static void
+ea_start(ifp)
+ struct ifnet *ifp;
+{
+ struct ea_softc *sc = ea_cd.cd_devs[ifp->if_unit];
+ int s;
+
+ s = splimp();
+#ifdef EA_TX_DEBUG
+ dprintf(("ea_start()...\n"));
+#endif
+
+ /* Don't do anything if output is active. */
+
+ if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE)
+ return;
+
+ /* Mark interface as output active */
+
+ sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
+
+ /* tx packets */
+
+ eatxpacket(sc);
+ (void)splx(s);
+}
+
+
+/*
+ * Transfer a packet to the interface buffer and start transmission
+ *
+ * Called at splimp()
+ */
+
+void
+eatxpacket(sc)
+ struct ea_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ struct mbuf *m, *m0;
+ int len;
+
+/* Dequeue the next datagram. */
+
+ IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
+
+/* If there's nothing to send, return. */
+
+ if (!m0) {
+ sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+ sc->sc_config2 |= EA_CFG2_OUTPUT;
+ WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+#ifdef EA_TX_DEBUG
+ dprintf(("tx finished\n"));
+#endif
+ return;
+ }
+
+ /* Give the packet to the bpf, if any. */
+#if NBPFILTER > 0
+ if (sc->sc_arpcom.ac_if.if_bpf)
+ bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
+#endif
+
+#ifdef EA_TX_DEBUG
+ dprintf(("Tx new packet\n"));
+#endif
+
+/*
+ * Copy the datagram to the temporary buffer.
+ *
+ * Eventually we may as well just copy straight into the interface buffer
+ */
+
+ len = 0;
+ for (m = m0; m; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ bcopy(mtod(m, caddr_t), sc->sc_pktbuf + len, m->m_len);
+ len += m->m_len;
+ }
+ m_freem(m0);
+
+/* If packet size is odd round up to the next 16 bit boundry */
+
+ if (len % 2)
+ ++len;
+
+ len = max(len, ETHER_MIN_LEN);
+
+ if (len > ETHER_MAX_LEN)
+ log(LOG_WARNING, "ea: oversize packet = %d bytes\n", len);
+
+/* Ok we now have a packet len bytes long in our packet buffer */
+
+/* Transfer datagram to board. */
+
+#ifdef EA_TX_DEBUG
+ dprintf(("ea: xfr pkt length=%d...\n", len));
+
+ dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
+ dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
+#endif
+
+ sc->sc_config2 &= ~EA_CFG2_OUTPUT;
+ WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+
+/* dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));*/
+
+/* Write the packet to the interface buffer, skipping the packet header */
+
+ ea_writebuf(sc, sc->sc_pktbuf, 0x0004, len);
+
+/* Follow it with a NULL packet header */
+
+ WriteShort(iobase + EA_8005_BUFWIN, 0x00);
+ WriteShort(iobase + EA_8005_BUFWIN, 0x00);
+
+/* Write the packet header */
+
+ ea_writebuf(sc, NULL, 0x0000, 0);
+
+ WriteShort(iobase + EA_8005_BUFWIN, (((len+4) & 0xff00) >> 8) | (((len+4) & 0xff) << 8));
+ WriteShort(iobase + EA_8005_BUFWIN, 0x00aa);
+
+ WriteShort(iobase + EA_8005_TX_PTR, 0x0000);
+
+/* dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));*/
+
+#ifdef EA_DEBUG
+ ea_dump_buffer(sc, 0);
+#endif
+
+/* Now transmit the datagram. */
+
+/* dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));*/
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_TX_ON);
+#ifdef EA_TX_DEBUG
+ dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));
+ dprintf(("tx: queued\n"));
+#endif
+}
+
+
+/*
+ * Ethernet controller interrupt.
+ */
+
+int
+eaintr(arg)
+ void *arg;
+{
+ register struct ea_softc *sc = arg;
+ u_int iobase = sc->sc_iobase;
+ int status, s;
+ u_int txstatus;
+
+ dprintf(("eaintr: "));
+
+/* Get the controller status */
+
+ status = ReadShort(iobase + EA_8005_STATUS);
+ dprintf(("st=%04x ", status));
+
+/* Tx interrupt ? */
+
+ if (status & EA_STATUS_TX_INT) {
+ dprintf(("txint "));
+
+/* Acknowledge the interrupt */
+
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+ | EA_CMD_TX_INTACK);
+
+ ea_readbuf(sc, (u_char *)&txstatus, 0x0000, 4);
+
+#ifdef EA_TX_DEBUG
+ dprintf(("txstatus=%08x\n", txstatus));
+#endif
+ txstatus = (txstatus >> 24) & 0xff;
+
+/*
+ * Did it succeed ? Did we collide ?
+ *
+ * The exact proceedure here is not clear. We should get
+ * an interrupt on a sucessfull tx or on a collision.
+ * The done flag is set after successfull tx or 16 collisions
+ * We should thus get a interrupt for each of collision
+ * and the done bit should not be set. However it does appear
+ * to be set at the same time as the collision bit ...
+ *
+ * So we will count collisions and output errors and will assume
+ * that if the done bit is set the packet was transmitted.
+ * Stats may be wrong if 16 collisions occur on a packet
+ * as the done flag should be set but the packet may not have been
+ * transmitted. so the output count might not require incrementing
+ * if the 16 collisions flags is set. I don;t know abou this until
+ * it happens.
+ */
+
+ if (txstatus & EA_TXHDR_COLLISION) {
+ sc->sc_arpcom.ac_if.if_collisions++;
+ } else if (txstatus & EA_TXHDR_ERROR_MASK) {
+ sc->sc_arpcom.ac_if.if_oerrors++;
+ }
+
+/* if (txstatus & EA_TXHDR_ERROR_MASK) {
+ log(LOG_WARNING, "tx packet error =%02x\n", txstatus);
+ }*/
+
+ if (txstatus & EA_PKTHDR_DONE) {
+ sc->sc_arpcom.ac_if.if_opackets++;
+
+ /* Tx next packet */
+
+ s = splimp();
+ eatxpacket(sc);
+ (void)splx(s);
+ }
+ }
+
+/* Rx interrupt ? */
+
+ if (status & EA_STATUS_RX_INT) {
+ dprintf(("rxint "));
+
+/* Acknowledge the interrupt */
+
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+ | EA_CMD_RX_INTACK);
+
+/* Install a watchdog timer needed atm to fixed rx lockups */
+
+ sc->sc_arpcom.ac_if.if_timer = EA_TIMEOUT;
+
+/* Processes the received packets */
+ eagetpackets(sc);
+
+/* Make sure the receiver is on */
+
+/* if ((status & EA_STATUS_RX_ON) == 0) {
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+ | EA_CMD_RX_ON);
+ printf("rxintr: rx is off st=%04x\n",status);
+ }*/
+ }
+
+#ifdef EA_DEBUG
+ status = ReadShort(iobase + EA_8005_STATUS);
+ dprintf(("st=%04x\n", status));
+#endif
+ return(0);
+}
+
+void
+eagetpackets(sc)
+ struct ea_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ int addr;
+ int len;
+ int ctrl;
+ int ptr;
+ int pack;
+ int status;
+ u_int rxstatus;
+
+/* We start from the last rx pointer position */
+
+ addr = sc->sc_rx_ptr;
+ sc->sc_config2 &= ~EA_CFG2_OUTPUT;
+ WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+
+ do {
+/* Read rx header */
+
+ ea_readbuf(sc, (u_char *)&rxstatus, addr, 4);
+
+/* Split the packet header */
+
+ ptr = ((rxstatus & 0xff) << 8) | ((rxstatus >> 8) & 0xff);
+ ctrl = (rxstatus >> 16) & 0xff;
+ status = (rxstatus >> 24) & 0xff;
+
+#ifdef EA_RX_DEBUG
+ dprintf(("addr=%04x ptr=%04x ctrl=%02x status=%02x\n", addr, ptr, ctrl, status));
+#endif
+
+/* Zero packet ptr ? then must be null header so exit */
+
+ if (ptr == 0) break;
+
+/* Get packet length */
+
+ len = (ptr - addr) - 4;
+
+ if (len < 0) {
+ len += EA_RX_BUFFER_SIZE;
+ }
+
+#ifdef EA_RX_DEBUG
+ dprintf(("len=%04x\n", len));
+#endif
+
+/* Has the packet rx completed ? if not then exit */
+
+ if ((status & EA_PKTHDR_DONE) == 0)
+ break;
+
+/* Did we have any errors ? then note error and go to next packet */
+
+ if (status & 0x0f) {
+ ++sc->sc_arpcom.ac_if.if_ierrors;
+ printf("rx packet error (%02x) - dropping packet\n", status & 0x0f);
+/* sc->sc_config2 |= EA_CFG2_OUTPUT;
+ WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+ ea_reinit(sc);
+ return; */
+ addr = ptr;
+ continue;
+ }
+
+/* Is the packet too big ? - this will probably be trapped above as a receive error */
+
+ if (len > ETHER_MAX_LEN) {
+ ++sc->sc_arpcom.ac_if.if_ierrors;
+ printf("rx packet size error len=%d\n", len);
+/* sc->sc_config2 |= EA_CFG2_OUTPUT;
+ WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+ ea_reinit(sc);
+ return;*/
+ addr = ptr;
+ continue;
+ }
+
+ ea_readbuf(sc, sc->sc_pktbuf, addr + 4, len);
+
+#ifdef EA_RX_DEBUG
+ dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
+ dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
+#endif
+ sc->sc_arpcom.ac_if.if_ipackets++;
+ /* Pass data up to upper levels. */
+ earead(sc, (caddr_t)sc->sc_pktbuf, len);
+
+ addr = ptr;
+ ++pack;
+ } while (len != 0);
+
+ sc->sc_config2 |= EA_CFG2_OUTPUT;
+ WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2);
+
+#ifdef EA_RX_DEBUG
+ dprintf(("new rx ptr=%04x\n", addr));
+#endif
+
+/* Store new rx pointer */
+
+ sc->sc_rx_ptr = addr;
+ WriteShort(iobase + EA_8005_RX_END, (sc->sc_rx_ptr >> 8));
+
+/* Make sure the receiver is on */
+
+ WriteShort(iobase + EA_8005_COMMAND, sc->sc_command
+ | EA_CMD_RX_ON);
+
+}
+
+
+/*
+ * Pass a packet up to the higher levels.
+ */
+
+static void
+earead(sc, buf, len)
+ struct ea_softc *sc;
+ caddr_t buf;
+ int len;
+{
+ register struct ether_header *eh;
+ struct mbuf *m;
+
+ eh = (struct ether_header *)buf;
+ len -= sizeof(struct ether_header);
+ if (len <= 0)
+ return;
+
+ /* Pull packet off interface. */
+ m = eaget(buf, len, &sc->sc_arpcom.ac_if);
+ if (m == 0)
+ return;
+
+#if NBPFILTER > 0
+ /*
+ * Check if there's a BPF listener on this interface.
+ * If so, hand off the raw packet to bpf.
+ */
+ if (sc->sc_arpcom.ac_if.if_bpf) {
+ bpf_tap(sc->sc_arpcom.ac_if.if_bpf, buf, len + sizeof(struct ether_header));
+/* bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);*/
+
+ /*
+ * Note that the interface cannot be in promiscuous mode if
+ * there are no BPF listeners. And if we are in promiscuous
+ * mode, we have to check if this packet is really ours.
+ */
+ if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
+ (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
+ bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
+ sizeof(eh->ether_dhost)) != 0) {
+ m_freem(m);
+ return;
+ }
+ }
+#endif
+
+ ether_input(&sc->sc_arpcom.ac_if, eh, m);
+}
+
+/*
+ * Pull read data off a interface. Len is length of data, with local net
+ * header stripped. We copy the data into mbufs. When full cluster sized
+ * units are present we copy into clusters.
+ */
+
+struct mbuf *
+eaget(buf, totlen, ifp)
+ caddr_t buf;
+ int totlen;
+ struct ifnet *ifp;
+{
+ struct mbuf *top, **mp, *m;
+ int len;
+ register caddr_t cp = buf;
+ char *epkt;
+
+ buf += sizeof(struct ether_header);
+ cp = buf;
+ epkt = cp + totlen;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == 0)
+ return 0;
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = totlen;
+ m->m_len = MHLEN;
+ top = 0;
+ mp = ⊤
+
+ while (totlen > 0) {
+ if (top) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == 0) {
+ m_freem(top);
+ return 0;
+ }
+ m->m_len = MLEN;
+ }
+ len = min(totlen, epkt - cp);
+ if (len >= MINCLSIZE) {
+ MCLGET(m, M_DONTWAIT);
+ if (m->m_flags & M_EXT)
+ m->m_len = len = min(len, MCLBYTES);
+ else
+ len = m->m_len;
+ } else {
+ /*
+ * Place initial small packet/header at end of mbuf.
+ */
+ if (len < m->m_len) {
+ if (top == 0 && len + max_linkhdr <= m->m_len)
+ m->m_data += max_linkhdr;
+ m->m_len = len;
+ } else
+ len = m->m_len;
+ }
+ bcopy(cp, mtod(m, caddr_t), (unsigned)len);
+ cp += len;
+ *mp = m;
+ mp = &m->m_next;
+ totlen -= len;
+ if (cp == epkt)
+ cp = buf;
+ }
+
+ return top;
+}
+
+/*
+ * Process an ioctl request. This code needs some work - it looks pretty ugly.
+ */
+static int
+ea_ioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct ea_softc *sc = ea_cd.cd_devs[ifp->if_unit];
+ struct ifaddr *ifa = (struct ifaddr *)data;
+/* struct ifreq *ifr = (struct ifreq *)data;*/
+ int s, error = 0;
+
+ s = splimp();
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ dprintf(("if_flags=%08x\n", ifp->if_flags));
+
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ arp_ifinit(&sc->sc_arpcom, ifa);
+ dprintf(("Interface ea is coming up (AF_INET)\n"));
+ ea_init(sc);
+ break;
+#endif
+#ifdef NS
+ /* XXX - This code is probably wrong. */
+ case AF_NS:
+ {
+ register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+
+ if (ns_nullhost(*ina))
+ ina->x_host =
+ *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
+ else
+ bcopy(ina->x_host.c_host,
+ sc->sc_arpcom.ac_enaddr,
+ sizeof(sc->sc_arpcom.ac_enaddr));
+ /* Set new address. */
+ dprintf(("Interface ea is coming up (AF_NS)\n"));
+ ea_init(sc);
+ break;
+ }
+#endif
+ default:
+ dprintf(("Interface ea is coming up (default)\n"));
+ ea_init(sc);
+ break;
+ }
+ break;
+
+ case SIOCSIFFLAGS:
+ dprintf(("if_flags=%08x\n", ifp->if_flags));
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ (ifp->if_flags & IFF_RUNNING) != 0) {
+ /*
+ * If interface is marked down and it is running, then
+ * stop it.
+ */
+ dprintf(("Interface ea is stopping\n"));
+ ea_stop(sc);
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if ((ifp->if_flags & IFF_UP) != 0 &&
+ (ifp->if_flags & IFF_RUNNING) == 0) {
+ /*
+ * If interface is marked up and it is stopped, then
+ * start it.
+ */
+ dprintf(("Interface ea is restarting(1)\n"));
+ ea_init(sc);
+ } else {
+ /*
+ * Some other important flag might have changed, so
+ * reset.
+ */
+ dprintf(("Interface ea is reinitialising\n"));
+ ea_reinit(sc);
+ }
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ (void)splx(s);
+ return error;
+}
+
+/*
+ * Device timeout routine.
+ *
+ * Ok I am not sure exactly how the device timeout should work....
+ * Currently what will happens is that that the device timeout is only
+ * set when a packet it received. This indicates we are on an active
+ * network and thus we should expect more packets. If non arrive in
+ * in the timeout period then we reinitialise as we may have jammed.
+ * We zero the timeout at this point so that we don't end up with
+ * an endless stream of timeouts if the network goes down.
+ */
+
+static void
+ea_watchdog(unit)
+ int unit;
+{
+ struct ea_softc *sc = ea_cd.cd_devs[unit];
+
+ log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
+ sc->sc_arpcom.ac_if.if_oerrors++;
+ dprintf(("ea_watchdog: "));
+ dprintf(("st=%04x\n", ReadShort(sc->sc_iobase + EA_8005_STATUS)));
+
+ /* Kick the interface */
+
+ ea_reinit(sc);
+
+/* sc->sc_arpcom.ac_if.if_timer = EA_TIMEOUT;*/
+ sc->sc_arpcom.ac_if.if_timer = 0;
+}
+
+/* End of if_ea.c */
--- /dev/null
+/* $NetBSD: if_eareg.h,v 1.2 1996/03/18 21:23:09 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * if_eareg.h
+ *
+ * Ether3 device driver
+ *
+ * Created : 08/07/95
+ */
+
+/*
+ * SEEQ 8005 Register Definitions
+ */
+
+#define EA_8005_BASE 0x000
+
+/*
+ * SEEQ 8005 registers
+ */
+
+
+#define EA_8005_COMMAND 0x000
+#define EA_8005_STATUS 0x000
+#define EA_8005_CONFIG1 0x040
+#define EA_8005_CONFIG2 0x080
+#define EA_8005_RX_END 0x0c0
+#define EA_8005_BUFWIN 0x100
+#define EA_8005_RX_PTR 0x140
+#define EA_8005_TX_PTR 0x180
+#define EA_8005_DMA_ADDR 0x1c0
+
+/* */
+
+#define EA_CMD_DMA_INTEN (1 << 0)
+#define EA_CMD_RX_INTEN (1 << 1)
+#define EA_CMD_TX_INTEN (1 << 2)
+#define EA_CMD_BW_INTEN (1 << 3)
+#define EA_CMD_DMA_INTACK (1 << 4)
+#define EA_CMD_RX_INTACK (1 << 5)
+#define EA_CMD_TX_INTACK (1 << 6)
+#define EA_CMD_BW_INTACK (1 << 7)
+#define EA_CMD_DMA_ON (1 << 8)
+#define EA_CMD_RX_ON (1 << 9)
+#define EA_CMD_TX_ON (1 << 10)
+#define EA_CMD_DMA_OFF (1 << 11)
+#define EA_CMD_RX_OFF (1 << 12)
+#define EA_CMD_TX_OFF (1 << 13)
+#define EA_CMD_FIFO_READ (1 << 14)
+#define EA_CMD_FIFO_WRITE (1 << 15)
+
+#define EA_STATUS_DMA_INT (1 << 4)
+#define EA_STATUS_RX_INT (1 << 5)
+#define EA_STATUS_TX_INT (1 << 6)
+#define EA_STATUS_RX_ON (1 << 9)
+#define EA_STATUS_TX_ON (1 << 10)
+#define EA_STATUS_FIFO_FULL (1 << 13)
+#define EA_STATUS_FIFO_EMPTY (1 << 14)
+#define EA_STATUS_FIFO_DIR (1 << 15)
+#define EA_STATUS_FIFO_READ (1 << 15)
+
+#define EA_CFG1_DMA_BURST_CONT 0x00
+#define EA_CFG1_DMA_BURST_800 0x10
+#define EA_CFG1_DMA_BURST_1600 0x20
+#define EA_CFG1_DMA_BURST_3200 0x30
+#define EA_CFG1_DMA_BSIZE_1 0x00
+#define EA_CFG1_DMA_BSIZE_4 0x40
+#define EA_CFG1_DMA_BSIZE_8 0x80
+#define EA_CFG1_DMA_BSIZE_16 0xc0
+
+#define EA_CFG1_STATION_ADDR0 (1 << 8)
+#define EA_CFG1_STATION_ADDR1 (1 << 9)
+#define EA_CFG1_STATION_ADDR2 (1 << 10)
+#define EA_CFG1_STATION_ADDR3 (1 << 11)
+#define EA_CFG1_STATION_ADDR4 (1 << 12)
+#define EA_CFG1_STATION_ADDR5 (1 << 13)
+#define EA_CFG1_SPECIFIC ((0 << 15) | (0 << 14))
+#define EA_CFG1_BROADCAST ((0 << 15) | (1 << 14))
+#define EA_CFG1_MULTICAST ((1 << 15) | (0 << 14))
+#define EA_CFG1_PROMISCUOUS ((1 << 15) | (1 << 14))
+
+#define EA_CFG2_BYTESWAP (1 << 0)
+#define EA_CFG2_CRC_ERR_ENABLE (1 << 3)
+#define EA_CFG2_DRIB_ERR_ENABLE (1 << 4)
+#define EA_CFG2_PASS_SHORT (1 << 5)
+#define EA_CFG2_SLOT_SELECT (1 << 6)
+#define EA_CFG2_PREAM_SELECT (1 << 7)
+#define EA_CFG2_ADDR_LENGTH (1 << 8)
+#define EA_CFG2_RX_CRC (1 << 9)
+#define EA_CFG2_NO_TX_CRC (1 << 10)
+#define EA_CFG2_LOOPBACK (1 << 11)
+#define EA_CFG2_OUTPUT (1 << 12)
+#define EA_CFG2_RESET (1 << 15)
+
+#define EA_BUFCODE_STATION_ADDR0 0x00
+#define EA_BUFCODE_STATION_ADDR1 0x01
+#define EA_BUFCODE_STATION_ADDR2 0x02
+#define EA_BUFCODE_STATION_ADDR3 0x03
+#define EA_BUFCODE_STATION_ADDR4 0x04
+#define EA_BUFCODE_STATION_ADDR5 0x05
+#define EA_BUFCODE_ADDRESS_PROM 0x06
+#define EA_BUFCODE_TX_EAP 0x07
+#define EA_BUFCODE_LOCAL_MEM 0x08
+#define EA_BUFCODE_INT_VECTOR 0x09
+/*#define EA_BUFCODE_MULTICAST 0x0f*/
+
+#define EA_PKTHDR_TX (1 << 7)
+#define EA_PKTHDR_RX (0 << 7)
+#define EA_PKTHDR_CHAIN_CONT (1 << 6)
+#define EA_PKTHDR_DATA_FOLLOWS (1 << 5)
+
+#define EA_PKTHDR_DONE (1 << 7)
+
+#define EA_TXHDR_BABBLE (1 << 0)
+#define EA_TXHDR_COLLISION (1 << 1)
+#define EA_TXHDR_COLLISION16 (1 << 2)
+
+#define EA_TXHDR_BABBLE_INT (1 << 0)
+#define EA_TXHDR_COLLISION_INT (1 << 1)
+#define EA_TXHDR_COLLISION16_INT (1 << 2)
+#define EA_TXHDR_XMIT_SUCCESS_INT (1 << 3)
+#define EA_TXHDR_ERROR_MASK (0x07)
+
+#define EA_RXHDR_OVERSIZE (1 << 0)
+#define EA_RXHDR_CRC_ERROR (1 << 1)
+#define EA_RXHDR_DRIBBLE_ERROR (1 << 2)
+#define EA_RXHDR_SHORT_FRAME (1 << 3)
+
+#define EA_BUFFER_SIZE 0x10000
+#define EA_TX_BUFFER_SIZE 0x4000
+#define EA_RX_BUFFER_SIZE 0xC000
+
+/* Packet buffer size */
+
+#define EA_BUFSIZ 2048
+
+/* End of if_eareg.h */
--- /dev/null
+/* $NetBSD: if_eb.c,v 1.4 1996/03/27 21:49:31 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * if_eb.c
+ *
+ * EtherB device driver
+ *
+ * Created : 08/07/95
+ */
+
+/*
+ * SEEQ 80C04 device driver
+ */
+
+/*
+ * Bugs/possible improvements:
+ * - Does not currently support DMA
+ * - Does not currently support multicasts
+ * - Does not transmit multiple packets in one go
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/katelib.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/bootconfig.h>
+
+#include <arm32/podulebus/if_ebreg.h>
+#include <arm32/podulebus/podulebus.h>
+
+#define ETHER_MIN_LEN 64
+#define ETHER_MAX_LEN 1514
+#define ETHER_ADDR_LEN 6
+
+#ifndef EB_TIMEOUT
+#define EB_TIMEOUT 60
+#endif
+
+/*#define EB_TX_DEBUG*/
+/*#define EB_RX_DEBUG*/
+/*#define EB_DEBUG*/
+/*#define EB_PACKET_DEBUG*/
+
+/* for debugging convenience */
+#ifdef EB_DEBUG
+#define dprintf(x) printf x
+#else
+#define dprintf(x)
+#endif
+
+#define MY_MANUFACTURER 0x53
+#define MY_PODULE 0xe4
+
+/*
+ * per-line info and status
+ */
+
+struct eb_softc {
+ struct device sc_dev;
+ irqhandler_t sc_ih;
+ int sc_irq; /* IRQ number */
+ podule_t *sc_podule; /* Our podule */
+ int sc_podule_number; /* Our podule number */
+ u_int sc_iobase; /* base I/O addr */
+ struct arpcom sc_arpcom; /* ethernet common */
+ char sc_pktbuf[EB_BUFSIZ]; /* frame buffer */
+ int sc_config1; /* Current config1 bits */
+ int sc_config2; /* Current config2 bits */
+ int sc_command; /* Current command bits */
+ int sc_irqclaimed; /* Whether we have an IRQ claimed */
+ int sc_rx_ptr; /* Receive buffer pointer */
+ int sc_tx_ptr; /* Transmit buffer pointer */
+};
+
+/*
+ * prototypes
+ */
+
+static int ebintr __P((void *));
+static int eb_init __P((struct eb_softc *));
+static int eb_ioctl __P((struct ifnet *, u_long, caddr_t));
+static void eb_start __P((struct ifnet *));
+static void eb_watchdog __P((int));
+static void eb_reinit __P((struct eb_softc *));
+static void eb_chipreset __P((struct eb_softc *));
+static void eb_ramtest __P((struct eb_softc *));
+static int eb_stoptx __P((struct eb_softc *));
+static int eb_stoprx __P((struct eb_softc *));
+static void eb_stop __P((struct eb_softc *));
+static void eb_writebuf __P((struct eb_softc *, u_char *, int, int));
+static void eb_readbuf __P((struct eb_softc *, u_char *, int, int));
+static void ebread __P((struct eb_softc *, caddr_t, int));
+static struct mbuf *ebget __P((caddr_t, int, struct ifnet *));
+static void eb_hardreset __P((struct eb_softc *));
+static void ebgetpackets __P((struct eb_softc *));
+static void ebtxpacket __P((struct eb_softc *));
+
+int ebprobe __P((struct device *, void *, void *));
+void ebattach __P((struct device *, struct device *, void *));
+
+/* driver structure for autoconf */
+
+struct cfattach eb_ca = {
+ sizeof(struct eb_softc), ebprobe, ebattach
+};
+
+struct cfdriver eb_cd = {
+ NULL, "eb", DV_IFNET
+};
+
+#if 0
+
+/*
+ * Dump the chip registers
+ */
+
+void
+ebdump(iobase)
+ u_int iobase;
+{
+ dprintf(("%08x: %04x %04x %04x %04x %04x %04x %04x %04x\n", iobase,
+ ReadShort(iobase + 0x00), ReadShort(iobase + 0x40),
+ ReadShort(iobase + 0x80), ReadShort(iobase + 0xc0),
+ ReadShort(iobase + 0x100), ReadShort(iobase + 0x140),
+ ReadShort(iobase + 0x180), ReadShort(iobase + 0x1c0)));
+}
+#endif
+
+/*
+ * Dump the interface buffer
+ */
+
+void
+eb_dump_buffer(sc, offset)
+ struct eb_softc *sc;
+ int offset;
+{
+#ifdef EB_PACKET_DEBUG
+ u_int iobase = sc->sc_iobase;
+ int addr;
+ int loop;
+ int size;
+ int ctrl;
+ int ptr;
+
+ addr = offset;
+
+ do {
+ WriteShort(sc->sc_iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_READ);
+ WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_LOCAL_MEM);
+ WriteShort(iobase + EB_8004_DMA_ADDR, addr);
+
+ ptr = ReadShort(iobase + EB_8004_BUFWIN);
+ ctrl = ReadShort(iobase + EB_8004_BUFWIN);
+ ptr = ((ptr & 0xff) << 8) | ((ptr >> 8) & 0xff);
+
+ if (ptr == 0) break;
+ size = ptr - addr;
+
+ printf("addr=%04x size=%04x ", addr, size);
+ printf("cmd=%02x st=%02x\n", ctrl & 0xff, ctrl >> 8);
+
+ for (loop = 0; loop < size - 4; loop += 2)
+ printf("%04x ", ReadShort(iobase + EB_8004_BUFWIN));
+ printf("\n");
+ addr = ptr;
+ } while (size != 0);
+#endif
+}
+
+/*
+ * Probe routine.
+ */
+
+/*
+ * int ebprobe(struct device *parent, void *match, void *aux)
+ *
+ * Probe for the ether3 podule.
+ */
+
+int
+ebprobe(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ struct podule_attach_args *pa = (void *)aux;
+ int podule;
+ u_int iobase;
+
+/* dprintf(("Probing for SEEQ 8004... \n"));*/
+
+/* Look for a network slot interface */
+
+ podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+/* Fail if we did not find it */
+
+ if (podule == -1)
+ return(0);
+
+ iobase = podules[podule].mod_base + EB_8004_BASE;
+
+/* Reset it - Why here ? */
+
+ WriteShort(iobase + EB_8004_CONFIG2, EB_CFG2_RESET);
+ delay(100);
+
+/* We found it */
+
+ pa->pa_podule_number = podule;
+ pa->pa_podule = &podules[podule];
+
+ return(1);
+}
+
+
+/*
+ * void ebattach(struct device *parent, struct device *dev, void *aux)
+ *
+ * Attach podule.
+ */
+
+void
+ebattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct eb_softc *sc = (void *)self;
+ struct podule_attach_args *pa = (void *)aux;
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ int loop;
+ int sum;
+ int id;
+
+/* dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));*/
+
+/* Note the podule number and validate */
+
+ sc->sc_podule_number = pa->pa_podule_number;
+ if (sc->sc_podule_number == -1)
+ panic("Podule has disappeared !");
+
+ sc->sc_podule = &podules[sc->sc_podule_number];
+ podules[sc->sc_podule_number].attached = 1;
+
+/* Set the address of the controller for easy access */
+
+ sc->sc_iobase = sc->sc_podule->mod_base + EB_8004_BASE;
+
+ sc->sc_irqclaimed = 0;
+
+/* Set up the interrupt structure */
+
+ sc->sc_ih.ih_func = ebintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_NET;
+ sc->sc_ih.ih_name = "net: eb";
+
+/* Claim either a network slot interrupt or a podule interrupt */
+
+ if (sc->sc_podule_number >= MAX_PODULES)
+ sc->sc_irq = IRQ_NETSLOT;
+ else
+ sc->sc_irq = IRQ_PODULE /*+ sc->sc_podule_number*/;
+
+ /* Stop the board. */
+
+ eb_chipreset(sc);
+ eb_stoptx(sc);
+ eb_stoprx(sc);
+
+ /* Initialise ifnet structure. */
+
+ ifp->if_unit = sc->sc_dev.dv_unit;
+ ifp->if_name = eb_cd.cd_name;
+ ifp->if_start = eb_start;
+ ifp->if_ioctl = eb_ioctl;
+ ifp->if_watchdog = eb_watchdog;
+ ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
+
+ /* Now we can attach the interface. */
+
+/* dprintf(("Attaching interface...\n"));*/
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+/* Read the station address - the receiver must be off */
+
+ WriteShort(sc->sc_iobase + EB_8004_CONFIG1, EB_BUFCODE_STATION_ADDR);
+
+ for (sum = 0, loop = 0; loop < ETHER_ADDR_LEN; ++loop) {
+ sc->sc_arpcom.ac_enaddr[loop] =
+ ReadByte(sc->sc_iobase + EB_8004_BUFWIN);
+ sum += sc->sc_arpcom.ac_enaddr[loop];
+ }
+
+/*
+ * Hard code the ether address if we don't have one.
+ * Build the address from the machine id.
+ */
+
+ if (sum == 0) {
+ sc->sc_arpcom.ac_enaddr[0] = 0x00;
+ sc->sc_arpcom.ac_enaddr[1] = 0x00;
+ sc->sc_arpcom.ac_enaddr[2] = bootconfig.machine_id[3];
+ sc->sc_arpcom.ac_enaddr[3] = bootconfig.machine_id[2];
+ sc->sc_arpcom.ac_enaddr[4] = bootconfig.machine_id[1];
+ sc->sc_arpcom.ac_enaddr[5] = bootconfig.machine_id[0];
+ }
+
+ /* Get the product ID */
+
+ WriteShort(sc->sc_iobase + EB_8004_CONFIG1, EB_BUFCODE_PRODUCTID);
+ id = ReadByte(sc->sc_iobase + EB_8004_BUFWIN);
+
+ /* Print out some information for the user. */
+
+ if ((id & 0xf0) == 0xa0)
+ printf(" SEEQ80C04 rev %x address %s", id & 0x0f, ether_sprintf(sc->sc_arpcom.ac_enaddr));
+ else
+ printf(" SEEQ???? rev %02x address %s", id, ether_sprintf(sc->sc_arpcom.ac_enaddr));
+
+ /* Finally, attach to bpf filter if it is present. */
+
+#if NBPFILTER > 0
+/* dprintf(("Attaching to BPF...\n"));*/
+ bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+
+ /* Should test the RAM */
+
+ eb_ramtest(sc);
+
+/* dprintf(("ebattach() finished.\n"));*/
+}
+
+
+/*
+ * Test the RAM on the ethernet card. This does not work yet
+ */
+
+void
+eb_ramtest(sc)
+ struct eb_softc *sc;
+{
+ register u_int iobase = sc->sc_iobase;
+ register int loop;
+ register u_int sum = 0;
+
+/* dprintf(("eb_ramtest()\n"));*/
+
+ /*
+ * Test the buffer memory on the board.
+ * Write simple pattens to it and read them back.
+ */
+
+ /* Set up the whole buffer RAM for writing */
+
+ WriteShort(iobase + EB_8004_CONFIG1, EB_BUFCODE_TX_EAP);
+ WriteShort(iobase + EB_8004_BUFWIN, ((EB_BUFFER_SIZE >> 8) - 1));
+ WriteShort(iobase + EB_8004_TX_PTR, 0x0000);
+ WriteShort(iobase + EB_8004_RX_PTR, EB_BUFFER_SIZE - 2);
+
+ /* Set the write start address and write a pattern */
+
+ eb_writebuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+ WriteShort(iobase + EB_8004_BUFWIN, loop);
+
+ /* Set the read start address and verify the pattern */
+
+ eb_readbuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+ if (ReadShort(iobase + EB_8004_BUFWIN) != loop)
+ ++sum;
+
+ if (sum != 0)
+ dprintf(("sum=%d\n", sum));
+
+ /* Set the write start address and write a pattern */
+
+ eb_writebuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+ WriteShort(iobase + EB_8004_BUFWIN, loop ^ (EB_BUFFER_SIZE - 1));
+
+ /* Set the read start address and verify the pattern */
+
+ eb_readbuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+ if (ReadShort(iobase + EB_8004_BUFWIN) != (loop ^ (EB_BUFFER_SIZE - 1)))
+ ++sum;
+
+ if (sum != 0)
+ dprintf(("sum=%d\n", sum));
+
+ /* Set the write start address and write a pattern */
+
+ eb_writebuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+ WriteShort(iobase + EB_8004_BUFWIN, 0xaa55);
+
+ /* Set the read start address and verify the pattern */
+
+ eb_readbuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+ if (ReadShort(iobase + EB_8004_BUFWIN) != 0xaa55)
+ ++sum;
+
+ if (sum != 0)
+ dprintf(("sum=%d\n", sum));
+
+ /* Set the write start address and write a pattern */
+
+ eb_writebuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+ WriteShort(iobase + EB_8004_BUFWIN, 0x55aa);
+
+ /* Set the read start address and verify the pattern */
+
+ eb_readbuf(sc, NULL, 0x0000, 0);
+
+ for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2)
+ if (ReadShort(iobase + EB_8004_BUFWIN) != 0x55aa)
+ ++sum;
+
+ if (sum != 0)
+ dprintf(("sum=%d\n", sum));
+
+ /* Report */
+
+ if (sum == 0)
+ printf(" %dK buffer RAM\n", EB_BUFFER_SIZE / 1024);
+ else
+ printf(" buffer RAM failed self test, %d faults\n", sum);
+}
+
+
+/* Claim an irq for the board */
+
+void
+eb_claimirq(sc)
+ struct eb_softc *sc;
+{
+/* Have we claimed one already ? */
+
+ if (sc->sc_irqclaimed) return;
+
+/* Claim it */
+
+ dprintf(("eb_claimirq(%d)\n", sc->sc_irq));
+ if (irq_claim(sc->sc_irq, &sc->sc_ih))
+ panic("Cannot install IRQ handler for IRQ %d\n", sc->sc_irq);
+
+ sc->sc_irqclaimed = 1;
+}
+
+
+/* Release an irq */
+
+void
+eb_releaseirq(sc)
+ struct eb_softc *sc;
+{
+/* Have we claimed one ? */
+
+ if (!sc->sc_irqclaimed) return;
+
+ dprintf(("eb_releaseirq(%d)\n", sc->sc_irq));
+ if (irq_release(sc->sc_irq, &sc->sc_ih))
+ panic("Cannot release IRQ handler for IRQ %d\n", sc->sc_irq);
+
+ sc->sc_irqclaimed = 0;
+}
+
+
+/*
+ * Stop and reinitialise the interface.
+ */
+
+static void
+eb_reinit(sc)
+ struct eb_softc *sc;
+{
+ int s;
+
+ dprintf(("eb_reinit()\n"));
+
+/* Stop and reinitialise the interface */
+
+ s = splimp();
+ eb_stop(sc);
+ eb_init(sc);
+ (void)splx(s);
+}
+
+
+/*
+ * Stop the tx interface.
+ *
+ * Returns 0 if the tx was already stopped or 1 if it was active
+ */
+
+static int
+eb_stoptx(sc)
+ struct eb_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ int timeout;
+ int status;
+
+ dprintf(("eb_stoptx()\n"));
+
+ status = ReadShort(iobase + EB_8004_STATUS);
+ if (!(status & EB_STATUS_TX_ON))
+ return(0);
+
+/* Stop any tx and wait for confirmation */
+
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_TX_OFF);
+
+ timeout = 20000;
+ do {
+ status = ReadShort(iobase + EB_8004_STATUS);
+ } while ((status & EB_STATUS_TX_ON) && --timeout > 0);
+ if (timeout == 0)
+ dprintf(("eb_stoptx: timeout waiting for tx termination\n"));
+
+/* Clear any pending tx interrupt */
+
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_TX_INTACK);
+ return(1);
+}
+
+
+/*
+ * Stop the rx interface.
+ *
+ * Returns 0 if the tx was already stopped or 1 if it was active
+ */
+
+static int
+eb_stoprx(sc)
+ struct eb_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ int timeout;
+ int status;
+
+ dprintf(("eb_stoprx()\n"));
+
+ status = ReadShort(iobase + EB_8004_STATUS);
+ if (!(status & EB_STATUS_RX_ON))
+ return(0);
+
+/* Stop any rx and wait for confirmation */
+
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_RX_OFF);
+
+ timeout = 20000;
+ do {
+ status = ReadShort(iobase + EB_8004_STATUS);
+ } while ((status & EB_STATUS_RX_ON) && --timeout > 0);
+ if (timeout == 0)
+ dprintf(("eb_stoprx: timeout waiting for rx termination\n"));
+
+/* Clear any pending rx interrupt */
+
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_RX_INTACK);
+ return(1);
+}
+
+
+/*
+ * Stop interface.
+ * Stop all IO and shut the interface down
+ */
+
+static void
+eb_stop(sc)
+ struct eb_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+
+ dprintf(("eb_stop()\n"));
+
+/* Stop all IO */
+
+ eb_stoptx(sc);
+ eb_stoprx(sc);
+
+ /* Disable rx and tx interrupts */
+
+ sc->sc_command &= (EB_CMD_RX_INTEN | EB_CMD_TX_INTEN);
+
+ /* Clear any pending interrupts */
+
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+ | EB_CMD_RX_INTACK | EB_CMD_TX_INTACK | EB_CMD_TEST_INTACK
+ | EB_CMD_BW_INTACK);
+ dprintf(("st=%08x", ReadShort(iobase + EB_8004_STATUS)));
+
+ /* Release the irq */
+
+ eb_releaseirq(sc);
+
+ /* Put the chip to sleep */
+
+ WriteShort(iobase + EB_8004_CONFIG1, EB_BUFCODE_CONFIG3);
+ WriteShort(iobase + EB_8004_BUFWIN, EB_CFG3_SLEEP);
+
+ /* Cancel any watchdog timer */
+
+ sc->sc_arpcom.ac_if.if_timer = 0;
+}
+
+
+/*
+ * Reset the chip
+ * Following this the software registers are reset
+ */
+
+static void
+eb_chipreset(sc)
+ struct eb_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+
+ dprintf(("eb_chipreset()\n"));
+
+/* Reset the controller. Min of 4us delay here */
+
+ WriteShort(iobase + EB_8004_CONFIG2, EB_CFG2_RESET);
+ delay(100);
+
+ sc->sc_command = 0;
+ sc->sc_config1 = 0;
+ sc->sc_config2 = 0;
+}
+
+
+/*
+ * Do a hardware reset of the board, and upload the ethernet address again in
+ * case the board forgets.
+ */
+
+static void
+eb_hardreset(sc)
+ struct eb_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ int loop;
+
+ dprintf(("eb_hardreset()\n"));
+
+/* Stop any activity */
+
+ eb_stoptx(sc);
+ eb_stoprx(sc);
+
+ eb_chipreset(sc);
+
+/* Set up defaults for the registers */
+
+ sc->sc_config2 = 0;
+ WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+ sc->sc_command = 0x00;
+ sc->sc_config1 = 0;
+ WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1);
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command);
+
+ WriteShort(iobase + EB_8004_CONFIG1, EB_BUFCODE_TX_EAP);
+ WriteShort(iobase + EB_8004_BUFWIN, ((EB_TX_BUFFER_SIZE >> 8) - 1));
+
+/* Write the station address - the receiver must be off */
+
+ WriteShort(sc->sc_iobase + EB_8004_CONFIG1,
+ sc->sc_config1 | EB_BUFCODE_STATION_ADDR);
+ for (loop = 0; loop < ETHER_ADDR_LEN; ++loop) {
+ WriteByte(sc->sc_iobase + EB_8004_BUFWIN, sc->sc_arpcom.ac_enaddr[loop]);
+ }
+}
+
+
+/*
+ * write to the buffer memory on the interface
+ *
+ * If addr is within range for the interface buffer then the buffer
+ * address is set to addr.
+ * If len != 0 then data is copied from the address starting at buf
+ * to the interface buffer.
+ */
+
+static void
+eb_writebuf(sc, buf, addr, len)
+ struct eb_softc *sc;
+ u_char *buf;
+ int addr;
+ int len;
+{
+ u_int iobase = sc->sc_iobase;
+ int loop;
+ int timeout;
+
+ dprintf(("writebuf: st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));
+
+/* If we have a valid buffer address set the buffer pointer and direction */
+
+ if (addr >= 0 && addr < EB_BUFFER_SIZE) {
+ WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_LOCAL_MEM);
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_WRITE);
+
+ /* Should wait here of FIFO empty flag */
+
+ timeout = 20000;
+ while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+
+
+ WriteShort(iobase + EB_8004_DMA_ADDR, addr);
+ }
+
+ for (loop = 0; loop < len; loop += 2)
+ WriteShort(iobase + EB_8004_BUFWIN, buf[loop] | buf[loop + 1] << 8);
+
+
+/* if (len > 0)
+ outsw(iobase + EB_8004_BUFWIN, buf, len / 2);*/
+}
+
+
+/*
+ * read from the buffer memory on the interface
+ *
+ * If addr is within range for the interface buffer then the buffer
+ * address is set to addr.
+ * If len != 0 then data is copied from the interface buffer to the
+ * address starting at buf.
+ */
+
+static void
+eb_readbuf(sc, buf, addr, len)
+ struct eb_softc *sc;
+ u_char *buf;
+ int addr;
+ int len;
+{
+ u_int iobase = sc->sc_iobase;
+ int loop;
+ int word;
+ int timeout;
+
+ dprintf(("readbuf: st=%04x addr=%04x len=%d\n", ReadShort(iobase + EB_8004_STATUS), addr, len));
+
+/* If we have a valid buffer address set the buffer pointer and direction */
+
+ if (addr >= 0 && addr < EB_BUFFER_SIZE) {
+ if ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_DIR) == 0) {
+ /* Should wait here of FIFO empty flag */
+
+ timeout = 20000;
+ while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+ }
+ WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_LOCAL_MEM);
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_WRITE);
+
+ /* Should wait here of FIFO empty flag */
+
+ timeout = 20000;
+ while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_EMPTY) == 0 && --timeout > 0);
+
+ WriteShort(iobase + EB_8004_DMA_ADDR, addr);
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_READ);
+
+ /* Should wait here of FIFO full flag */
+
+ timeout = 20000;
+ while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_FULL) == 0 && --timeout > 0);
+
+
+ }
+
+ for (loop = 0; loop < len; loop += 2) {
+ word = ReadShort(iobase + EB_8004_BUFWIN);
+ buf[loop] = word & 0xff;
+ buf[loop + 1] = word >> 8;
+ }
+
+/* if (len > 0)
+ insw(iobase + EB_8004_BUFWIN, buf, len / 2);*/
+}
+
+
+/*
+ * Initialize interface.
+ *
+ * This should leave the interface in a state for packet reception and transmission
+ */
+
+static int
+eb_init(sc)
+ struct eb_softc *sc;
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ u_int iobase = sc->sc_iobase;
+ int s;
+
+ dprintf(("eb_init()\n"));
+
+ s = splimp();
+
+/* Grab an irq */
+
+ eb_claimirq(sc);
+
+ /* First, reset the board. */
+
+ eb_hardreset(sc);
+
+/* Configure rx. */
+
+ dprintf(("Configuring rx...\n"));
+ if (ifp->if_flags & IFF_PROMISC)
+ sc->sc_config1 = EB_CFG1_PROMISCUOUS;
+ else
+ sc->sc_config1 = EB_CFG1_BROADCAST;
+
+ sc->sc_config1 |= 0;
+ WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1);
+
+/* Configure TX. */
+
+ dprintf(("Configuring tx...\n"));
+
+ WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_TX_EAP);
+ WriteShort(iobase + EB_8004_BUFWIN, ((EB_TX_BUFFER_SIZE >> 8) - 1));
+ WriteShort(iobase + EB_8004_TX_PTR, 0x0000);
+
+ sc->sc_config2 |= (EB_CFG2_OUTPUT | EB_CFG2_RX_TX_DISABLE);
+ WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+
+/* Place a NULL header at the beginning of the transmit area */
+
+ eb_writebuf(sc, NULL, 0x0000, 0);
+
+ WriteShort(iobase + EB_8004_BUFWIN, 0x0000);
+ WriteShort(iobase + EB_8004_BUFWIN, 0x0000);
+
+ sc->sc_command |= EB_CMD_TX_INTEN;
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command);
+
+/* Setup the Rx pointers */
+
+ sc->sc_rx_ptr = EB_TX_BUFFER_SIZE;
+
+ WriteShort(iobase + EB_8004_RX_PTR, sc->sc_rx_ptr);
+ WriteShort(iobase + EB_8004_RX_END, (sc->sc_rx_ptr >> 8));
+
+/* Place a NULL header at the beginning of the receive area */
+
+ eb_writebuf(sc, NULL, sc->sc_rx_ptr, 0);
+
+ WriteShort(iobase + EB_8004_BUFWIN, 0x0000);
+ WriteShort(iobase + EB_8004_BUFWIN, 0x0000);
+
+/* Turn on Rx */
+
+ sc->sc_command |= EB_CMD_RX_INTEN;
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_RX_ON);
+
+ /* Set flags appropriately. */
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ dprintf(("init: st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));
+
+ /* And start output. */
+ eb_start(ifp);
+
+ (void)splx(s);
+ return(0);
+}
+
+
+/*
+ * Start output on interface. Get datagrams from the queue and output them,
+ * giving the receiver a chance between datagrams. Call only from splimp or
+ * interrupt level!
+ */
+
+static void
+eb_start(ifp)
+ struct ifnet *ifp;
+{
+ struct eb_softc *sc = eb_cd.cd_devs[ifp->if_unit];
+ int s;
+
+ s = splimp();
+#ifdef EB_TX_DEBUG
+ dprintf(("eb_start()...\n"));
+#endif
+
+ /* Don't do anything if output is active. */
+
+ if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE)
+ return;
+
+ /* Mark interface as output active */
+
+ sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
+
+ /* tx packets */
+
+ ebtxpacket(sc);
+ (void)splx(s);
+}
+
+
+/*
+ * Transfer a packet to the interface buffer and start transmission
+ *
+ * Called at splimp()
+ */
+
+void
+ebtxpacket(sc)
+ struct eb_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ struct mbuf *m, *m0;
+ int len;
+
+/* Dequeue the next datagram. */
+
+ IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0);
+
+/* If there's nothing to send, return. */
+
+ if (!m0) {
+ sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+ sc->sc_config2 |= EB_CFG2_OUTPUT;
+ WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+#ifdef EB_TX_DEBUG
+ dprintf(("tx finished\n"));
+#endif
+ return;
+ }
+
+ /* Give the packet to the bpf, if any. */
+#if NBPFILTER > 0
+ if (sc->sc_arpcom.ac_if.if_bpf)
+ bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
+#endif
+
+#ifdef EB_TX_DEBUG
+ dprintf(("Tx new packet\n"));
+#endif
+
+/*
+ * Copy the datagram to the temporary buffer.
+ *
+ * Eventually we may as well just copy straight into the interface buffer
+ */
+
+ len = 0;
+ for (m = m0; m; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ bcopy(mtod(m, caddr_t), sc->sc_pktbuf + len, m->m_len);
+ len += m->m_len;
+ }
+ m_freem(m0);
+
+/* If packet size is odd round up to the next 16 bit boundry */
+
+ if (len % 2)
+ ++len;
+
+ len = max(len, ETHER_MIN_LEN);
+
+ if (len > ETHER_MAX_LEN)
+ log(LOG_WARNING, "ea: oversize packet = %d bytes\n", len);
+
+/* Ok we now have a packet len bytes long in our packet buffer */
+
+/* Transfer datagram to board. */
+
+#ifdef EB_TX_DEBUG
+ dprintf(("eb: xfr pkt length=%d...\n", len));
+
+ dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
+ dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
+#endif
+
+ sc->sc_config2 &= ~EB_CFG2_OUTPUT;
+ WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+
+/* dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));*/
+
+/* Write the packet to the interface buffer, skipping the packet header */
+
+ eb_writebuf(sc, sc->sc_pktbuf, 0x0004, len);
+
+/* Follow it with a NULL packet header */
+
+ WriteShort(iobase + EB_8004_BUFWIN, 0x00);
+ WriteShort(iobase + EB_8004_BUFWIN, 0x00);
+
+/* Write the packet header */
+
+ eb_writebuf(sc, NULL, 0x0000, 0);
+
+ WriteShort(iobase + EB_8004_BUFWIN, (((len+4) & 0xff00) >> 8) | (((len+4) & 0xff) << 8));
+ WriteShort(iobase + EB_8004_BUFWIN, 0x00aa);
+
+ WriteShort(iobase + EB_8004_TX_PTR, 0x0000);
+
+/* dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));*/
+
+#ifdef EB_DEBUG
+ eb_dump_buffer(sc, 0);
+#endif
+
+/* Now transmit the datagram. */
+
+/* dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));*/
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_TX_ON);
+#ifdef EB_TX_DEBUG
+ dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));
+ dprintf(("tx: queued\n"));
+#endif
+}
+
+
+/*
+ * Ethernet controller interrupt.
+ */
+
+int
+ebintr(arg)
+ void *arg;
+{
+ register struct eb_softc *sc = arg;
+ u_int iobase = sc->sc_iobase;
+ int status, s;
+ u_int txstatus;
+
+ dprintf(("ebintr: "));
+
+/* Get the controller status */
+
+ status = ReadShort(iobase + EB_8004_STATUS);
+ dprintf(("st=%04x ", status));
+
+/* Tx interrupt ? */
+
+ if (status & EB_STATUS_TX_INT) {
+ dprintf(("txint "));
+
+/* Acknowledge the interrupt */
+
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+ | EB_CMD_TX_INTACK);
+
+ eb_readbuf(sc, (u_char *)&txstatus, 0x0000, 4);
+
+#ifdef EB_TX_DEBUG
+ dprintf(("txstatus=%08x\n", txstatus));
+#endif
+ txstatus = (txstatus >> 24) & 0xff;
+
+/*
+ * Did it succeed ? Did we collide ?
+ *
+ * The exact proceedure here is not clear. We should get
+ * an interrupt on a sucessfull tx or on a collision.
+ * The done flag is set after successfull tx or 16 collisions
+ * We should thus get a interrupt for each of collision
+ * and the done bit should not be set. However it does appear
+ * to be set at the same time as the collision bit ...
+ *
+ * So we will count collisions and output errors and will assume
+ * that if the done bit is set the packet was transmitted.
+ * Stats may be wrong if 16 collisions occur on a packet
+ * as the done flag should be set but the packet may not have been
+ * transmitted. so the output count might not require incrementing
+ * if the 16 collisions flags is set. I don;t know abou this until
+ * it happens.
+ */
+
+ if (txstatus & EB_TXHDR_COLLISION) {
+ sc->sc_arpcom.ac_if.if_collisions++;
+ } else if (txstatus & EB_TXHDR_ERROR_MASK) {
+ sc->sc_arpcom.ac_if.if_oerrors++;
+ }
+
+/* if (txstatus & EB_TXHDR_ERROR_MASK) {
+ log(LOG_WARNING, "tx packet error =%02x\n", txstatus);
+ }*/
+
+ if (txstatus & EB_PKTHDR_DONE) {
+ sc->sc_arpcom.ac_if.if_opackets++;
+
+ /* Tx next packet */
+
+ s = splimp();
+ ebtxpacket(sc);
+ (void)splx(s);
+ }
+ }
+
+/* Rx interrupt ? */
+
+ if (status & EB_STATUS_RX_INT) {
+ dprintf(("rxint "));
+
+/* Acknowledge the interrupt */
+
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+ | EB_CMD_RX_INTACK);
+
+/* Install a watchdog timer needed atm to fixed rx lockups */
+
+ sc->sc_arpcom.ac_if.if_timer = EB_TIMEOUT;
+
+/* Processes the received packets */
+ ebgetpackets(sc);
+
+/* Make sure the receiver is on */
+
+/* if ((status & EB_STATUS_RX_ON) == 0) {
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+ | EB_CMD_RX_ON);
+ printf("rxintr: rx is off st=%04x\n",status);
+ }*/
+ }
+
+#ifdef EB_DEBUG
+ status = ReadShort(iobase + EB_8004_STATUS);
+ dprintf(("st=%04x\n", status));
+#endif
+ return(0);
+}
+
+void
+ebgetpackets(sc)
+ struct eb_softc *sc;
+{
+ u_int iobase = sc->sc_iobase;
+ int addr;
+ int len;
+ int ctrl;
+ int ptr;
+ int pack;
+ int status;
+ u_int rxstatus;
+
+/* We start from the last rx pointer position */
+
+ addr = sc->sc_rx_ptr;
+ sc->sc_config2 &= ~EB_CFG2_OUTPUT;
+ WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+
+ do {
+/* Read rx header */
+
+ eb_readbuf(sc, (u_char *)&rxstatus, addr, 4);
+
+/* Split the packet header */
+
+ ptr = ((rxstatus & 0xff) << 8) | ((rxstatus >> 8) & 0xff);
+ ctrl = (rxstatus >> 16) & 0xff;
+ status = (rxstatus >> 24) & 0xff;
+
+#ifdef EB_RX_DEBUG
+ dprintf(("addr=%04x ptr=%04x ctrl=%02x status=%02x\n", addr, ptr, ctrl, status));
+#endif
+
+/* Zero packet ptr ? then must be null header so exit */
+
+ if (ptr == 0) break;
+
+/* Get packet length */
+
+ len = (ptr - addr) - 4;
+
+ if (len < 0) {
+ len += EB_RX_BUFFER_SIZE;
+ }
+
+#ifdef EB_RX_DEBUG
+ dprintf(("len=%04x\n", len));
+#endif
+
+/* Has the packet rx completed ? if not then exit */
+
+ if ((status & EB_PKTHDR_DONE) == 0)
+ break;
+
+/* Did we have any errors ? then note error and go to next packet */
+
+ if (status & 0x0f) {
+ ++sc->sc_arpcom.ac_if.if_ierrors;
+ printf("rx packet error (%02x) - dropping packet\n", status & 0x0f);
+/* sc->sc_config2 |= EB_CFG2_OUTPUT;
+ WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+ eb_reinit(sc);
+ return; */
+ addr = ptr;
+ continue;
+ }
+
+/* Is the packet too big ? - this will probably be trapped above as a receive error */
+
+ if (len > ETHER_MAX_LEN) {
+ ++sc->sc_arpcom.ac_if.if_ierrors;
+ printf("rx packet size error len=%d\n", len);
+/* sc->sc_config2 |= EB_CFG2_OUTPUT;
+ WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+ eb_reinit(sc);
+ return;*/
+ addr = ptr;
+ continue;
+ }
+
+ eb_readbuf(sc, sc->sc_pktbuf, addr + 4, len);
+
+#ifdef EB_RX_DEBUG
+ dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6)));
+ dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf)));
+#endif
+ sc->sc_arpcom.ac_if.if_ipackets++;
+ /* Pass data up to upper levels. */
+ ebread(sc, (caddr_t)sc->sc_pktbuf, len);
+
+ addr = ptr;
+ ++pack;
+ } while (len != 0);
+
+ sc->sc_config2 |= EB_CFG2_OUTPUT;
+ WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2);
+
+#ifdef EB_RX_DEBUG
+ dprintf(("new rx ptr=%04x\n", addr));
+#endif
+
+/* Store new rx pointer */
+
+ sc->sc_rx_ptr = addr;
+ WriteShort(iobase + EB_8004_RX_END, (sc->sc_rx_ptr >> 8));
+
+/* Make sure the receiver is on */
+
+ WriteShort(iobase + EB_8004_COMMAND, sc->sc_command
+ | EB_CMD_RX_ON);
+
+}
+
+
+/*
+ * Pass a packet up to the higher levels.
+ */
+
+static void
+ebread(sc, buf, len)
+ struct eb_softc *sc;
+ caddr_t buf;
+ int len;
+{
+ register struct ether_header *eh;
+ struct mbuf *m;
+
+ eh = (struct ether_header *)buf;
+ len -= sizeof(struct ether_header);
+ if (len <= 0)
+ return;
+
+ /* Pull packet off interface. */
+ m = ebget(buf, len, &sc->sc_arpcom.ac_if);
+ if (m == 0)
+ return;
+
+#if NBPFILTER > 0
+ /*
+ * Check if there's a BPF listener on this interface.
+ * If so, hand off the raw packet to bpf.
+ */
+ if (sc->sc_arpcom.ac_if.if_bpf) {
+ bpf_tap(sc->sc_arpcom.ac_if.if_bpf, buf, len + sizeof(struct ether_header));
+/* bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m);*/
+
+ /*
+ * Note that the interface cannot be in promiscuous mode if
+ * there are no BPF listeners. And if we are in promiscuous
+ * mode, we have to check if this packet is really ours.
+ */
+ if ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) &&
+ (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
+ bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
+ sizeof(eh->ether_dhost)) != 0) {
+ m_freem(m);
+ return;
+ }
+ }
+#endif
+
+ ether_input(&sc->sc_arpcom.ac_if, eh, m);
+}
+
+/*
+ * Pull read data off a interface. Len is length of data, with local net
+ * header stripped. We copy the data into mbufs. When full cluster sized
+ * units are present we copy into clusters.
+ */
+
+struct mbuf *
+ebget(buf, totlen, ifp)
+ caddr_t buf;
+ int totlen;
+ struct ifnet *ifp;
+{
+ struct mbuf *top, **mp, *m;
+ int len;
+ register caddr_t cp = buf;
+ char *epkt;
+
+ buf += sizeof(struct ether_header);
+ cp = buf;
+ epkt = cp + totlen;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == 0)
+ return 0;
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = totlen;
+ m->m_len = MHLEN;
+ top = 0;
+ mp = ⊤
+
+ while (totlen > 0) {
+ if (top) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == 0) {
+ m_freem(top);
+ return 0;
+ }
+ m->m_len = MLEN;
+ }
+ len = min(totlen, epkt - cp);
+ if (len >= MINCLSIZE) {
+ MCLGET(m, M_DONTWAIT);
+ if (m->m_flags & M_EXT)
+ m->m_len = len = min(len, MCLBYTES);
+ else
+ len = m->m_len;
+ } else {
+ /*
+ * Place initial small packet/header at end of mbuf.
+ */
+ if (len < m->m_len) {
+ if (top == 0 && len + max_linkhdr <= m->m_len)
+ m->m_data += max_linkhdr;
+ m->m_len = len;
+ } else
+ len = m->m_len;
+ }
+ bcopy(cp, mtod(m, caddr_t), (unsigned)len);
+ cp += len;
+ *mp = m;
+ mp = &m->m_next;
+ totlen -= len;
+ if (cp == epkt)
+ cp = buf;
+ }
+
+ return top;
+}
+
+/*
+ * Process an ioctl request. This code needs some work - it looks pretty ugly.
+ */
+static int
+eb_ioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct eb_softc *sc = eb_cd.cd_devs[ifp->if_unit];
+ struct ifaddr *ifa = (struct ifaddr *)data;
+/* struct ifreq *ifr = (struct ifreq *)data;*/
+ int s, error = 0;
+
+ s = splimp();
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ dprintf(("if_flags=%08x\n", ifp->if_flags));
+
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ arp_ifinit(&sc->sc_arpcom, ifa);
+ dprintf(("Interface eb is coming up (AF_INET)\n"));
+ eb_init(sc);
+ break;
+#endif
+#ifdef NS
+ /* XXX - This code is probably wrong. */
+ case AF_NS:
+ {
+ register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+
+ if (ns_nullhost(*ina))
+ ina->x_host =
+ *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
+ else
+ bcopy(ina->x_host.c_host,
+ sc->sc_arpcom.ac_enaddr,
+ sizeof(sc->sc_arpcom.ac_enaddr));
+ /* Set new address. */
+ dprintf(("Interface eb is coming up (AF_NS)\n"));
+ eb_init(sc);
+ break;
+ }
+#endif
+ default:
+ dprintf(("Interface eb is coming up (default)\n"));
+ eb_init(sc);
+ break;
+ }
+ break;
+
+ case SIOCSIFFLAGS:
+ dprintf(("if_flags=%08x\n", ifp->if_flags));
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ (ifp->if_flags & IFF_RUNNING) != 0) {
+ /*
+ * If interface is marked down and it is running, then
+ * stop it.
+ */
+ dprintf(("Interface ea is stopping\n"));
+ eb_stop(sc);
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if ((ifp->if_flags & IFF_UP) != 0 &&
+ (ifp->if_flags & IFF_RUNNING) == 0) {
+ /*
+ * If interface is marked up and it is stopped, then
+ * start it.
+ */
+ dprintf(("Interface eb is restarting(1)\n"));
+ eb_init(sc);
+ } else {
+ /*
+ * Some other important flag might have changed, so
+ * reset.
+ */
+ dprintf(("Interface eb is reinitialising\n"));
+ eb_reinit(sc);
+ }
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ (void)splx(s);
+ return error;
+}
+
+/*
+ * Device timeout routine.
+ *
+ * Ok I am not sure exactly how the device timeout should work....
+ * Currently what will happens is that that the device timeout is only
+ * set when a packet it received. This indicates we are on an active
+ * network and thus we should expect more packets. If non arrive in
+ * in the timeout period then we reinitialise as we may have jammed.
+ * We zero the timeout at this point so that we don't end up with
+ * an endless stream of timeouts if the network goes down.
+ */
+
+static void
+eb_watchdog(unit)
+ int unit;
+{
+ struct eb_softc *sc = eb_cd.cd_devs[unit];
+
+ log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
+ sc->sc_arpcom.ac_if.if_oerrors++;
+ dprintf(("eb_watchdog: "));
+ dprintf(("st=%04x\n", ReadShort(sc->sc_iobase + EB_8004_STATUS)));
+
+ /* Kick the interface */
+
+ eb_reinit(sc);
+
+ sc->sc_arpcom.ac_if.if_timer = 0;
+}
+
+/* End of if_ea.c */
--- /dev/null
+/* $NetBSD: if_ebreg.h,v 1.2 1996/03/18 21:23:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * if_ebreg.h
+ *
+ * EtherB device driver
+ *
+ * Created : 08/07/95
+ */
+
+/*
+ * SEEQ 80C04 Register Definitions
+ */
+
+#define EB_8004_BASE 0x800
+
+/*
+ * SEEQ 80C04 registers
+ */
+
+#define EB_8004_COMMAND 0x000
+#define EB_8004_STATUS 0x000
+#define EB_8004_CONFIG1 0x040
+#define EB_8004_CONFIG2 0x080
+#define EB_8004_RX_END 0x0c0
+#define EB_8004_BUFWIN 0x100
+#define EB_8004_RX_PTR 0x140
+#define EB_8004_TX_PTR 0x180
+#define EB_8004_DMA_ADDR 0x1c0
+
+/* */
+
+#define EB_CMD_TEST_INTEN (1 << 0)
+#define EB_CMD_RX_INTEN (1 << 1)
+#define EB_CMD_TX_INTEN (1 << 2)
+#define EB_CMD_TEST_INTACK (1 << 4)
+#define EB_CMD_RX_INTACK (1 << 5)
+#define EB_CMD_TX_INTACK (1 << 6)
+#define EB_CMD_BW_INTACK (1 << 7)
+#define EB_CMD_TEST_INT1 (1 << 8)
+#define EB_CMD_RX_ON (1 << 9)
+#define EB_CMD_TX_ON (1 << 10)
+#define EB_CMD_TEST_INT2 (1 << 11)
+#define EB_CMD_RX_OFF (1 << 12)
+#define EB_CMD_TX_OFF (1 << 13)
+#define EB_CMD_FIFO_READ (1 << 14)
+#define EB_CMD_FIFO_WRITE (1 << 15)
+
+#define EB_STATUS_TEST_INT (1 << 4)
+#define EB_STATUS_RX_INT (1 << 5)
+#define EB_STATUS_TX_INT (1 << 6)
+#define EB_STATUS_RX_ON (1 << 9)
+#define EB_STATUS_TX_ON (1 << 10)
+#define EB_STATUS_TX_NOFAIL (1 << 12)
+#define EB_STATUS_FIFO_FULL (1 << 13)
+#define EB_STATUS_FIFO_EMPTY (1 << 14)
+#define EB_STATUS_FIFO_DIR (1 << 15)
+#define EB_STATUS_FIFO_READ (1 << 15)
+
+#define EB_CFG1_SPECIFIC ((0 << 15) | (0 << 14))
+#define EB_CFG1_BROADCAST ((0 << 15) | (1 << 14))
+#define EB_CFG1_MULTICAST ((1 << 15) | (0 << 14))
+#define EB_CFG1_PROMISCUOUS ((1 << 15) | (1 << 14))
+
+#define EB_CFG2_BYTESWAP (1 << 0)
+#define EB_CFG2_REA_AUTOUPDATE (1 << 1)
+#define EB_CFG2_RX_TX_DISABLE (1 << 2)
+#define EB_CFG2_CRC_ERR_ENABLE (1 << 3)
+#define EB_CFG2_DRIB_ERR_ENABLE (1 << 4)
+#define EB_CFG2_PASS_LONGSHORT (1 << 5)
+#define EB_CFG2_PREAM_SELECT (1 << 7)
+#define EB_CFG2_RX_CRC (1 << 9)
+#define EB_CFG2_NO_TX_CRC (1 << 10)
+#define EB_CFG2_LOOPBACK (1 << 11)
+#define EB_CFG2_OUTPUT (1 << 12)
+#define EB_CFG2_RESET (1 << 15)
+
+#define EB_CFG3_SLEEP (1 << 3)
+
+#define EB_BUFCODE_STATION_ADDR 0x00
+#define EB_BUFCODE_ADDRESS_PROM 0x06
+#define EB_BUFCODE_TX_EAP 0x07
+#define EB_BUFCODE_LOCAL_MEM 0x08
+#define EB_BUFCODE_TX_COLLS 0x0b
+#define EB_BUFCODE_CONFIG3 0x0c
+#define EB_BUFCODE_PRODUCTID 0x0d
+#define EB_BUFCODE_TESTENABLE 0x0e
+#define EB_BUFCODE_MULTICAST 0x0f
+
+#define EB_PKTHDR_TX (1 << 7)
+#define EB_PKTHDR_RX (0 << 7)
+#define EB_PKTHDR_CHAIN_CONT (1 << 6)
+#define EB_PKTHDR_DATA_FOLLOWS (1 << 5)
+
+#define EB_PKTHDR_DONE (1 << 7)
+
+#define EB_TXHDR_BABBLE (1 << 0)
+#define EB_TXHDR_COLLISION (1 << 1)
+#define EB_TXHDR_COLLISION16 (1 << 2)
+#define EB_TXHDR_COLLISIONMASK (0x78)
+#define EB_TXHDR_ERROR_MASK (0x07)
+
+#define EB_TXHDR_BABBLE_INT (1 << 0)
+#define EB_TXHDR_COLLISION_INT (1 << 1)
+#define EB_TXHDR_COLLISION16_INT (1 << 2)
+#define EB_TXHDR_XMIT_SUCCESS_INT (1 << 3)
+#define EB_TXHDR_SQET_TEST_INT (1 << 3)
+
+#define EB_RXHDR_OVERSIZE (1 << 0)
+#define EB_RXHDR_CRC_ERROR (1 << 1)
+#define EB_RXHDR_DRIBBLE_ERROR (1 << 2)
+#define EB_RXHDR_SHORT_FRAME (1 << 3)
+
+#define EB_BUFFER_SIZE 0x10000
+#define EB_TX_BUFFER_SIZE 0x4000
+#define EB_RX_BUFFER_SIZE 0xC000
+
+/* Packet buffer size */
+
+#define EB_BUFSIZ 2048
+
+/* End of if_ebreg.h */
--- /dev/null
+/* $NetBSD: if_eh.c,v 1.6 1996/03/27 21:49:34 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson.
+ * All rights reserved.
+ *
+ * Essential things to do
+ * - BPF and multicast support
+ * - Testing
+ * - 16-bit dma's
+ * - Buffer overflow handling (This must be done a certain way) [Nuts]
+ * - Enabling card interrupts (Need i cubed info)
+ *
+ * Other things to do
+ * - Pipelined transmitts
+ * - Dynamic buffer allocation
+ * - Shared RAM if I cubed give me info
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * if_eh.c
+ *
+ * Ether H driver.
+ */
+
+/* Some system includes *****************************************************/
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <machine/bootconfig.h>
+
+/* Hardware related include chip/card/bus ***********************************/
+
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/if_ehreg.h>
+
+/* Includes for interfacing with the network subsystem **********************/
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+/****************************************************************************/
+/* Some useful definitions **************************************************/
+/****************************************************************************/
+
+#define MY_MANUFACTURER (0x46)
+#define MY_PODULE (0xec)
+
+#define TXBUF_SIZE (1522)
+#define NTXBUF (1)
+
+#define RXBUF_SIZE (256)
+#define NRXBUF (26)
+
+#define ETHER_MIN_LEN (64)
+#define ETHER_MAX_LEN (1522)
+
+#define PRINTF printf
+
+/****************************************************************************/
+/* Prototype internal data structures ***************************************/
+/****************************************************************************/
+
+struct eh_softc {
+ /* Kernel interface variables */
+ struct device sc_dev;
+ int sc_podule_number;
+ podule_t *sc_podule;
+ irqhandler_t sc_ih;
+
+ /* Network subsystem interface */
+ struct arpcom sc_arpcom;
+ int promisc;
+
+ /* Driver defined state variables */
+ int sc_flags;
+
+ /* Hardware defined state */
+ int sc_base;
+ int sc_reg;
+ int sc_nxtpkt;
+
+ /* Card memory map */
+ int sc_physstart;
+ int sc_physend;
+ int sc_tbs[NTXBUF]; /* Transmit buffer start */
+ int sc_rbs;
+ int sc_rbd;
+
+ /* Txrx parameters */
+ int sc_txcur; /* Fill this buffer next */
+ int sc_txlst; /* Buffer in use */
+};
+
+/* sc_flags */
+
+#define MODE_MASK (3)
+#define MODE_DEAD (0)
+#define MODE_PIO (1)
+#define MODE_SHRAM (2)
+
+/****************************************************************************/
+/* Function and data prototypes *********************************************/
+/****************************************************************************/
+
+int ehprobe __P((struct device *parent, void *match, void *aux));
+void ehattach __P((struct device *parent, struct device *self, void *aux));
+void ehstart __P((struct ifnet *ifp));
+int ehioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
+void ehwatchdog __P((int unit));
+void eh_stop_controller __P((struct eh_softc *sc));
+void eh_start_controller __P((struct eh_softc *sc));
+void eh_transmit_command __P((struct eh_softc *sc));
+int eh_copyin __P((struct eh_softc *sc, int src, char *dest, int len));
+int eh_copyout __P((struct eh_softc *sc, char *src, int dest, int len));
+void ehinit __P((struct eh_softc *sc));
+int ehstop __P((struct eh_softc *sc));
+int ehintr __P((void *arg));
+void eh_shutdown __P((void *arg));
+
+struct cfattach eh_ca = {
+ sizeof(struct eh_softc), ehprobe, ehattach
+};
+
+struct cfdriver eh_cd = {
+ NULL, "eh", DV_DULL, NULL, 0
+};
+
+/****************************************************************************/
+/* Some useful macros *******************************************************/
+/****************************************************************************/
+
+#define SetReg(r,v) WriteWord ( sc->sc_reg+(r), (v)|((v)<<16) )
+
+#define GetReg(r) ReadByte ( sc->sc_reg+(r) )
+
+#define PAGE(n) SetReg ( EH_COMMAND, \
+ ((GetReg(EH_COMMAND)&COM_MASK_PAGE)|(n<<6)) )
+
+/* When initiating a remote dma, reset the TXP bit. This Does Not abort */
+/* the transmit, but allows us overlap this remote dma */
+
+#define REMOTE_DMA(n) SetReg ( EH_COMMAND, \
+ ((GetReg(EH_COMMAND)&(COM_MASK_DMA))|n) )
+
+extern char *boot_args;
+char *strstr __P((char */*s1*/, char */*s2*/));
+
+/****************************************************************************/
+/* Bus attachment code ******************************************************/
+/****************************************************************************/
+
+int
+ehprobe(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ struct eh_softc *sc = (void *) match;
+ struct podule_attach_args *pa = (void *) aux;
+ int counter;
+ int temp;
+ int podule;
+
+ podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+ if (podule == -1)
+ return 0;
+
+ /* Start to fill in the softc with the trivial variables */
+
+ sc->sc_flags = MODE_PIO; /* Select pio mode until I get info from i^3 */
+ sc->sc_base = podules[podule].fast_base;
+ sc->sc_reg = sc->sc_base + 0x800;
+
+ /* The probe could be tidied up a little */
+
+ /* Reset the card */
+ SetReg(EH_RESET, 0xff);
+ delay(10000);
+
+ /* Explicitly abort remote DMA, mainly to set a legal state */
+ PAGE(0);
+ eh_stop_controller(sc);
+ SetReg(EH_COMMAND, 0x20); /* This is wrong */
+
+ SetReg(EH_ISR, 0xf ); /* Clear any previous work */
+
+ temp = GetReg(EH_CONFIGA);
+ temp = GetReg(EH_CONFIGA);
+ temp &= ~0x38;
+ SetReg(EH_CONFIGA, temp | 3<<3);
+
+ temp = GetReg(EH_CONFIGA);
+ temp = GetReg(EH_CONFIGA);
+
+ /* Make the thing interrupt and test it */
+
+ eh_start_controller(sc);
+
+ /* Temporary initialisation, to allow a transmit test */
+
+ SetReg(EH_PSTART, 16384 >> 8);
+ SetReg(EH_PSTOP, 16896 >> 8);
+ SetReg(EH_BNRY, 16384 >> 8);
+
+ SetReg(EH_TCR, TCR_NORMALLOOP); /* Erk!! No, put us in loopback */
+ SetReg(EH_DCR, DCR_WTS|DCR_LS|DCR_LAS);
+ SetReg(EH_RCR, 0);
+
+ /* Transmit some garbage into the loopback */
+
+ SetReg(EH_TPSR, 0x5000);
+ SetReg(EH_TBCR0, 0);
+ SetReg(EH_TBCR1, 3);
+
+ eh_transmit_command(sc);
+
+ /* The card shouldn't be this quick, so use it as a test */
+
+ if ((GetReg(EH_TSR)&TSR_DONE) != 0)
+ PRINTF("eh: Card responded rather quickly %02x\n", GetReg(EH_TSR));
+
+ for (counter=500; counter>0; counter--) {
+ if ((GetReg(EH_TSR)&TSR_DONE) != 0)
+ break;
+
+ delay(500);
+ }
+
+ if (counter == 0) {
+ PRINTF("eh: card did not respond\n");
+ return 0;
+ }
+
+ /* Let it sleep since we're not doing anything with it for now */
+
+ SetReg(EH_ISR, 0);
+ SetReg(EH_DCR, DCR_WTS|DCR_LS|DCR_LAS);
+
+
+ /* Test the board ram. This code will change */
+
+ /*
+ * Due to problems with some ether H cards the boot option ehbug
+ * can be used to skip this test.
+ * If you system hangs during the eh probe try this option.
+ */
+
+ #define NLEN (0x2000)
+ #define NBASE (0x4000)
+
+ if (boot_args) {
+ char *ptr;
+
+ ptr = strstr(boot_args, "ehbug");
+ if (!ptr) {
+ char *test_data;
+ char *read_buffer;
+ MALLOC(test_data, char *, NLEN, M_TEMP, M_NOWAIT);
+ if (test_data == NULL)
+ panic("Cannot allocate temporary memory for buffer test (1)\n");
+ MALLOC(read_buffer, char *, NLEN, M_TEMP, M_NOWAIT);
+ if (read_buffer == NULL)
+ panic("Cannot allocate temporary memory for buffer test (1)\n");
+
+ printf("1.");
+
+ /* Fill the test_data block */
+
+ for (counter=0; counter<NLEN; counter++) {
+ test_data[counter] = (char)(counter&0xff);
+ if (test_data[counter] == 0)
+ test_data[counter]=0x23;
+ }
+
+ printf("2.");
+
+ eh_copyout(sc, test_data, NBASE, NLEN);
+ printf("3.");
+ delay(10000);
+ eh_copyin(sc, NBASE, read_buffer, NLEN);
+ printf("4.");
+
+ if (bcmp(test_data, read_buffer, NLEN))
+ PRINTF("Block test failed\n");
+ printf("5.");
+ FREE(test_data, M_TEMP);
+ FREE(read_buffer, M_TEMP);
+ }
+ }
+ /* This is always true for our ether h */
+
+ sc->sc_physstart = 0x4000;
+ sc->sc_physend = 0x6000;
+
+ /* Get out ethernet address */
+ sc->sc_arpcom.ac_enaddr[0] = 0x00;
+ sc->sc_arpcom.ac_enaddr[1] = 0x00;
+ sc->sc_arpcom.ac_enaddr[2] = 0xc0;
+ sc->sc_arpcom.ac_enaddr[3] = 0x41;
+ sc->sc_arpcom.ac_enaddr[4] = bootconfig.machine_id[1];
+ sc->sc_arpcom.ac_enaddr[5] = bootconfig.machine_id[0];
+
+ /* Copy the ether addr cards filter */
+
+ PAGE(1);
+ for (counter=0; counter<6; counter++)
+ SetReg(((counter+1)<<2), sc->sc_arpcom.ac_enaddr[counter]);
+ PAGE(0);
+
+ /* Tell the podule system about our successful probe */
+ pa->pa_podule_number = podule;
+ pa->pa_podule = &podules[podule];
+
+ return 1;
+}
+
+void
+ehattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct eh_softc *sc = (void *) self;
+ struct podule_attach_args *pa = (void *)aux;
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ int irq;
+ int temp;
+
+ /* Check a few things about the attach args */
+ sc->sc_podule_number = pa->pa_podule_number;
+ if (sc->sc_podule_number == -1)
+ panic("Podule has disappeared !");
+
+ sc->sc_podule = &podules[sc->sc_podule_number];
+ podules[sc->sc_podule_number].attached = 1;
+
+ /* Fill in my application form to attach to the networking system */
+
+ ifp->if_unit = sc->sc_dev.dv_unit;
+ ifp->if_name = eh_cd.cd_name;
+ ifp->if_start = ehstart;
+ ifp->if_ioctl = ehioctl;
+ ifp->if_watchdog = ehwatchdog;
+ ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
+
+ /* Signed, dated then sent */
+
+ if_attach(ifp);
+ ether_ifattach(ifp);
+
+ /* Not print some stuff for the attach line, starting with the address */
+
+ PRINTF(" address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));
+
+ /* Now the transfer mode we're operating in */
+
+ switch (sc->sc_flags & MODE_MASK) {
+ case MODE_PIO:
+ PRINTF(" pio mode");
+ break;
+ case MODE_SHRAM:
+ PRINTF(" ram mode");
+ break;
+ default:
+ panic("Ether H probe set an unknown mode");
+ }
+
+ /* Get an irq handler installed */
+
+ SetReg(EH_IMR, 0);
+ SetReg(EH_ISR, 0xff);
+
+ sc->sc_ih.ih_func = ehintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_NET;
+ sc->sc_ih.ih_name = "net: eh";
+
+ irq = (sc->sc_podule_number>=MAX_PODULES) ? IRQ_NETSLOT : IRQ_PODULE;
+
+ if (irq_claim(irq, &sc->sc_ih))
+ panic("Cannot install IRQ handler");
+
+ /* This loopbacks the card on reset, and stops riscos locking */
+
+ if (shutdownhook_establish(eh_shutdown, (void *)sc)==NULL)
+ panic("Cannot install shutdown handler");
+
+ /* Reprogram CONFIGA. I dont think we should do this any more */
+
+ temp = GetReg(EH_CONFIGA);
+ temp = GetReg(EH_CONFIGA);
+ temp &= ~0x38;
+ SetReg(EH_CONFIGA, temp | (3<<3));
+
+ /* And that's it */
+
+ PRINTF("\n");
+}
+
+/****************************************************************************/
+/* Net subsystem interface **************************************************/
+/****************************************************************************/
+
+#define NEXT_TXBUF (((sc->sc_txcur+1)>=NTXBUF) ? 0 : (sc->sc_txcur+1))
+
+void
+ehstart(ifp)
+ struct ifnet *ifp;
+{
+ struct eh_softc *sc = eh_cd.cd_devs[ifp->if_unit];
+ int cur;
+ struct mbuf *m0, *m;
+ int nextbuf;
+ char *buffer;
+ char txbuf[TXBUF_SIZE];
+ int len = 0;
+
+ PAGE(0);
+
+ if ((ifp->if_flags & IFF_OACTIVE) != 0)
+ return;
+
+/* This is for pipelined transmit. At present just use 1 buffer */
+
+ for (;;) {
+
+/* The #ifdef PIPELINE_TRANSMIT code is total screwed */
+
+#ifdef PIPELINE_TRANSMIT
+ nextbuf = NEXT_TXBUF;
+ if ( nextbuf == sc->sc_txlst )
+ ifp->if_flags |= IFF_OACTIVE;
+ break;
+ }
+#else
+ nextbuf = 0;
+#endif
+
+ /*** Speed up - In future, copy the bufs direct to the card ***/
+
+ /* Copy a frame out of the mbufs */
+
+ IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m);
+ if ( !m )
+ break;
+
+ buffer = txbuf;
+
+ len = 0;
+ for ( m0=m; m && (len + m->m_len) < TXBUF_SIZE; m=m->m_next ) {
+ bcopy(mtod(m,caddr_t), buffer, m->m_len);
+ buffer+=m->m_len;
+ len+=m->m_len;
+ }
+
+ m_freem(m0);
+ len = max ( len, ETHER_MIN_LEN );
+
+ /* And blat it to the card */
+
+ eh_copyout ( sc, txbuf, sc->sc_tbs[nextbuf], len );
+
+#ifdef PIPELINE_TRANSMIT
+ sc->sc_txlst = nextbuf;
+#endif
+ PAGE(0);
+
+ SetReg ( EH_TPSR, sc->sc_tbs[nextbuf]>>8 );
+ SetReg ( EH_TBCR0, len&0xff );
+ SetReg ( EH_TBCR1, (len>>8) & 0xff );
+
+ cur = GetReg(EH_COMMAND);
+
+ eh_transmit_command (sc );
+
+ ifp->if_flags |= IFF_OACTIVE;
+ ifp->if_timer = 30;
+
+#ifndef PIPELINE_TRANSMIT
+ break;
+#endif
+ }
+}
+
+#define IZSET(a,b) ((a->if_flags&b)!=0)
+#define IZCLR(a,b) ((a->if_flags&b)==0)
+#define DOSET(a,b) (a->if_flags|=b)
+#define DOCLR(a,b) (a->if_flags&=~b)
+
+int
+ehioctl(ifp, cmd, data)
+ struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct eh_softc *sc = eh_cd.cd_devs[ifp->if_unit];
+ struct ifaddr *ifa = (struct ifaddr *)data;
+ int s = splimp ();
+ int error = 0;
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ switch ( ifa->ifa_addr->sa_family ) {
+#ifdef INET
+ case AF_INET:
+ ehinit(sc);
+ arp_ifinit(&sc->sc_arpcom, ifa);
+ break;
+#endif
+ default:
+ ehinit(sc);
+ break;
+ }
+ break;
+
+ case SIOCSIFFLAGS:
+ sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI );
+
+ if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) ) {
+ /* Interface marked down, but still running */
+ ehstop(sc);
+ DOCLR(ifp,IFF_RUNNING);
+ } else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) ) {
+ /* Just marked up, not running yet */
+ ehinit(sc);
+ } else {
+ /* Reset to invoke changes in other registers */
+ ehstop(sc);
+ ehinit(sc);
+ }
+
+ default:
+ error = EINVAL;
+ }
+
+ splx (s);
+ return error;
+}
+
+void
+ehwatchdog(unit)
+ int unit;
+{
+ struct eh_softc *sc = eh_cd.cd_devs[unit];
+
+ log (LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname );
+ sc->sc_arpcom.ac_if.if_oerrors++;
+
+ ehinit (sc);
+}
+
+/*
+ * void eh_stop_controller ( struct eh_softc *sc )
+ *
+ * Software reset command, takes the controller offline, no packets will be
+ * received or transmitted. Any reception or transmission inprogres will
+ * continue to completion before entering the reset state.
+ */
+
+void
+eh_stop_controller(sc)
+ struct eh_softc *sc;
+{
+ SetReg ( EH_COMMAND, ((GetReg(EH_COMMAND)&0xfc)|1) );
+ delay ( 10000 ); /* Change this to wait on the ISR bit */
+}
+
+/*
+ * void eh_start_controller ( struct eh_softc *sc )
+ *
+ * Activte the NIC core after either power up or when the NIC Core has
+ * been placed in a reset mode by eh_stop_controller or an error.
+ */
+
+void
+eh_start_controller(sc)
+ struct eh_softc *sc;
+{
+ int temp = GetReg(EH_COMMAND);
+ SetReg ( EH_COMMAND, ( (temp&0xfc)|2) );
+}
+
+void
+eh_transmit_command(sc)
+ struct eh_softc *sc;
+{
+ /* Explicit set here. There is no other reasonable combination */
+ SetReg ( EH_COMMAND, COM_ABORT|COM_STA|COM_TXP);
+}
+
+/****************************************************************************/
+/* Remote DMA handling ******************************************************/
+/****************************************************************************/
+
+/* Remote DMA handling is going to undergo a major overhaul real soon now */
+
+/* We musn't fail */
+
+inline void
+eh_ensure_dma_ok(sc)
+ struct eh_softc *sc;
+{
+ register int isr = GetReg ( EH_ISR );
+ register int status = GetReg ( EH_COMMAND );
+ int dummy;
+
+ if ((status&COM_ABORT)==0) {
+ SetReg ( EH_COMMAND, status|COM_ABORT );
+ while ((isr&ISR_RDC)==0) {
+ dummy = GetReg ( EH_DATA_PORT );
+ delay(50);
+ }
+ }
+
+ /* Reset the COM_TXP bit. This does not abort transmission */
+
+ SetReg(EH_COMMAND, 0x22);
+}
+
+inline int
+eh_ensure_dma_competed(sc, type)
+ struct eh_softc *sc;
+ int type;
+{
+ register int status = GetReg ( EH_COMMAND );
+
+ if ( (status&COM_ABORT)==0 ) {
+ int dummy=0;
+ printf ( "EHDEBUG: Remote %d wasn't finished\n", type );
+ SetReg ( EH_COMMAND, status|COM_ABORT );
+ switch ( type ) {
+ case COM_READ:
+ dummy = GetReg ( EH_DATA_PORT );
+ break;
+ case COM_WRITE:
+ SetReg ( EH_DATA_PORT, dummy );
+ break;
+ }
+ ehinit (sc);
+ return 1;
+ }
+ return 0;
+}
+
+/* Do an eh_copyin, but take into consideration ring wrap */
+
+int
+eh_copyring(sc, src, dest, len)
+ struct eh_softc *sc;
+ int src;
+ char *dest;
+ int len;
+{
+ if ( (src+len)>sc->sc_rbd ) {
+ register int in = sc->sc_rbd - src;
+ if ( eh_copyin ( sc, src, dest, in )==0 ) {
+ printf ( "copyring failed pass 1\n" );
+ return 0;
+ }
+ if ( eh_copyin ( sc, sc->sc_rbs, dest+in, len-in )==0 ) {
+ printf ( "copyring failed pass 2\n" );
+ return 0;
+ }
+ } else {
+ if ( eh_copyin ( sc, src, dest, len )==0 ) {
+ printf ( "copyring faild on 1 pass copy\n" );
+ return 0;
+ }
+ }
+ return len;
+}
+
+int
+eh_copyin(sc, src, dest, len)
+ struct eh_softc *sc;
+ int src;
+ char *dest;
+ int len;
+{
+ int counter;
+ int s;
+ short *dst = (short *)dest;
+
+ s = splhigh(); /* Erm, maybe not needed now */
+
+ if (len & 1)
+ len++;
+ if (src & 1) {
+ printf ( "EHDEBUG: Copying from odd address\n" );
+ src++;
+ }
+
+ /* Remote DMA to the DP83905 must be done with care. If we dont */
+ /* do it exactly right, it punishes us by locking the bus. */
+
+ eh_ensure_dma_ok (sc);
+
+ /* Set up the DMA */
+
+ SetReg ( EH_RSAR0, src & 0xff );
+ SetReg ( EH_RSAR1, (src>>8) & 0xff );
+ SetReg ( EH_RBCR0, len & 0xff );
+ SetReg ( EH_RBCR1, (len>>8) & 0xff );
+
+ /* Set the DMA running */
+ /* REMOTE_DMA ( COM_READ ); */ /* SetReg ( EH_COMMAND, 0x0a ); */
+ SetReg ( EH_COMMAND, COM_READ|COM_STA );
+
+ for ( counter=0; counter<len; counter+=2 )
+ *(dst++)=ReadShort ( sc->sc_reg + EH_DATA_PORT );
+
+ splx(s);
+
+ if ( eh_ensure_dma_competed ( sc, COM_READ ) )
+ return 0;
+
+ return len;
+}
+
+int
+eh_copyout(sc, src, dest, len)
+ struct eh_softc *sc;
+ char *src;
+ int dest;
+ int len;
+{
+ int counter;
+ int s;
+ short *sr = (short *)src;
+
+ if (len & 1)
+ len++;
+ if (dest & 1) {
+ printf ( "EHDEBUG: Copying to odd address\n" );
+ dest++;
+ }
+
+ s = splhigh(); /* Erm, maybe not needed now */
+
+ /* Remote DMA to the DP83905 must be done with care. If we dont */
+ /* do it exactly right, it punishes us by locking the bus. */
+
+ eh_ensure_dma_ok (sc);
+
+ /* Set up the DMA */
+
+ SetReg ( EH_RSAR0, dest & 0xff );
+ SetReg ( EH_RSAR1, (dest>>8) & 0xff );
+ SetReg ( EH_RBCR0, len & 0xff );
+ SetReg ( EH_RBCR1, (len>>8) & 0xff );
+
+ /* Set the DMA running */
+ /*REMOTE_DMA ( COM_WRITE );*/ /* SetReg ( EH_COMMAND, 0x0a ); */
+ SetReg ( EH_COMMAND, COM_WRITE|COM_STA );
+
+ for ( counter=0; counter<len; counter+=2 ) {
+ WriteShort ( sc->sc_reg + EH_DATA_PORT, *(sr) );
+ sr++;
+ }
+
+ splx(s);
+
+ if ( eh_ensure_dma_competed ( sc, COM_WRITE ) )
+ return 0;
+
+ return len;
+}
+
+#define ALLOCBLK(v,s) (v)=card_freestart; \
+ card_freestart+=((s)+0xff)&(~0xff)
+
+void
+ehinit(sc)
+ struct eh_softc *sc;
+{
+ int card_freestart;
+ int counter;
+
+ PAGE(0);
+
+ /* Lay out the cards ram */
+ card_freestart = sc->sc_physstart;
+
+ /* Allocate receive buffers */
+
+ ALLOCBLK ( sc->sc_rbs, (RXBUF_SIZE*NRXBUF) );
+ sc->sc_rbd = card_freestart;
+ sc->sc_nxtpkt = sc->sc_rbs + 0x100;
+
+ /* Allocate transmit buffers */
+ for ( counter=0; counter<NTXBUF; counter++ ) {
+ ALLOCBLK ( sc->sc_tbs[counter], TXBUF_SIZE );
+ }
+
+ if ( card_freestart > sc->sc_physend ) {
+ printf ( "eh: card short of ram %02x required %02x present\n",
+ card_freestart, sc->sc_physstart );
+ sc->sc_arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+ sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
+ return;
+ }
+
+ /*
+ * Bring the controller up
+ *
+ * The ordering here is critical. Dont change unless you know what
+ * you're doing
+ */
+
+ /* Reset the card */
+
+ SetReg ( EH_RESET, 0xff );
+ delay (50000);
+ SetReg ( EH_RESET, 0x00 );
+ delay (50000);
+
+ /* 1. Program the command register for page 0 */
+
+ SetReg ( EH_COMMAND, 0x21 );
+
+ /* 2. Initialize the Data configuration register */
+
+ SetReg ( EH_DCR, DCR_WTS|DCR_LS|(0<<5) );
+
+ /* 3. Clear RBCR if using remote DMA */
+
+ SetReg ( EH_RBCR0, 0 );
+ SetReg ( EH_RBCR1, 0 );
+
+ /* 4. Initialise RCR */
+
+ SetReg ( EH_RCR, 0x04 );
+
+ /* 5. Place the controller in loopback mode 1 or 2 TCR=02H or 04H */
+
+ SetReg ( EH_TCR, 0x02 );
+
+ /* 6. Initiliase Receive ring buffer BNDRY PSTART PSTOP */
+
+ SetReg ( EH_BNRY, sc->sc_rbs >> 8 );
+ SetReg ( EH_PSTART, sc->sc_rbs >> 8 );
+ SetReg ( EH_PSTOP, sc->sc_rbd >> 8 );
+
+ /* 7. Clear ISR */
+
+ SetReg ( EH_ISR, 0xff );
+
+ /* 8. Initialise IMR */
+
+ SetReg ( EH_IMR, ISR_PRX|ISR_PTX|ISR_RXE|ISR_TXE|ISR_OVW|ISR_CNT );
+
+ /* 9. Program command register for page 1 COM=0x61 */
+ /* Initialise PAR MAR and CURR */
+
+ PAGE(1);
+
+ SetReg ( EH_CURR, sc->sc_nxtpkt >> 8 );
+
+ for ( counter=0; counter<6; counter++ )
+ SetReg ( ((counter+1)<<2), sc->sc_arpcom.ac_enaddr[counter] );
+
+ /* Put controller into start mode COM = 0x22 */
+
+ SetReg ( EH_COMMAND, 0x22 );
+
+ /* Initialise the TCR */
+
+ SetReg ( EH_TCR, TCR_NORMALLOOP );
+
+ /* Interface is up */
+
+ sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING;
+ sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+
+ ehstart(&sc->sc_arpcom.ac_if);
+}
+
+int
+ehstop(sc)
+ struct eh_softc *sc;
+{
+ int s = splimp();
+ eh_stop_controller(sc);
+ SetReg(EH_DCR, DCR_LS|DCR_LAS);
+ splx(s);
+ return 0;
+}
+
+#define INTR_ACK(s) SetReg ( EH_ISR, s )
+
+/* In need of tidying */
+
+#undef MYTEST
+
+void
+eh_rint(sc)
+ struct eh_softc *sc;
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ struct mbuf *top, **mp, *m;
+ struct ether_header eh;
+ struct eh_rxhdr hdr;
+ int status = GetReg(EH_RSR);
+ int rxstatus=0;
+ int totlen, len;
+ int ptr;
+ int rbend;
+ int thispacket;
+ int bnry;
+
+#ifdef MYTEST
+ int old;
+#endif
+
+ /* Get the end of the ring buffer */
+
+ PAGE(1);
+ rbend = GetReg ( EH_CURR ) << 8;
+ PAGE(0);
+
+ /* If we have something to receive then receive it */
+
+ if ( status&RSR_PRX ) {
+ /* Remove all the packets from the ring buffer */
+ for ( ptr=sc->sc_nxtpkt; ptr!=rbend ; ptr = sc->sc_nxtpkt ) {
+
+ thispacket = ptr;
+ /* Copy the ether h receive header */
+
+ if ( eh_copyring ( sc, ptr, (char *)&hdr, 4 ) != 4 ) {
+ printf ( "eh: Failed copying in header\n" );
+ printf ( "eh: thispacket %02x\n", thispacket );
+ ehinit (sc);
+ return;
+ }
+
+ rxstatus = hdr.rx_status;
+ totlen = (hdr.rx_rbc1<<8) + hdr.rx_rbc0;
+
+ ptr+=4;
+
+ /* Check the packet's status */
+ if ( hdr.rx_status&(RSR_CRC|RSR_FAE|RSR_FO|RSR_MPA) ) {
+ printf ( "eh: intact packet is corrupt %02x %04x\n",
+ hdr.rx_status, ptr );
+ }
+
+ if (((hdr.rx_nxtpkt<<8)>sc->sc_rbd) || ((hdr.rx_nxtpkt<<8)<sc->sc_rbs)) {
+ printf ( "eh: ring buffer empty %04x %04x\n",
+ hdr.rx_nxtpkt, ptr );
+ ehinit (sc);
+ return;
+ }
+
+ if (0)
+ printf ( "pulling packet at %08x, next at %08x\n", thispacket, sc->sc_nxtpkt );
+
+ if ( totlen>ETHER_MAX_LEN ) {
+ printf ( "eh: giant packet received %04x\n", totlen );
+ totlen = ETHER_MAX_LEN;
+ }
+
+ /* Copy the ether header */
+
+ if ((eh_copyring ( sc, ptr, (char *)&eh, sizeof (eh)))!=sizeof(eh)) {
+ printf ( "eh: Failed copying in ethenet header\n" );
+ return;
+ }
+ ptr+=sizeof(eh);
+ totlen-=sizeof(eh);
+
+ /* Copy the packet into mbufs */
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if ( m==0 )
+ return;
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = totlen;
+ len = MHLEN;
+ top = 0;
+ mp = ⊤
+
+ while ( totlen > 0 ) {
+ if (top) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if ( m==0 ) {
+ m_freem(top);
+ goto skip;
+ }
+ len = MLEN;
+ }
+ if ( totlen >= MINCLSIZE ) {
+ MCLGET(m, M_DONTWAIT);
+ if (m->m_flags & M_EXT)
+ len = MCLBYTES;
+ }
+ m->m_len = len = min ( totlen, len );
+
+ if ((eh_copyring ( sc, ptr, mtod(m, caddr_t), len))!=len)
+ printf ( "eh: failed copying in buffer %d\n", len );
+
+ ptr += len;
+ totlen -= len;
+ *mp = m;
+ mp = &m->m_next;
+ }
+
+ m = top;
+ ifp->if_ipackets++;
+ ether_input(ifp, &eh, m );
+skip:
+
+ /* Ok, I'm done with this packet */
+
+ sc->sc_nxtpkt = hdr.rx_nxtpkt << 8;
+
+ /* Set the boundary pointer on the ring buffer */
+
+ bnry = (sc->sc_nxtpkt>>8)-1;
+ if ( bnry < (sc->sc_rbs>>8) )
+ bnry = (sc->sc_rbd>>8)-1;
+ SetReg ( EH_BNRY, bnry );
+
+ PAGE(1);
+ rbend = GetReg ( EH_CURR ) << 8;
+ PAGE(0);
+ }
+ }
+}
+
+int
+ehintr(arg)
+ void *arg;
+{
+ struct eh_softc *sc = arg;
+ register int isr = GetReg ( EH_ISR ); /* Is char of int faster ? */
+ register int times = 0;
+
+ PAGE(0);
+
+ if ( isr & ISR_RXE ) {
+ int status = GetReg ( EH_RSR );
+ PRINTF ( "eh: Receive Error:" );
+ if ( status&RSR_PRX )
+ PRINTF ( " packet received intact (this should happen)" );
+ if ( status&RSR_CRC )
+ PRINTF ( " crc error" );
+ if ( status&RSR_FAE )
+ PRINTF ( " frame alignment error" );
+ if ( status&RSR_FO )
+ PRINTF ( " fifo overrun" );
+ if ( status&RSR_MPA )
+ PRINTF ( " missed packet" );
+ if ( status&RSR_DIS )
+ PRINTF ( " receiver disabled" );
+ printf ( "\n" );
+ INTR_ACK ( ISR_RXE );
+ ehinit (sc);
+ return 0;
+ }
+
+ if ( isr & ISR_PRX ) {
+ eh_rint (sc);
+ INTR_ACK ( ISR_PRX );
+ }
+
+ if ( isr & ISR_PTX ) {
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ int status;
+ INTR_ACK ( ISR_PTX );
+ ifp->if_timer=0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ status = GetReg ( EH_TSR );
+
+ if ( status&TSR_PTX )
+ ifp->if_opackets++;
+
+ if ( status&TSR_COL )
+ ifp->if_collisions+=GetReg(EH_NCR);
+
+ if ( status&TSR_ABT )
+ PRINTF ( "eh: too many collisions\n" );
+
+ if ( status&TSR_CRS )
+ PRINTF ( "eh: no carrier\n" );
+
+ if ( status&TSR_CDH )
+ PRINTF ( "eh: tranceiver failure, no heartbeat \n" );
+
+ if ( status&TSR_OWC )
+ PRINTF ( "eh: out of window \n" );
+
+ if ( status&(TSR_ABT|TSR_CRS|TSR_FU|TSR_CDH|TSR_OWC) )
+ ifp->if_oerrors++;
+
+ ehstart(ifp);
+ }
+
+ if ( isr & ISR_TXE ) {
+ INTR_ACK ( ISR_TXE );
+ PRINTF ( "ehintr: Transmit error\n" );
+ }
+
+ if ( isr & ISR_OVW ) {
+ INTR_ACK ( ISR_OVW );
+ PRINTF ( "ehintr: Counter overflow\n" );
+ }
+
+ if ( isr & ISR_RST ) {
+ INTR_ACK ( ISR_RST );
+ PRINTF ( "ehintr: Reset status\n" );
+ }
+
+ if ((times++)>16) {
+ PRINTF ( "eh: possible interrupt jammed on." );
+ SetReg ( EH_IMR, 0x0 );
+ }
+
+ /* Dont do this for the mo until I'm sure.
+
+ isr = GetReg ( EH_ISR );
+
+ if ( (isr&GetReg(EH_IMR))!=0 )
+ goto more;
+ */
+
+ if ( (isr&GetReg(EH_IMR))!=0 )
+ printf ( "eh: Interrupt not serviced\n" );
+
+ return 0;
+}
+
+/****************************************************************************/
+/* Auxilary routines ********************************************************/
+/****************************************************************************/
+
+void
+eh_shutdown(arg)
+ void *arg;
+{
+ struct eh_softc *sc = (struct eh_softc *)arg;
+
+ /* On shutdown put us in loopback */
+
+ SetReg(EH_DCR, DCR_LAS);
+ SetReg(EH_TCR, TCR_NICMOD);
+
+ /* and program remote dma so riscos doesnt lock */
+
+ SetReg(EH_RSAR0, 0);
+ SetReg(EH_RSAR1, 1);
+ SetReg(EH_RBCR0, 0);
+ SetReg(EH_RBCR1, 1);
+}
--- /dev/null
+/* $NetBSD: if_ehreg.h,v 1.2 1996/03/08 16:24:51 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * if_ehreg.h
+ *
+ * Ether H register definitions.
+ */
+
+#define EH_RESET (0x18<<2)
+
+#define EH_DATA_PORT (0x10<<2)
+
+/* Special registers */
+
+#define EH_CONFIGA (0x0a<<2)
+
+/* Page 0 read registers */
+
+#define EH_COMMAND (0x00<<2)
+#define EH_CLAD0 (0x01<<2)
+#define EH_CLDA1 (0x02<<2)
+#define EH_BNRY (0x03<<2)
+#define EH_TSR (0x04<<2)
+#define EH_NCR (0x05<<2)
+#define EH_FIFO (0x06<<2)
+#define EH_ISR (0x07<<2)
+#define EH_CRDA0 (0x08<<2)
+#define EH_CRDA1 (0x09<<2)
+#define EH_RSR (0x0c<<2)
+
+/* Page 0 write registers */
+
+#define EH_PSTART (0x01<<2)
+#define EH_PSTOP (0x02<<2)
+#define EH_TPSR (0x04<<2)
+#define EH_TBCR0 (0x05<<2)
+#define EH_TBCR1 (0x06<<2)
+#define EH_RSAR0 (0x08<<2)
+#define EH_RSAR1 (0x09<<2)
+#define EH_RBCR0 (0x0a<<2)
+#define EH_RBCR1 (0x0b<<2)
+#define EH_RCR (0x0c<<2)
+#define EH_TCR (0x0d<<2)
+#define EH_DCR (0x0e<<2)
+#define EH_IMR (0x0f<<2)
+
+/* Page 1 write registers */
+
+#define EH_CURR (0x07<<2)
+
+/* Command bits */
+
+#define COM_STP (0x01)
+#define COM_STA (0x02)
+#define COM_TXP (0x04)
+#define COM_MASK_PAGE (0x3f)
+#define COM_READ (0x08)
+#define COM_WRITE (0x10)
+#define COM_SEND (0x18)
+#define COM_ABORT (0x20)
+#define COM_MASK_DMA (0xc7)
+#define COM_DMA_MASK (0x38)
+
+/* DCR bits */
+
+#define DCR_WTS (0x01)
+#define DCR_BOS (0x02)
+#define DCR_LAS (0x04)
+#define DCR_LS (0x08)
+#define DCR_ARM (0x10)
+
+/* TSR bits */
+
+#define TSR_PTX (0x01)
+#define TSR_COL (0x04)
+#define TSR_ABT (0x08)
+#define TSR_CRS (0x10)
+#define TSR_FU (0x20)
+#define TSR_CDH (0x40)
+#define TSR_OWC (0x80)
+#define TSR_DONE ((TSR_PTX)|(TSR_ABT))
+
+/* TCR bits */
+
+#define TCR_CRC (0x01)
+#define TCR_NORMALLOOP (0x00)
+#define TCR_NICMOD (0x02)
+#define TCR_ENDECMOD (0x04)
+#define TCR_EXTLOOP (0x06)
+#define TCR_ATD (0x08)
+#define TCR_OFST (0x10)
+
+/* ISR bits */
+
+#define ISR_PRX (0x01)
+#define ISR_PTX (0x02)
+#define ISR_RXE (0x04)
+#define ISR_TXE (0x08)
+#define ISR_OVW (0x10)
+#define ISR_CNT (0x20)
+#define ISR_RDC (0x40)
+#define ISR_RST (0x80)
+
+/* RSR bits */
+
+#define RSR_PRX (0x01)
+#define RSR_CRC (0x02)
+#define RSR_FAE (0x04)
+#define RSR_FO (0x08)
+#define RSR_MPA (0x10)
+#define RSR_PHY (0x20)
+#define RSR_DIS (0x40)
+#define RSR_DFR (0x80)
+
+struct eh_rxhdr {
+ char rx_status;
+ char rx_nxtpkt;
+ char rx_rbc0;
+ char rx_rbc1;
+};
+
--- /dev/null
+/* $NetBSD: if_ie.c,v 1.5 1996/03/27 21:49:36 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson.
+ * All rights reserved.
+ *
+ * This driver is a major hash up of src/sys/dev/isa/if_ie.c and
+ * src/sys/arch/arm32/podule/kgdb_ie.c Please refer to copyright
+ * notices from them too.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * if_ie.c
+ *
+ * Ether 1 podule driver
+ *
+ * Created : 26/06/95
+ */
+
+/*
+ * This driver is at it's last beta release. It should not cause
+ * any problems (Touch wood)
+ *
+ * If it passes field tests again. This will constitute the realse
+ * version.
+ */
+
+#define IGNORE_ETHER1_IDROM_CHECKSUM
+
+/* Standard podule includes */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+
+/* Include for interface to the net and ethernet subsystems */
+
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+/* Import our data structres */
+
+#include "if_iereg.h"
+
+/* BPF support */
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+/* Some useful defines and macros */
+
+#define MY_MANUFACTURER 0x00
+#define MY_PODULE 0x03
+#define PODULE_IRQ_PENDING (1)
+#define NFRAMES (16) /* number of frame to allow for receive */
+#define NRXBUF (48) /* number of receive buffers to allocate */
+#define IE_RXBUF_SIZE (256) /* receive buf size */
+#define NTXBUF (2) /* number of transmit buffers to allocate */
+#define IE_TXBUF_SIZE (1522) /* size of tx buffer */
+
+#define ETHER_MIN_LEN (64)
+#define ETHER_MAX_LEN (1518)
+
+#define PWriteShort(a,b) WriteWord(a,(b)<<16|(b))
+
+#define offsetof(type, member) (((size_t)&((type *)0)->member)<<1)
+
+/* Some data structres local to this file */
+
+struct ie_softc {
+ struct device sc_dev;
+ int sc_podule_number;
+ podule_t *sc_podule;
+ irqhandler_t sc_ih;
+ int sc_iobase;
+ int sc_fastbase;
+ int sc_rom;
+ int sc_ram;
+ int sc_control;
+ struct arpcom sc_arpcom;
+ int promisc;
+ int sc_irqmode;
+
+ u_long rframes[NFRAMES];
+ u_long rbuffs[NRXBUF];
+ u_long cbuffs[NRXBUF];
+ int rfhead, rftail, rbhead, rbtail;
+
+ u_long xmit_cmds[NTXBUF];
+ u_long xmit_buffs[NTXBUF];
+ u_long xmit_cbuffs[NTXBUF];
+ int xmit_count;
+ int xmit_free;
+ int xchead;
+ int xctail;
+};
+
+/* Function and data prototypes */
+
+static void host2ie ( struct ie_softc *sc, void *src, u_long dest, int size );
+static void ie2host ( struct ie_softc *sc, u_long src, void *dest, int size );
+static void iezero ( struct ie_softc *sc, u_long p, int size );
+void iereset ( struct ie_softc *sc );
+void iewatchdog ( int unit );
+int ieioctl ( struct ifnet *ifp, u_long cmd, caddr_t data );
+void iestart ( struct ifnet *ifp );
+int iestop ( struct ie_softc *sc );
+int ieinit ( struct ie_softc *sc );
+int ieintr ( void *arg );
+void ietint ( struct ie_softc *sc );
+
+/* A whopper of a function */
+static int command_and_wait ( struct ie_softc *sc, u_short cmd,
+ struct ie_sys_ctl_block *pscb,
+ void *pcmd, int ocmd, int scmd, int mask );
+
+struct cfattach ie_ca;
+
+struct cfdriver ie_cd;
+
+/* Let's go! */
+
+/*
+ * Clear all pending interrupts from the i82586 chip
+ */
+
+static __inline void ie_cli ( struct ie_softc *sc )
+{
+ WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_CLI );
+}
+
+/*
+ * Cool down the i82586, like its namesake, it gets very hot
+ */
+
+static __inline void ie_cooldown ( int temperature )
+{
+}
+
+/*
+ * Wake the i82586 chip up and get it to do something
+ */
+
+static __inline void ieattn ( struct ie_softc *sc )
+{
+ WriteByte ( sc->sc_control + (IE_CONTROL<<2), IE_CONT_ATTN );
+}
+
+/*
+ * Set the podule page register to bring a given address into view
+ */
+
+static __inline void setpage ( struct ie_softc *sc, u_long off )
+{
+ WriteByte ( sc->sc_control + (IE_PAGE<<2), IE_COFF2PAGE(off) );
+}
+
+/*
+ * Ack the i82586
+ */
+
+static void ie_ack ( struct ie_softc *sc, u_short mask )
+{
+ u_short stat;
+ int i;
+ setpage(sc, IE_IBASE + IE_SCB_OFF );
+
+ stat = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+ (offsetof(struct ie_sys_ctl_block, ie_status)) );
+
+ PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+ (offsetof(struct ie_sys_ctl_block, ie_command)),
+ stat & mask );
+
+ ieattn(sc);
+
+ for ( i=4000; --i>=0; ) {
+ if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+ (offsetof(struct ie_sys_ctl_block, ie_command))) )
+ break;
+ delay(100);
+ }
+
+ if ( i<=0 )
+ {
+ printf ( "ie: command timed out\n" );
+ }
+ ie_cli(sc);
+}
+
+/*
+ * This routine does the checksumming for the idrom
+ */
+
+static u_long crc32(u_char *p, int l)
+{
+ u_long crc=-1;
+ int i, b;
+ while ( --l >= 0 ) {
+ b = *p++;
+ for ( i=8; --i >= 0; b>>=1 )
+ if ((b&1)^(crc>>31))
+ crc=(crc<<1)^0x4c11db7;
+ else
+ crc<<=1;
+ }
+ return crc;
+}
+
+/*
+ * Probe for the ether1 card. return 1 on success 0 on failure
+ */
+
+int ieprobe ( struct device *parent, void *match, void *aux )
+{
+ struct ie_softc *sc = (void *)match;
+ struct podule_attach_args *pa = (void *)aux;
+ int podule, i;
+ char idrom[32];
+ u_char *hwaddr = sc->sc_arpcom.ac_enaddr;
+
+ /* Get the nice podulebus podule to find my podule in its table */
+ podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+ if (podule == -1)
+ return(0);
+
+ /* Index some podule areas */
+ sc->sc_iobase = podules[podule].sync_base; /* OBSOLETE */
+ sc->sc_fastbase = podules[podule].fast_base; /* OBSOLETE */
+ sc->sc_rom = podules[podule].sync_base;
+ sc->sc_control = podules[podule].fast_base;
+ sc->sc_ram = podules[podule].fast_base + IE_MEMOFF;
+
+ /* Set the page mask to something know and neutral */
+ setpage(sc, IE_SCB_OFF);
+
+ /* Fetch the first part of the idrom */
+ for ( i=0; i<16; i++ ) {
+ idrom[i] = ReadByte ( sc->sc_rom + (i<<2) );
+ };
+
+ /* Verify the podulebus probe incase RiscOS lied */
+ if ( ReadByte ( sc->sc_rom + (3<<2) ) != 0x03 ) {
+ panic ( "ie: Ether1 ROM probablly broken. ECID corrupt" );
+ return 0;
+ }
+
+ /* Reset the 82586 */
+ WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_RESET );
+ delay(1000);
+ WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), 0 );
+ delay(10000);
+
+ /* Clear pending interrupts */
+ ie_cli (sc);
+
+ /* Setup SCP */
+ {
+ struct ie_sys_conf_ptr scp;
+ bzero (&scp, sizeof(scp) );
+ scp.ie_iscp_ptr = (caddr_t)IE_ISCP_ADDR;
+ host2ie(sc, &scp, IE_SCP_ADDR, sizeof (scp) );
+ }
+
+ /* Setup ISCP */
+ {
+ struct ie_int_sys_conf_ptr iscp;
+ bzero ( &iscp, sizeof(iscp) );
+ iscp.ie_busy = 1;
+ iscp.ie_base = (caddr_t)IE_IBASE;
+ iscp.ie_scb_offset = IE_SCB_OFF;
+ host2ie(sc, &iscp, IE_ISCP_ADDR, sizeof(iscp) );
+ }
+
+ /* Initialise the control block */
+ iezero ( sc, IE_IBASE + IE_SCB_OFF, sizeof(struct ie_sys_ctl_block) );
+ ieattn(sc);
+
+ /* Wait for not busy */
+ setpage ( sc, IE_ISCP_ADDR );
+ for ( i=10000; --i>=0; ) {
+ if ( !ReadShort( sc->sc_ram + IE_COFF2POFF(IE_ISCP_ADDR) +
+ ( offsetof(struct ie_int_sys_conf_ptr, ie_busy)) ) )
+ break;
+ delay (10);
+ }
+
+ /* If the busy didn't go low, the i82586 is broken or too slow */
+ if ( i<=0 )
+ {
+ printf ( "ie: ether1 chipset didn't respond\n" );
+ return 0;
+ }
+
+ /* Ensure that the podule sends interrupts */
+ for ( i=1000; --i>=0 ; ) {
+ if ( ReadByte(sc->sc_rom + 0) & PODULE_IRQ_PENDING )
+ break;
+ delay (10);
+ }
+
+ /* If we didn't see the interrupt then the IRQ line is broken */
+ if ( i<=0 )
+ {
+ printf ( "ie: interrupt from chipset didn't reach host\n" );
+ return 0;
+ }
+
+ /* Ack our little test operation */
+ ie_ack(sc,IE_ST_WHENCE);
+ ie_cli (sc);
+
+ /* Get second part of idrom */
+ for ( i=16; i<32; i++ ) {
+ idrom[i] = ReadByte ( sc->sc_rom + (i<<2) );
+ };
+
+ /* This checksum always fails. For some reason the first 16 */
+ /* bytes are duplicated in the second 16 bytes, the checksum */
+ /* should be at location 28 it is clearly not */
+
+ /* It is possible that this ether1 card is buggered */
+
+#ifndef IGNORE_ETHER1_IDROM_CHECKSUM
+ if ( crc32(idrom,28) != *(u_long *)(idrom+28) )
+ {
+ printf ( "ie: ether1 idrom failed checksum %08x!=%08x\n",
+ crc32(idrom,28), *(u_long *)(idrom+28));
+ for ( i=0; i<32; i+=8 ) {
+ printf ( "IDROM: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ idrom[0+i], idrom[1+i], idrom[2+i], idrom[3+i],
+ idrom[4+i], idrom[5+i], idrom[6+i], idrom[7+i] );
+ }
+ printf ( "ie: I'll ignore this fact for now!\n" );
+ }
+#endif
+
+ /* Get our ethernet address. Do explicit copy */
+ for ( i=0; i<ETHER_ADDR_LEN; i++ )
+ hwaddr[i] = idrom[9+i];
+
+ /* Tell the podule system about our successful probe */
+ pa->pa_podule_number = podule;
+ pa->pa_podule = &podules[podule];
+
+ return(1);
+}
+
+/*
+ * Attach our driver to the interfaces it uses
+ */
+
+void ieattach ( struct device *parent, struct device *self, void *aux )
+{
+ struct ie_softc *sc = (void *)self;
+ struct podule_attach_args *pa = (void *)aux;
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+
+ /* Check a few things about the attach args */
+ sc->sc_podule_number = pa->pa_podule_number;
+ if (sc->sc_podule_number == -1)
+ panic("Podule has disappeared !");
+
+ sc->sc_podule = &podules[sc->sc_podule_number];
+ podules[sc->sc_podule_number].attached = 1;
+
+ /* Fill in my application form to attach to the inet system */
+
+ ifp->if_unit = sc->sc_dev.dv_unit;
+ ifp->if_name = ie_cd.cd_name;
+ ifp->if_start = iestart;
+ ifp->if_ioctl = ieioctl;
+ ifp->if_watchdog = iewatchdog;
+ ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
+
+ /* Signed, dated then sent */
+ if_attach (ifp);
+ ether_ifattach(ifp);
+
+ /* "Hmm," said nuts, "what if the attach fails" */
+
+ /* Write some pretty things on the annoucement line */
+ printf ( " %s using %dk card ram",
+ ether_sprintf(sc->sc_arpcom.ac_enaddr),
+ ((NRXBUF*IE_RXBUF_SIZE)+(NTXBUF*IE_TXBUF_SIZE))/1024 );
+
+#if NBPFILTER > 0
+ printf ( " BPF" );
+ bpfattach ( &ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+
+ sc->sc_ih.ih_func = ieintr;
+ sc->sc_ih.ih_arg = sc;
+ sc->sc_ih.ih_level = IPL_NET;
+ sc->sc_ih.ih_name = "net: ie";
+
+ if (irq_claim(IRQ_PODULE, &sc->sc_ih))
+ {
+ sc->sc_irqmode = 0;
+ printf ( " POLLED" );
+ panic("Cannot install IRQ handler\n");
+ }
+ else
+ {
+ sc->sc_irqmode = 1;
+ printf ( " IRQ" );
+ }
+
+ printf ( "\n" );
+}
+
+
+/*
+ * Our cfdriver structure for the autoconfig system to chew on
+ */
+
+struct cfattach ie_ca = {
+ sizeof(struct ie_softc), ieprobe, ieattach
+};
+
+struct cfdriver ie_cd = {
+ NULL, "ie", DV_IFNET
+};
+
+/*
+ * Oh no!! Where's my shorts!!! I'm sure I put them on this morning
+ */
+
+void PWriteShorts ( char *src, char *dest, int cnt )
+{
+ for ( cnt/=2; --cnt>=0; ) {
+ PWriteShort ( dest, *(u_short *)src );
+ src+=2;
+ dest+=4;
+ }
+}
+
+void ReadShorts ( char *src, char *dest, int cnt )
+{
+ for ( cnt/=2; --cnt>=0; ) {
+ *(u_short *)dest = ReadShort ( src );
+ src+=4;
+ dest+=2;
+ }
+}
+
+/*
+ * A bcopy or memcpy to adapter ram. It handles the page register for you
+ * so you dont have to worry about the ram windowing
+ */
+
+static void host2ie ( struct ie_softc *sc, void *src, u_long dest, int size )
+{
+ int cnt;
+
+ if (size&1)
+ panic ( "host2ie" );
+
+ while ( size>0 ) {
+ cnt = IE_PAGESIZE - dest % IE_PAGESIZE;
+ if ( cnt > size )
+ cnt = size;
+ setpage ( sc, dest );
+ PWriteShorts ( src, (char *)sc->sc_ram + IE_COFF2POFF(dest), cnt );
+ src+=cnt;
+ dest+=cnt;
+ size-=cnt;
+ }
+}
+
+static void ie2host ( struct ie_softc *sc, u_long src, void *dest, int size )
+{
+ int cnt;
+
+ if (size&1)
+ panic ( "ie2host" );
+
+ while ( size>0 ) {
+ cnt = IE_PAGESIZE - src % IE_PAGESIZE;
+ if ( cnt > size )
+ cnt = size;
+ setpage ( sc, src );
+ ReadShorts ( (char *)sc->sc_ram + IE_COFF2POFF(src), dest, cnt );
+ src+=cnt;
+ dest+=cnt;
+ size-=cnt;
+ }
+}
+
+/*
+ * Like a bzero or memset 0 for adapter memory. It handles the page
+ * register so you dont have to worry about it
+ */
+
+static void iezero ( struct ie_softc *sc, u_long p, int size )
+{
+ int cnt;
+ while ( size > 0 ) {
+ cnt = IE_PAGESIZE - p % IE_PAGESIZE;
+ if ( cnt>size )
+ cnt=size;
+ setpage(sc, p);
+ bzero((char *)sc->sc_ram + IE_COFF2POFF(p), 2*cnt );
+ p += cnt;
+ size -= cnt;
+ }
+}
+
+/*
+ * I/O Control interface to the kernel, entry point here
+ */
+
+int ieioctl ( struct ifnet *ifp, u_long cmd, caddr_t data )
+{
+ struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
+ struct ifaddr *ifa = (struct ifaddr *)data;
+/* struct ifreq *ifr = (struct ifreq *)data;*/
+ int s;
+ int error=0;
+
+ s=splimp();
+
+ switch ( cmd )
+ {
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ switch ( ifa->ifa_addr->sa_family ) {
+#ifdef INET
+ case AF_INET:
+ ieinit(sc);
+ arp_ifinit(&sc->sc_arpcom, ifa );
+ break;
+#endif
+ default:
+ ieinit(sc);
+ break;
+ }
+ break;
+
+#define IZSET(a,b) ((a->if_flags&b)!=0)
+#define IZCLR(a,b) ((a->if_flags&b)==0)
+#define DOSET(a,b) (a->if_flags|=b)
+#define DOCLR(a,b) (a->if_flags&=~b)
+
+ case SIOCSIFFLAGS:
+ sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI );
+
+ if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) )
+ {
+ /* Interface was marked down and its running so stop it */
+ iestop(sc);
+ DOCLR(ifp,IFF_RUNNING);
+ }
+ else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) )
+ {
+ /* Just marked up and we're not running so start it */
+ ieinit(sc);
+ }
+ else
+ {
+ /* else reset to invoke changes in other registers */
+ iestop(sc);
+ ieinit(sc);
+ }
+
+ default:
+ error = EINVAL;
+ }
+ (void)splx(s);
+ return error;
+}
+
+/*
+ * Reset the card. Completely.
+ */
+
+void iereset( struct ie_softc *sc )
+{
+ struct ie_sys_ctl_block scb;
+ int s = splimp();
+
+ iestop(sc);
+
+ ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+
+ if ( command_and_wait(sc, IE_RU_ABORT|IE_CU_ABORT, 0, 0, 0, 0, 0) )
+ printf ( "ie0: abort commands timed out\n" );
+
+ if ( command_and_wait(sc, IE_RU_DISABLE|IE_CU_STOP, 0, 0, 0, 0, 0) )
+ printf ( "ie0: abort commands timed out\n" );
+
+ ieinit(sc);
+
+ (void)splx(s);
+}
+
+/*
+ * Watchdog entry point. This is the entry for the kernel to call us
+ */
+
+void iewatchdog ( int unit )
+{
+ struct ie_softc *sc = ie_cd.cd_devs[unit];
+
+ /* WOOF WOOF */
+ log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname );
+ ++sc->sc_arpcom.ac_if.if_oerrors;
+ iereset(sc);
+}
+
+/*
+ * Start the time-domain-refloctometer running
+ */
+
+static void run_tdr ( struct ie_softc *sc )
+{
+ struct ie_sys_ctl_block scb;
+ u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb;
+ struct ie_tdr_cmd cmd;
+ int result;
+
+ bzero ( &scb, sizeof(scb) );
+ bzero ( &cmd, sizeof(cmd) );
+
+ cmd.com.ie_cmd_status = 0;
+ cmd.com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
+ cmd.com.ie_cmd_link = 0xffff;
+ cmd.ie_tdr_time = 0;
+
+ scb.ie_command_list = (u_short)ptr;
+
+ result=0;
+ if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd,
+ IE_STAT_COMPL) )
+ {
+ result = 0x10000;
+ }
+ else if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
+ {
+ result = 0x10000;
+ }
+
+ if ( result==0 )
+ result = cmd.ie_tdr_time;
+
+ ie_ack ( sc, IE_ST_WHENCE );
+
+ if (result & IE_TDR_SUCCESS )
+ return;
+
+ /* Very messy. I'll tidy it later */
+
+ if ( result & 0x10000 )
+ {
+ printf ( "ie: TDR command failed\n" );
+ }
+ else if ( result & IE_TDR_XCVR )
+ {
+ printf ( "ie: tranceiver problem. Is it plugged in?\n" );
+ }
+ else if ( result & IE_TDR_OPEN )
+ {
+ if ((result & IE_TDR_TIME)>0)
+ printf ( "ie: TDR detected an open %d clocks away.\n",
+ result & IE_TDR_TIME );
+ }
+ else if ( result & IE_TDR_SHORT )
+ {
+ if ((result & IE_TDR_TIME)>0)
+ printf ( "ie: TDR detected a short %d clock away.\n",
+ result & IE_TDR_TIME );
+ }
+ else
+ {
+ printf ( "ie: TDR returned unknown status %x\n", result );
+ }
+}
+
+u_long setup_rfa ( struct ie_softc *sc, u_long ptr )
+{
+ int i;
+ {
+ /* Receive frame descriptors */
+ struct ie_recv_frame_desc rfd;
+ bzero( &rfd, sizeof rfd );
+ for ( i=0; i<NFRAMES; i++ )
+ {
+ sc->rframes[i] = ptr;
+ rfd.ie_fd_next = ptr + sizeof rfd;
+ host2ie(sc, (char *)&rfd, ptr, sizeof rfd);
+ ptr += sizeof rfd;
+ }
+ rfd.ie_fd_next = sc->rframes[0];
+ rfd.ie_fd_last |= IE_FD_LAST;
+ host2ie(sc, (char *)&rfd, sc->rframes[NFRAMES-1], sizeof rfd );
+
+ ie2host(sc, sc->rframes[0], (char *)&rfd, sizeof rfd );
+ rfd.ie_fd_buf_desc = (u_short) ptr;
+ host2ie(sc, (char *)&rfd, sc->rframes[0], sizeof rfd );
+ }
+
+ {
+ /* Receive frame descriptors */
+ struct ie_recv_buf_desc rbd;
+ bzero(&rbd, sizeof rbd);
+ for ( i=0; i<NRXBUF; i++ )
+ {
+ sc->rbuffs[i] = ptr;
+ rbd.ie_rbd_length = IE_RXBUF_SIZE;
+ rbd.ie_rbd_buffer = (caddr_t)(ptr + sizeof rbd);
+ rbd.ie_rbd_next = (u_short)(ptr + sizeof rbd + IE_RXBUF_SIZE);
+ host2ie(sc, &rbd, ptr, sizeof rbd);
+ ptr+=sizeof rbd;
+
+ sc->cbuffs[i] = ptr;
+ ptr+=IE_RXBUF_SIZE;
+ }
+ rbd.ie_rbd_next = sc->rbuffs[0];
+ rbd.ie_rbd_length |= IE_RBD_LAST;
+ host2ie(sc, &rbd, sc->rbuffs[NRXBUF-1], sizeof rbd);
+ }
+
+ sc->rfhead = 0;
+ sc->rftail = NFRAMES-1;
+ sc->rbhead = 0;
+ sc->rbtail = NRXBUF-1;
+
+ {
+ struct ie_sys_ctl_block scb;
+ bzero ( &scb, sizeof scb );
+ scb.ie_recv_list = (u_short)sc->rframes[0];
+ host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb );
+ }
+ return ptr;
+}
+
+static void start_receiver ( struct ie_softc *sc )
+{
+ struct ie_sys_ctl_block scb;
+ ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+ scb.ie_recv_list = (u_short)sc->rframes[0];
+ command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0);
+ ie_ack(sc, IE_ST_WHENCE );
+}
+
+/*
+ * Take our configuration and update all the other data structures that
+ * require information from the driver.
+ *
+ * CALL AT SPLIMP OR HIGHER
+ */
+
+int ieinit ( struct ie_softc *sc )
+{
+ struct ie_sys_ctl_block scb;
+ struct ie_config_cmd cmd;
+ struct ie_iasetup_cmd iasetup_cmd;
+ u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb;
+ int n;
+
+ bzero ( &scb, sizeof(scb) );
+
+ /* Send the configure command */
+
+ cmd.com.ie_cmd_status = 0;
+ cmd.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
+ cmd.com.ie_cmd_link = 0xffff;
+
+ cmd.ie_config_count = 0x0c;
+ cmd.ie_fifo = 8;
+ cmd.ie_save_bad = 0x40;
+ cmd.ie_addr_len = 0x2e;
+ cmd.ie_priority = 0;
+ cmd.ie_ifs = 0x60;
+ cmd.ie_slot_low = 0;
+ cmd.ie_slot_high = 0xf2;
+ cmd.ie_promisc = 0; /* Hey nuts, look at this! */
+ cmd.ie_crs_cdt = 0;
+ cmd.ie_min_len = 64;
+ cmd.ie_junk = 0xff;
+
+ scb.ie_command_list = (u_short)ptr;
+
+ if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd,
+ IE_STAT_COMPL) )
+ {
+ printf ( "%s: command failed: timeout\n", sc->sc_dev.dv_xname );
+ return 0;
+ }
+
+ if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
+ {
+ printf ( "%s: command failed: !IE_STAT_OK\n", sc->sc_dev.dv_xname );
+ return 0;
+ }
+
+ /* Individual address setup command */
+
+ iasetup_cmd.com.ie_cmd_status = 0;
+ iasetup_cmd.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
+ iasetup_cmd.com.ie_cmd_link = 0xffff;
+
+ bcopy ( sc->sc_arpcom.ac_enaddr, (caddr_t) &iasetup_cmd.ie_address,
+ sizeof (iasetup_cmd.ie_address) );
+
+ if ( command_and_wait(sc, IE_CU_START, &scb, &iasetup_cmd, ptr, sizeof cmd,
+ IE_STAT_COMPL) )
+ {
+ printf ( "%s: iasetup failed : timeout\n", sc->sc_dev.dv_xname );
+ return 0;
+ }
+
+ if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
+ {
+ printf ( "%s: iasetup failed : !IE_STAT_OK\n", sc->sc_dev.dv_xname );
+ return 0;
+ }
+
+ ie_ack ( sc, IE_ST_WHENCE );
+
+ /* Run the time-domain refloctometer */
+ run_tdr ( sc );
+
+ ie_ack ( sc, IE_ST_WHENCE );
+
+ /* meminit */
+ ptr = setup_rfa(sc, ptr);
+
+ sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING;
+ sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+
+ /* Setup transmit buffers */
+
+ for ( n=0; n<NTXBUF; n++ ) {
+ sc->xmit_cmds[n] = ptr;
+ iezero(sc, ptr, sizeof(struct ie_xmit_cmd) );
+ ptr += sizeof(struct ie_xmit_cmd);
+
+ sc->xmit_buffs[n] = ptr;
+ iezero(sc, ptr, sizeof(struct ie_xmit_buf));
+ ptr += sizeof(struct ie_xmit_buf);
+ }
+
+ for ( n=0; n<NTXBUF; n++ ) {
+ sc->xmit_cbuffs[n] = ptr;
+ ptr += IE_TXBUF_SIZE;
+ }
+
+ sc->xmit_free = NTXBUF;
+ sc->xchead = sc->xctail = 0;
+
+ {
+ struct ie_xmit_cmd xmcmd;
+ bzero ( &xmcmd, sizeof xmcmd );
+ xmcmd.ie_xmit_status = IE_STAT_COMPL;
+ host2ie(sc, &xmcmd, sc->xmit_cmds[0], sizeof xmcmd);
+ }
+
+ start_receiver (sc);
+
+ return 0;
+}
+
+int iestop ( struct ie_softc *sc )
+{
+ struct ie_sys_ctl_block scb;
+ int s = splimp();
+
+ ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+
+ if ( command_and_wait(sc, IE_RU_DISABLE, &scb, 0, 0, 0, 0) )
+ printf ( "ie0: abort commands timed out\n" );
+
+ (void)splx(s);
+ return(0);
+}
+
+/*
+ * Send a command to the card and awaits it's completion.
+ * Timeout if it's taking too long
+ */
+
+/*CAW*/
+
+static int command_and_wait ( struct ie_softc *sc, u_short cmd,
+ struct ie_sys_ctl_block *pscb,
+ void *pcmd, int ocmd, int scmd, int mask )
+{
+ int i=0;
+
+ /* Copy the command to the card */
+
+ if ( pcmd )
+ host2ie(sc, pcmd, ocmd, scmd); /* transfer the command to the card */
+
+ /* Copy the scb to the card */
+
+ if ( pscb ) {
+ pscb->ie_command = cmd;
+ host2ie(sc, pscb, IE_IBASE + IE_SCB_OFF, sizeof *pscb);
+ }
+ else
+ {
+ setpage ( sc, IE_IBASE + IE_SCB_OFF );
+ PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+ (offsetof(struct ie_sys_ctl_block, ie_command)), cmd );
+ }
+
+ /* Prod the card to act on the newly loaded command */
+ ieattn(sc);
+
+ /* Wait for the command to complete */
+ if ( IE_ACTION_COMMAND(cmd) && pcmd )
+ {
+ setpage(sc,ocmd);
+ for ( i=4000; --i>=0; ) {
+ if ( ReadShort(sc->sc_ram + IE_COFF2POFF(ocmd) +
+ (offsetof(struct ie_config_cmd, ie_config_status))) & mask)
+ break;
+ delay(100);
+ }
+ }
+ else
+ {
+ for ( i=4000; --i>=0; ) {
+ if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+ (offsetof(struct ie_sys_ctl_block, ie_command))) )
+ break;
+ delay(100);
+ }
+ }
+
+ /* Update the host structures to reflect the state on the card */
+ if ( pscb )
+ ie2host(sc, IE_IBASE + IE_SCB_OFF, pscb, sizeof *pscb );
+ if ( pcmd )
+ ie2host(sc, ocmd, pcmd, scmd);
+
+ return i < 0;
+}
+
+#define READ_MEMBER(sc,type,member,ptr,dest) \
+ setpage(sc, ptr); \
+ dest = ReadShort(sc->sc_ram + IE_COFF2POFF(ptr) + \
+ (offsetof(type, member)) );
+
+#define WRITE_MEMBER(sc,type,member,ptr,dest) \
+ setpage(sc, ptr); \
+ PWriteShort(sc->sc_ram + IE_COFF2POFF(ptr) + \
+ (offsetof(type, member)), dest );
+
+static inline int ie_buflen ( struct ie_softc *sc, int head )
+{
+ int actual;
+ READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
+ sc->rbuffs[head], actual );
+
+ return ( actual & ( IE_RXBUF_SIZE | ( IE_RXBUF_SIZE-1 ) ) ) ;
+}
+
+static inline int ie_packet_len ( struct ie_softc *sc )
+{
+ int i;
+ int actual;
+ int head = sc->rbhead;
+ int acc=0;
+
+ do {
+ READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
+ sc->rbuffs[sc->rbhead], actual );
+ if (!(actual&IE_RBD_USED))
+ {
+ return (-1);
+ }
+
+ READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
+ sc->rbuffs[head], i );
+ i = i & IE_RBD_LAST;
+
+ acc += ie_buflen(sc, head);
+ head = (head+1) % NRXBUF;
+ } while (!i);
+
+ return acc;
+}
+
+struct mbuf *ieget(struct ie_softc *sc, struct ether_header *ehp, int *to_bpf )
+{
+ struct mbuf *top, **mp, *m;
+ int head;
+ int resid, totlen, thisrboff, thismboff;
+ int len;
+
+ totlen = ie_packet_len(sc);
+
+ if ( totlen > ETHER_MAX_LEN )
+ {
+ printf ( "ie: Gosh that packet was s-o-o-o big.\n" );
+ return 0;
+ }
+
+ if ( totlen<=0 )
+ return 0;
+
+ head = sc->rbhead;
+
+ /* Read the ethernet header */
+ ie2host ( sc, sc->cbuffs[head], (caddr_t)ehp, sizeof *ehp );
+
+ /* Check if the packet is for us */
+
+ resid = totlen -= (thisrboff = sizeof *ehp);
+
+ MGETHDR ( m, M_DONTWAIT, MT_DATA );
+ if ( m==0 )
+ return 0;
+
+ m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
+ m->m_pkthdr.len = totlen;
+ len = MHLEN;
+ top = 0;
+ mp = ⊤
+
+ /*
+ * This loop goes through and allocates mbufs for all the data we will
+ * be copying in. It does not actually do the copying yet.
+ */
+ while (totlen > 0) {
+ if (top) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == 0) {
+ m_freem(top);
+ return 0;
+ }
+ len = MLEN;
+ }
+ if (totlen >= MINCLSIZE) {
+ MCLGET(m, M_DONTWAIT);
+ if (m->m_flags & M_EXT)
+ len = MCLBYTES;
+ }
+ m->m_len = len = min(totlen, len);
+ totlen -= len;
+ *mp = m;
+ mp = &m->m_next;
+ }
+
+ m = top;
+ thismboff = 0;
+
+ /*
+ * Now we take the mbuf chain (hopefully only one mbuf most of the
+ * time) and stuff the data into it. There are no possible failures at
+ * or after this point.
+ */
+ while (resid > 0) {
+ int thisrblen = ie_buflen(sc, head) - thisrboff,
+ thismblen = m->m_len - thismboff;
+ len = min(thisrblen, thismblen);
+
+/* bcopy((caddr_t)(sc->cbuffs[head] + thisrboff),
+ mtod(m, caddr_t) + thismboff, (u_int)len); */
+
+
+ if ( len&1 )
+ {
+ ie2host(sc, sc->cbuffs[head]+thisrboff,
+ mtod(m, caddr_t) + thismboff, (u_int)len+1);
+ }
+ else
+ {
+ ie2host(sc, sc->cbuffs[head]+thisrboff,
+ mtod(m, caddr_t) + thismboff, (u_int)len);
+ }
+
+ resid -= len;
+
+ if (len == thismblen) {
+ m = m->m_next;
+ thismboff = 0;
+ } else
+ thismboff += len;
+
+ if (len == thisrblen) {
+ head = (head + 1) % NRXBUF;
+ thisrboff = 0;
+ } else
+ thisrboff += len;
+ }
+
+
+ return top;
+}
+
+void ie_drop_packet_buffer ( struct ie_softc *sc )
+{
+ int i, actual, last;
+
+ do {
+ READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
+ sc->rbuffs[sc->rbhead], actual );
+ if (!(actual&IE_RBD_USED))
+ {
+ iereset(sc);
+ return;
+ }
+
+ i = actual & IE_RBD_LAST;
+
+ READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
+ sc->rbuffs[sc->rbhead], last );
+ last |= IE_RBD_LAST;
+ WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
+ sc->rbuffs[sc->rbhead], last );
+
+ WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_actual,
+ sc->rbuffs[sc->rbhead], 0 );
+
+ sc->rbhead = ( sc->rbhead + 1 ) % NRXBUF;
+
+ READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
+ sc->rbuffs[sc->rbtail], last );
+ last &= ~IE_RBD_LAST;
+ WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
+ sc->rbuffs[sc->rbtail], last );
+
+ sc->rbtail = ( sc->rbtail + 1 ) % NRXBUF;
+ } while (!i);
+}
+
+void ie_read_frame ( struct ie_softc *sc, int num )
+{
+ int status;
+ struct ie_recv_frame_desc rfd;
+ struct mbuf *m=0;
+ struct ether_header eh;
+ int last;
+
+ ie2host(sc, sc->rframes[num], &rfd, sizeof rfd );
+ status = rfd.ie_fd_status;
+
+ /* Advance the RFD list, since we're done with this descriptor */
+
+ WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status,
+ sc->rframes[num], 0 );
+
+ READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
+ sc->rframes[num], last );
+ last |= IE_FD_LAST;
+ WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
+ sc->rframes[num], last );
+
+ READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
+ sc->rframes[sc->rftail], last );
+ last &= ~IE_FD_LAST;
+ WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
+ sc->rframes[sc->rftail], last );
+
+ sc->rftail = ( sc->rftail + 1 ) % NFRAMES;
+ sc->rfhead = ( sc->rfhead + 1 ) % NFRAMES;
+
+ if ( status & IE_FD_OK ) {
+ m = ieget(sc, &eh, 0);
+ ie_drop_packet_buffer(sc);
+ }
+
+ if ( m==0 ) {
+ sc->sc_arpcom.ac_if.if_ierrors++;
+ return;
+ }
+
+/*
+ printf ( "%s: frame from ether %s type %x\n", sc->sc_dev.dv_xname,
+ ether_sprintf(eh.ether_shost), (u_int)eh.ether_type );
+*/
+
+#if NBFILTER > 0
+ if ( sc->sc_arpcom.ac_if.if_bpf ) {
+ bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m );
+ };
+#endif
+
+ ether_input ( &sc->sc_arpcom.ac_if, &eh, m );
+ sc->sc_arpcom.ac_if.if_ipackets++;
+}
+
+void ierint ( struct ie_softc *sc )
+{
+ int i;
+ int times_thru = 1024;
+ struct ie_sys_ctl_block scb;
+ int status;
+ int saftey_catch = 0;
+
+ i = sc->rfhead;
+ for (;;) {
+
+ if ( (saftey_catch++)>100 )
+ {
+ printf ( "ie: ierint saftey catch tripped\n" );
+ iereset(sc);
+ return;
+ }
+
+ READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status,
+ sc->rframes[i],status);
+
+ if ((status&IE_FD_COMPLETE)&&(status&IE_FD_OK)) {
+ if ( !--times_thru ) {
+ printf ( "IERINT: Uh oh. Nuts, look at this bit!!!\n" );
+ ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+ sc->sc_arpcom.ac_if.if_ierrors += scb.ie_err_crc +
+ scb.ie_err_align +
+ scb.ie_err_resource +
+ scb.ie_err_overrun;
+ scb.ie_err_crc = scb.ie_err_align = 0;
+ scb.ie_err_resource = scb.ie_err_overrun = 0;
+ host2ie(sc, &scb, IE_SCP_ADDR, sizeof (scb) );
+ }
+ ie_read_frame(sc, i);
+ } else {
+ ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+
+ if ( ((status&IE_FD_RNR)!=0) && ((scb.ie_status&IE_RU_READY)==0) )
+ {
+ WRITE_MEMBER(sc,struct ie_recv_frame_desc, ie_fd_buf_desc,
+ sc->rframes[0], sc->rbuffs[0] );
+
+ scb.ie_recv_list = sc->rframes[0];
+ host2ie(sc, (char *)&scb, IE_IBASE + IE_SCB_OFF, sizeof (scb) );
+ command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0);
+ }
+ break;
+ }
+ i = (i + 1) % NFRAMES;
+ }
+}
+
+static int in_intr = 0;
+
+int ieintr ( void *arg )
+{
+ struct ie_softc *sc = arg;
+ u_short status;
+ int saftey_catch = 0;
+ static saftey_net = 0;
+
+ if ( in_intr==1 )
+ {
+ panic ( "ie: INTERRUPT REENTERED\n" );
+ }
+
+ /* Clear the interrrupt */
+ ie_cli (sc);
+
+ setpage(sc, IE_IBASE + IE_SCB_OFF );
+ status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+ (offsetof(struct ie_sys_ctl_block, ie_status)) );
+
+ status = status & IE_ST_WHENCE;
+
+ if ( status==0 )
+ {
+ in_intr = 0;
+ return 0;
+ }
+
+loop:
+
+ ie_ack(sc, status);
+
+ if (status & (IE_ST_FR | IE_ST_RNR)) {
+ ierint(sc);
+ }
+
+ if (status & IE_ST_CX) {
+ ietint(sc);
+ }
+
+ if (status & IE_ST_RNR) {
+ printf ( "ie: receiver not ready\n" );
+ sc->sc_arpcom.ac_if.if_ierrors++;
+ iereset(sc);
+ }
+
+ setpage(sc, IE_IBASE + IE_SCB_OFF );
+ status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
+ (offsetof(struct ie_sys_ctl_block, ie_status)) );
+ status = status & IE_ST_WHENCE;
+
+ ie_cli(sc);
+
+ if ( status==0 )
+ {
+ in_intr = 0;
+ return 1;
+ }
+
+ /* This is prehaps a little over cautious */
+ if ( saftey_catch++ > 10 )
+ {
+ printf ( "ie: Interrupt couldn't be cleared\n" );
+ delay ( 1000 );
+ ie_cli(sc);
+ if ( saftey_net++ > 50 )
+ {
+ printf ( "ie: saftey net catches driver, shutting down\n" );
+ disable_irq ( IRQ_PODULE );
+ }
+ in_intr = 0;
+ return 1;
+ }
+
+ goto loop;
+}
+
+void iexmit ( struct ie_softc *sc )
+{
+/* int actual;*/
+ struct ie_sys_ctl_block scb;
+
+ struct ie_xmit_cmd xc;
+ struct ie_xmit_buf xb;
+
+ ie2host(sc, sc->xmit_buffs[sc->xctail], (char *)&xb, sizeof xb );
+ xb.ie_xmit_flags |= IE_XMIT_LAST;
+ xb.ie_xmit_next = 0xffff;
+ xb.ie_xmit_buf = (caddr_t)sc->xmit_cbuffs[sc->xctail];
+ host2ie(sc, &xb, sc->xmit_buffs[sc->xctail], sizeof xb );
+
+ bzero ( &xc, sizeof xc );
+ xc.com.ie_cmd_link = 0xffff;
+ xc.com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;
+ xc.ie_xmit_status = 0x0000;
+ xc.ie_xmit_desc = sc->xmit_buffs[sc->xctail];
+ host2ie(sc, (char *)&xc, sc->xmit_cmds[sc->xctail], sizeof xc );
+
+ ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
+ scb.ie_command_list = sc->xmit_cmds[sc->xctail];
+ host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb );
+
+ command_and_wait(sc, IE_CU_START, &scb, &xc, sc->xmit_cmds[sc->xctail]
+ , sizeof xc, IE_STAT_COMPL);
+
+ sc->sc_arpcom.ac_if.if_timer = 5;
+}
+/*
+ * Start sending all the queued buffers.
+ */
+
+void iestart( struct ifnet *ifp )
+{
+ struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
+ struct mbuf *m0, *m;
+ u_char *buffer;
+ u_short len;
+ char txbuf[IE_TXBUF_SIZE];
+ int saftey_catch = 0;
+
+ if ((ifp->if_flags & IFF_OACTIVE) != 0)
+ return;
+
+ for (;;) {
+ if ( (saftey_catch++)>100 )
+ {
+ printf ( "ie: iestart saftey catch tripped\n" );
+ iereset(sc);
+ return;
+ }
+ if (sc->xmit_free == 0) {
+ ifp->if_flags |= IFF_OACTIVE;
+ break;
+ }
+
+ IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m);
+ if (!m)
+ break;
+
+ /* TODO: Write directly to the card */
+ len = 0;
+ /* buffer = sc->xmit_cbuffs[sc->xchead]; */
+ buffer = txbuf;
+
+ for (m0 = m; m && (len + m->m_len) < IE_TXBUF_SIZE;
+ m = m->m_next) {
+ bcopy(mtod(m, caddr_t), buffer, m->m_len);
+ buffer += m->m_len;
+ len += m->m_len;
+ }
+
+ m_freem(m0);
+ len = max(len, ETHER_MIN_LEN);
+
+#if NBPFILTER > 0
+ if ( sc->sc_arpcom.ac_if.if_bpf )
+ bpf_tap(sc->sc_arpcom.ac_if.if_bpf, txbuf, len);
+#endif
+
+ /* When we write directly to the card we dont need this */
+ if (len&1)
+ host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len+1 );
+ else
+ host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len );
+
+ /* sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len; */
+
+ WRITE_MEMBER(sc,struct ie_xmit_buf, ie_xmit_flags,
+ sc->xmit_buffs[sc->xchead], len)
+
+ /* Start the first packet transmitting. */
+ if (sc->xmit_free == NTXBUF)
+ iexmit(sc);
+
+ sc->xchead = (sc->xchead + 1) % NTXBUF;
+ sc->xmit_free--;
+ }
+}
+
+void ietint ( struct ie_softc *sc )
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+
+ int status;
+
+ ifp->if_timer=0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ READ_MEMBER(sc,struct ie_xmit_cmd, ie_xmit_status,
+ sc->xmit_cmds[sc->xctail], status );
+
+ if (!(status&IE_STAT_COMPL) || (status & IE_STAT_BUSY) )
+ printf ( "ietint: command still busy!\n" );
+
+ if ( status & IE_STAT_OK ) {
+ ifp->if_opackets++;
+ ifp->if_collisions += status & IE_XS_MAXCOLL;
+ } else {
+ ifp->if_oerrors++;
+ if ( status & IE_STAT_ABORT )
+ printf ( "ie: send aborted\n" );
+ if ( status & IE_XS_LATECOLL )
+ printf ( "ie: late collision\n" );
+ if ( status & IE_XS_NOCARRIER )
+ printf ( "ie: no carrier\n" );
+ if ( status & IE_XS_LOSTCTS )
+ printf ( "ie: lost CTS\n" );
+ if ( status & IE_XS_UNDERRUN )
+ printf ( "ie: DMA underrun\n" );
+ if ( status & IE_XS_EXCMAX )
+ printf ( "ie: too many collisions\n" );
+ ifp->if_collisions+=16;
+ }
+ /* Done with the buffer */
+ sc->xmit_free++;
+ sc->xctail = (sc->xctail + 1 ) % NTXBUF;
+
+ /* Start the next packet transmitting, if any */
+ if ( sc->xmit_free<NTXBUF )
+ iexmit(sc);
+
+ iestart(ifp);
+}
+
+
+/* End of if_ie.c */
--- /dev/null
+/* $NetBSD: if_iereg.h,v 1.2 1996/03/18 21:23:16 mark Exp $ */
+
+/*
+ * Copyright (C) 1994 Wolfgang Solfrank.
+ * Copyright (C) 1994 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define IE_PAGE 0
+
+#define IE_CONTROL 1
+#define IE_CONT_RESET 1
+#define IE_CONT_LOOP 2
+#define IE_CONT_ATTN 4
+#define IE_CONT_CLI 8
+
+#define IE_MEMSIZE 65536
+#define IE_PAGESIZE 4096
+#define IE_MEMOFF 0x2000
+#define IE_COFF2POFF(off) ((off) % IE_PAGESIZE * 2)
+#define IE_COFF2PAGE(off) (((off) % IE_MEMSIZE) / IE_PAGESIZE)
+
+#define IE_ISCP_ADDR (IE_SCP_ADDR - sizeof(struct ie_int_sys_conf_ptr))
+#define IE_IBASE (0x1000000 - IE_MEMSIZE)
+#define IE_SCB_OFF 0
+
+/* Steal most defines from PC driver: */
+#include <dev/ic/i82586reg.h>
--- /dev/null
+/* $NetBSD: ncr5380reg.h,v 1.1 1996/01/31 23:26:04 mark Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY (mach3)
+ * Revision 2.3 91/08/24 12:25:10 af
+ * Moved padding of regmap in impl file.
+ * [91/08/02 04:22:39 af]
+ *
+ * Revision 2.2 91/06/19 16:28:35 rvb
+ * From the NCR data sheets
+ * "NCR 5380 Family, SCSI Protocol Controller Data Manual"
+ * NCR Microelectronics Division, Colorado Spring, 6/98 T01891L
+ * [91/04/21 af]
+ *
+ */
+
+/*
+ * File: scsi_5380.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 5/91
+ *
+ * Defines for the NCR 5380 (SCSI chip), aka Am5380
+ */
+
+/*
+ * Register map: Note not declared here anymore!
+ * All the 5380 registers are accessed through individual
+ * pointers initialized by MD code. This allows the 5380
+ * MI functions to be shared between MD drivers that have
+ * different padding between the registers (i.e. amiga).
+ */
+#if 0 /* example only */
+struct ncr5380regs {
+ volatile u_char sci_r0;
+ volatile u_char sci_r1;
+ volatile u_char sci_r2;
+ volatile u_char sci_r3;
+ volatile u_char sci_r4;
+ volatile u_char sci_r5;
+ volatile u_char sci_r6;
+ volatile u_char sci_r7;
+};
+#endif
+
+/*
+ * Machine-independent code uses these names:
+ */
+#define sci_data sci_r0 /* r: Current data */
+#define sci_odata sci_r0 /* w: Out data */
+
+#define sci_icmd sci_r1 /* rw: Initiator command */
+#define sci_mode sci_r2 /* rw: Mode */
+#define sci_tcmd sci_r3 /* rw: Target command */
+
+#define sci_bus_csr sci_r4 /* r: Bus Status */
+#define sci_sel_enb sci_r4 /* w: Select enable */
+
+#define sci_csr sci_r5 /* r: Status */
+#define sci_dma_send sci_r5 /* w: Start dma send data */
+
+#define sci_idata sci_r6 /* r: Input data */
+#define sci_trecv sci_r6 /* w: Start dma receive, target */
+
+#define sci_iack sci_r7 /* r: Interrupt Acknowledge */
+#define sci_irecv sci_r7 /* w: Start dma receive, initiator */
+
+
+/*
+ * R1: Initiator command register
+ */
+#define SCI_ICMD_DATA 0x01 /* rw: Assert data bus */
+#define SCI_ICMD_ATN 0x02 /* rw: Assert ATN signal */
+#define SCI_ICMD_SEL 0x04 /* rw: Assert SEL signal */
+#define SCI_ICMD_BSY 0x08 /* rw: Assert BSY signal */
+#define SCI_ICMD_ACK 0x10 /* rw: Assert ACK signal */
+#define SCI_ICMD_LST 0x20 /* r: Lost arbitration */
+#define SCI_ICMD_DIFF SCI_ICMD_LST /* w: Differential cable */
+#define SCI_ICMD_AIP 0x40 /* r: Arbitration in progress */
+#define SCI_ICMD_TEST SCI_ICMD_AIP /* w: Test mode */
+#define SCI_ICMD_RST 0x80 /* rw: Assert RST signal */
+/* Bits to keep when doing read/modify/write (leave out RST) */
+#define SCI_ICMD_RMASK 0x1F
+
+
+/*
+ * R2: Mode register
+ */
+#define SCI_MODE_ARB 0x01 /* rw: Start arbitration */
+#define SCI_MODE_DMA 0x02 /* rw: Enable DMA xfers */
+#define SCI_MODE_MONBSY 0x04 /* rw: Monitor BSY signal */
+#define SCI_MODE_DMA_IE 0x08 /* rw: Enable DMA complete interrupt */
+#define SCI_MODE_PERR_IE 0x10 /* rw: Interrupt on parity errors */
+#define SCI_MODE_PAR_CHK 0x20 /* rw: Check parity */
+#define SCI_MODE_TARGET 0x40 /* rw: Target mode (Initiator if 0) */
+#define SCI_MODE_BLOCKDMA 0x80 /* rw: Block-mode DMA handshake */
+
+
+/*
+ * R3: Target command register
+ */
+#define SCI_TCMD_IO 0x01 /* rw: Assert I/O signal */
+#define SCI_TCMD_CD 0x02 /* rw: Assert C/D signal */
+#define SCI_TCMD_MSG 0x04 /* rw: Assert MSG signal */
+#define SCI_TCMD_PHASE_MASK 0x07 /* r: Mask for current bus phase */
+#define SCI_TCMD_REQ 0x08 /* rw: Assert REQ signal */
+#define SCI_TCMD_LAST_SENT 0x80 /* ro: Last byte was xferred
+ * (not on 5380/1) */
+
+#define SCI_TCMD_PHASE(x) ((x) & 0x7)
+
+/*
+ * R4: Current (SCSI) Bus status (.sci_bus_csr)
+ */
+#define SCI_BUS_DBP 0x01 /* r: Data Bus parity */
+#define SCI_BUS_SEL 0x02 /* r: SEL signal */
+#define SCI_BUS_IO 0x04 /* r: I/O signal */
+#define SCI_BUS_CD 0x08 /* r: C/D signal */
+#define SCI_BUS_MSG 0x10 /* r: MSG signal */
+#define SCI_BUS_REQ 0x20 /* r: REQ signal */
+#define SCI_BUS_BSY 0x40 /* r: BSY signal */
+#define SCI_BUS_RST 0x80 /* r: RST signal */
+
+#define SCI_BUS_PHASE(x) (((x) >> 2) & 7)
+
+/*
+ * R5: Bus and Status register (.sci_csr)
+ */
+#define SCI_CSR_ACK 0x01 /* r: ACK signal */
+#define SCI_CSR_ATN 0x02 /* r: ATN signal */
+#define SCI_CSR_DISC 0x04 /* r: Disconnected (BSY==0) */
+#define SCI_CSR_PHASE_MATCH 0x08 /* r: Bus and SCI_TCMD match */
+#define SCI_CSR_INT 0x10 /* r: Interrupt request */
+#define SCI_CSR_PERR 0x20 /* r: Parity error */
+#define SCI_CSR_DREQ 0x40 /* r: DMA request */
+#define SCI_CSR_DONE 0x80 /* r: DMA count is zero */
--- /dev/null
+/* $NetBSD: ncr5380sbc.c,v 1.2 1996/03/27 22:05:19 mark Exp $ */
+
+/*
+ * Copyright (c) 1996 Melvin Tang-Richardson (Modified for weird regs)
+ * Copyright (c) 1995 David Jones, Gordon W. Ross
+ * Copyright (c) 1994 Jarle Greipsland
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * 4. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by
+ * David Jones and Gordon Ross
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#undef DIAGNOSTIC
+
+/*
+ * This is a machine-independent driver for the NCR5380
+ * SCSI Bus Controller (SBC), also known as the Am5380.
+ *
+ * This code should work with any memory-mapped 5380,
+ * and can be shared by multiple adapters that address
+ * the 5380 with different register offset spacings.
+ * (This can happen on the atari, for example.)
+ * For porting/design info. see: ncr5380.doc
+ *
+ * Credits, history:
+ *
+ * David Jones is the author of most of the code that now
+ * appears in this file, and was the architect of the
+ * current overall structure (MI/MD code separation, etc.)
+ *
+ * Gordon Ross integrated the message phase code, added lots of
+ * comments about what happens when and why (re. SCSI spec.),
+ * debugged some reentrance problems, and added several new
+ * "hooks" needed for the Sun3 "si" adapters.
+ *
+ * The message in/out code was taken nearly verbatim from
+ * the aic6360 driver by Jarle Greipsland.
+ *
+ * Several other NCR5380 drivers were used for reference
+ * while developing this driver, including work by:
+ * The Alice Group (mac68k port) namely:
+ * Allen K. Briggs, Chris P. Caputo, Michael L. Finch,
+ * Bradley A. Grantham, and Lawrence A. Kesteloot
+ * Michael L. Hitch (amiga drivers: sci.c)
+ * Leo Weppelman (atari driver: ncr5380.c)
+ * There are others too. Thanks, everyone.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_debug.h>
+#include <scsi/scsi_message.h>
+#include <scsi/scsiconf.h>
+
+#define DEBUG XXX
+
+#define SetReg(l,d) *((volatile unsigned int *)((void *)l))=((d)|(((d)<<16)))
+
+#if 0 /* XXX - not yet... */
+#include <dev/ic/ncr5380reg.h>
+#include <dev/ic/ncr5380var.h>
+#else
+#include "ncr5380reg.h"
+#include "ncr5380var.h"
+#endif
+
+static int ncr5380_wait_req __P((struct ncr5380_softc *));
+static int ncr5380_wait_not_req __P((struct ncr5380_softc *));
+
+static void ncr5380_sched __P((struct ncr5380_softc *));
+static void ncr5380_done __P((struct ncr5380_softc *));
+
+static int ncr5380_select
+ __P((struct ncr5380_softc *, struct sci_req *));
+static void ncr5380_reselect __P((struct ncr5380_softc *));
+
+static int ncr5380_msg_in __P((struct ncr5380_softc *));
+static int ncr5380_msg_out __P((struct ncr5380_softc *));
+static int ncr5380_data_xfer __P((struct ncr5380_softc *, int));
+static int ncr5380_command __P((struct ncr5380_softc *));
+static int ncr5380_status __P((struct ncr5380_softc *));
+static void ncr5380_machine __P((struct ncr5380_softc *));
+
+/*
+ * Action flags returned by the info_tranfer functions:
+ * (These determine what happens next.)
+ */
+#define ACT_CONTINUE 0x00 /* No flags: expect another phase */
+#define ACT_DISCONNECT 0x01 /* Target is disconnecting */
+#define ACT_CMD_DONE 0x02 /* Need to call scsi_done() */
+#define ACT_RESET_BUS 0x04 /* Need bus reset (cmd timeout) */
+#define ACT_WAIT_DMA 0x10 /* Wait for DMA to complete */
+
+/*****************************************************************
+ * Debugging stuff
+ *****************************************************************/
+
+#ifndef DDB
+/* This is used only in recoverable places. */
+#define Debugger() printf("Debug: ncr5380.c:%d\n", __LINE__)
+#endif
+
+#ifdef DEBUG
+
+#define NCR_DBG_BREAK 1
+#define NCR_DBG_CMDS 2
+int ncr5380_debug = NCR_DBG_BREAK;
+#define NCR_BREAK() \
+ do { if (ncr5380_debug & NCR_DBG_BREAK) Debugger(); } while (0)
+static void ncr5380_show_scsi_cmd __P((struct scsi_xfer *));
+static void ncr5380_show_sense __P((struct scsi_xfer *));
+#else /* DEBUG */
+#define NCR_BREAK() /* nada */
+#define ncr5380_show_scsi_cmd(xs) /* nada */
+#define ncr5380_show_sense(xs) /* nada */
+#endif /* DEBUG */
+
+static char *
+phase_names[8] = {
+ "DATA_OUT",
+ "DATA_IN",
+ "COMMAND",
+ "STATUS",
+ "UNSPEC1",
+ "UNSPEC2",
+ "MSG_OUT",
+ "MSG_IN",
+};
+
+/*****************************************************************
+ * Actual chip control
+ *****************************************************************/
+
+/*
+ * XXX: These timeouts might need to be tuned...
+ */
+
+/* This one is used when waiting for a phase change. (X100uS.) */
+int ncr5380_wait_phase_timo = 1000 * 10 * 300; /* 5 min. */
+
+/* These are used in the following inline functions. */
+int ncr5380_wait_req_timo = 1000 * 50; /* X2 = 100 mS. */
+int ncr5380_wait_nrq_timo = 1000 * 25; /* X2 = 50 mS. */
+
+/* Return zero on success. */
+static __inline__ int ncr5380_wait_req(sc)
+ struct ncr5380_softc *sc;
+{
+ register int timo = ncr5380_wait_req_timo;
+ for (;;) {
+ if (*sc->sci_bus_csr & SCI_BUS_REQ) {
+ timo = 0; /* return 0 */
+ break;
+ }
+ if (--timo < 0)
+ break; /* return -1 */
+ delay(2);
+ }
+ return (timo);
+}
+
+/* Return zero on success. */
+static __inline__ int ncr5380_wait_not_req(sc)
+ struct ncr5380_softc *sc;
+{
+ register int timo = ncr5380_wait_nrq_timo;
+ for (;;) {
+ if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0) {
+ timo = 0; /* return 0 */
+ break;
+ }
+ if (--timo < 0)
+ break; /* return -1 */
+ delay(2);
+ }
+ return (timo);
+}
+
+/* Ask the target for a MSG_OUT phase. */
+static __inline__ void
+ncr_sched_msgout(sc, msg_code)
+ struct ncr5380_softc *sc;
+ int msg_code;
+{
+ /* First time, raise ATN line. */
+ if (sc->sc_msgpriq == 0) {
+ register u_char icmd;
+ icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
+ SetReg ( sc->sci_icmd, icmd | SCI_ICMD_ATN );
+/* *sc->sci_icmd = icmd | SCI_ICMD_ATN; */
+ delay(2);
+ }
+ sc->sc_msgpriq |= msg_code;
+}
+
+
+int
+ncr5380_pio_out(sc, phase, count, data)
+ struct ncr5380_softc *sc;
+ int phase, count;
+ unsigned char *data;
+{
+ register u_char icmd;
+ register int resid;
+ register int error;
+
+ icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
+
+ icmd |= SCI_ICMD_DATA;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ resid = count;
+ while (resid > 0) {
+ if (!SCI_BUSY(sc)) {
+ NCR_TRACE("pio_out: lost BSY, resid=%d\n", resid);
+ break;
+ }
+ if (ncr5380_wait_req(sc)) {
+ NCR_TRACE("pio_out: no REQ, resid=%d\n", resid);
+ break;
+ }
+ if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
+ break;
+
+ /* Put the data on the bus. */
+ SetReg ( sc->sci_odata, *data ); data++;
+/* *sc->sci_odata = *data++; */
+
+ /* Tell the target it's there. */
+ icmd |= SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ /* Wait for target to get it. */
+ error = ncr5380_wait_not_req(sc);
+
+ /* OK, it's got it (or we gave up waiting). */
+ icmd &= ~SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ if (error) {
+ NCR_TRACE("pio_out: stuck REQ, resid=%d\n", resid);
+ break;
+ }
+
+ --resid;
+ }
+
+ /* Stop driving the data bus. */
+ icmd &= ~SCI_ICMD_DATA;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ return (count - resid);
+}
+
+
+int
+ncr5380_pio_in(sc, phase, count, data)
+ struct ncr5380_softc *sc;
+ int phase, count;
+ unsigned char *data;
+{
+ register u_char icmd;
+ register int resid;
+ register int error;
+
+ icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
+
+ resid = count;
+ while (resid > 0) {
+ if (!SCI_BUSY(sc)) {
+ NCR_TRACE("pio_in: lost BSY, resid=%d\n", resid);
+ break;
+ }
+ if (ncr5380_wait_req(sc)) {
+ NCR_TRACE("pio_in: no REQ, resid=%d\n", resid);
+ break;
+ }
+ /* A phase change is not valid until AFTER REQ rises! */
+ if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
+ break;
+
+ /* Read the data bus. */
+ *data++ = *sc->sci_data;
+
+ /* Tell target we got it. */
+ icmd |= SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ /* Wait for target to drop REQ... */
+ error = ncr5380_wait_not_req(sc);
+
+ /* OK, we can drop ACK. */
+ icmd &= ~SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ if (error) {
+ NCR_TRACE("pio_in: stuck REQ, resid=%d\n", resid);
+ break;
+ }
+
+ --resid;
+ }
+
+ return (count - resid);
+}
+
+
+void
+ncr5380_init(sc)
+ struct ncr5380_softc *sc;
+{
+ int i, j;
+
+#ifdef DEBUG
+ ncr5380_debug_sc = sc;
+#endif
+
+ for (i = 0; i < SCI_OPENINGS; i++)
+ sc->sc_ring[i].sr_xs = NULL;
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 8; j++)
+ sc->sc_matrix[i][j] = NULL;
+
+ sc->sc_link.openings = 2; /* XXX - Not SCI_OPENINGS */
+ sc->sc_prevphase = PHASE_INVALID;
+ sc->sc_state = NCR_IDLE;
+
+ SetReg ( sc->sci_tcmd, PHASE_INVALID );
+ SetReg ( sc->sci_icmd, 0 );
+ SetReg ( sc->sci_mode, 0 );
+ SetReg ( sc->sci_sel_enb, 0 );
+
+/* *sc->sci_tcmd = PHASE_INVALID;
+ *sc->sci_icmd = 0;
+ *sc->sci_mode = 0;
+ *sc->sci_sel_enb = 0; */
+ SCI_CLR_INTR(sc);
+
+ /* XXX: Enable reselect interrupts... */
+ SetReg ( sc->sci_sel_enb, 0x80 );
+/* *sc->sci_sel_enb = 0x80; */
+
+ /* Another hack (Er.. hook!) for the sun3 si: */
+ if (sc->sc_intr_on) {
+ NCR_TRACE("init: intr ON\n", 0);
+ sc->sc_intr_on(sc);
+ }
+}
+
+
+void
+ncr5380_reset_scsibus(sc)
+ struct ncr5380_softc *sc;
+{
+
+ NCR_TRACE("reset_scsibus, cur=0x%x\n",
+ (long) sc->sc_current);
+
+ SetReg ( sc->sci_icmd, SCI_ICMD_RST );
+/* *sc->sci_icmd = SCI_ICMD_RST; */
+ delay(500);
+ SetReg ( sc->sci_icmd, 0 );
+/* *sc->sci_icmd = 0; */
+
+ SetReg ( sc->sci_mode, 0 );
+ SetReg ( sc->sci_tcmd, PHASE_INVALID );
+
+/* *sc->sci_mode = 0;
+ *sc->sci_tcmd = PHASE_INVALID; */
+
+ SCI_CLR_INTR(sc);
+ /* XXX - Need long delay here! */
+ delay(100000);
+
+ /* XXX - Need to cancel disconnected requests. */
+}
+
+
+/*
+ * Interrupt handler for the SCSI Bus Controller (SBC)
+ * This may also called for a DMA timeout (at splbio).
+ */
+int
+ncr5380_intr(sc)
+ struct ncr5380_softc *sc;
+{
+ int claimed = 0;
+
+ /*
+ * Do not touch SBC regs here unless sc_current == NULL
+ * or it will complain about "register conflict" errors.
+ * Instead, just let ncr5380_machine() deal with it.
+ */
+ NCR_TRACE("intr: top, state=%d\n", sc->sc_state);
+
+ if (sc->sc_state == NCR_IDLE) {
+ /*
+ * Might be reselect. ncr5380_reselect() will check,
+ * and set up the connection if so. This will verify
+ * that sc_current == NULL at the beginning...
+ */
+
+ /* Another hack (Er.. hook!) for the sun3 si: */
+ if (sc->sc_intr_off) {
+ NCR_TRACE("intr: for reselect, intr off\n", 0);
+ sc->sc_intr_off(sc);
+ }
+
+ ncr5380_reselect(sc);
+ }
+
+ /*
+ * The remaining documented interrupt causes are phase mismatch and
+ * disconnect. In addition, the sunsi controller may produce a state
+ * where SCI_CSR_DONE is false, yet DMA is complete.
+ *
+ * The procedure in all these cases is to let ncr5380_machine()
+ * figure out what to do next.
+ */
+ if (sc->sc_state & NCR_WORKING) {
+ NCR_TRACE("intr: call machine, cur=0x%x\n",
+ (long) sc->sc_current);
+ /* This will usually free-up the nexus. */
+ ncr5380_machine(sc);
+ NCR_TRACE("intr: machine done, cur=0x%x\n",
+ (long) sc->sc_current);
+ claimed = 1;
+ }
+
+ /* Maybe we can run some commands now... */
+ if (sc->sc_state == NCR_IDLE) {
+ NCR_TRACE("intr: call sched, cur=0x%x\n",
+ (long) sc->sc_current);
+ ncr5380_sched(sc);
+ NCR_TRACE("intr: sched done, cur=0x%x\n",
+ (long) sc->sc_current);
+ }
+
+ return claimed;
+}
+
+
+/*
+ * Abort the current command (i.e. due to timeout)
+ */
+void
+ncr5380_abort(sc)
+ struct ncr5380_softc *sc;
+{
+
+ /*
+ * Finish it now. If DMA is in progress, we
+ * can not call ncr_sched_msgout() because
+ * that hits the SBC (avoid DMA conflict).
+ */
+
+ /* Another hack (Er.. hook!) for the sun3 si: */
+ if (sc->sc_intr_off) {
+ NCR_TRACE("abort: intr off\n", 0);
+ sc->sc_intr_off(sc);
+ }
+
+ sc->sc_state |= NCR_ABORTING;
+ if ((sc->sc_state & NCR_DOINGDMA) == 0) {
+ ncr_sched_msgout(sc, SEND_ABORT);
+ }
+ NCR_TRACE("abort: call machine, cur=0x%x\n",
+ (long) sc->sc_current);
+ ncr5380_machine(sc);
+ NCR_TRACE("abort: machine done, cur=0x%x\n",
+ (long) sc->sc_current);
+
+ /* Another hack (Er.. hook!) for the sun3 si: */
+ if (sc->sc_intr_on) {
+ NCR_TRACE("abort: intr ON\n", 0);
+ sc->sc_intr_on(sc);
+ }
+}
+
+/*
+ * Timeout handler, scheduled for each SCSI command.
+ */
+void
+ncr5380_cmd_timeout(arg)
+ void *arg;
+{
+ struct sci_req *sr = arg;
+ struct scsi_xfer *xs;
+ struct scsi_link *sc_link;
+ struct ncr5380_softc *sc;
+ int s;
+
+ s = splbio();
+
+ /* Get all our variables... */
+ xs = sr->sr_xs;
+ if (xs == NULL) {
+ printf("ncr5380_cmd_timeout: no scsi_xfer\n");
+ goto out;
+ }
+ sc_link = xs->sc_link;
+ sc = sc_link->adapter_softc;
+
+ printf("%s: cmd timeout, targ=%d, lun=%d\n",
+ sc->sc_dev.dv_xname,
+ sr->sr_target, sr->sr_lun);
+
+ /*
+ * Mark the overdue job as failed, and arrange for
+ * ncr5380_machine to terminate it. If the victim
+ * is the current job, call ncr5380_machine() now.
+ * Otherwise arrange for ncr5380_sched() to do it.
+ */
+ sr->sr_flags |= SR_OVERDUE;
+ if (sc->sc_current == sr) {
+ NCR_TRACE("cmd_tmo: call abort, sr=0x%x\n", (long) sr);
+ ncr5380_abort(sc);
+ } else {
+ /*
+ * The driver may be idle, or busy with another job.
+ * Arrange for ncr5380_sched() to do the deed.
+ */
+ NCR_TRACE("cmd_tmo: clear matrix, t/l=0x%02x\n",
+ (sr->sr_target << 4) | sr->sr_lun);
+ sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL;
+ }
+
+ /*
+ * We may have aborted the current job, or may have
+ * already been idle. In either case, we should now
+ * be idle, so try to start another job.
+ */
+ if (sc->sc_state == NCR_IDLE) {
+ NCR_TRACE("cmd_tmo: call sched, cur=0x%x\n",
+ (long) sc->sc_current);
+ ncr5380_sched(sc);
+ NCR_TRACE("cmd_tmo: sched done, cur=0x%x\n",
+ (long) sc->sc_current);
+ }
+
+out:
+ splx(s);
+}
+
+
+/*****************************************************************
+ * Interface to higher level
+ *****************************************************************/
+
+
+/*
+ * Enter a new SCSI command into the "issue" queue, and
+ * if there is work to do, start it going.
+ *
+ * WARNING: This can be called recursively!
+ * (see comment in ncr5380_done)
+ */
+int
+ncr5380_scsi_cmd(xs)
+ struct scsi_xfer *xs;
+{
+ struct ncr5380_softc *sc;
+ struct sci_req *sr;
+ int s, rv, i, flags;
+ extern int cold; /* XXX */
+
+ sc = xs->sc_link->adapter_softc;
+
+ flags = xs->flags;
+ /*
+ * XXX: Hack: During autoconfig, force polling mode.
+ * Needed as long as sdsize() can be called while cold,
+ * otherwise timeouts will never call back (grumble).
+ */
+ if (cold)
+ flags |= SCSI_POLL;
+
+ if (sc->sc_flags & NCR5380_FORCE_POLLING)
+ flags |= SCSI_POLL;
+
+ if (flags & SCSI_DATA_UIO)
+ panic("ncr5380: scsi data uio requested");
+
+ s = splbio();
+
+ if (flags & SCSI_POLL) {
+ /* Terminate any current command. */
+ sr = sc->sc_current;
+ if (sr) {
+ printf("%s: polled request aborting %d/%d\n",
+ sc->sc_dev.dv_xname,
+ sr->sr_target, sr->sr_lun);
+ ncr5380_abort(sc);
+ }
+ if (sc->sc_state != NCR_IDLE) {
+ panic("ncr5380_scsi_cmd: polled request, abort failed");
+ }
+ }
+
+ /*
+ * Find lowest empty slot in ring buffer.
+ * XXX: What about "fairness" and cmd order?
+ */
+ for (i = 0; i < SCI_OPENINGS; i++)
+ if (sc->sc_ring[i].sr_xs == NULL)
+ goto new;
+
+ rv = TRY_AGAIN_LATER;
+ NCR_TRACE("scsi_cmd: no openings, rv=%d\n", rv);
+ goto out;
+
+new:
+ /* Create queue entry */
+ sr = &sc->sc_ring[i];
+ sr->sr_xs = xs;
+ sr->sr_target = xs->sc_link->target;
+ sr->sr_lun = xs->sc_link->lun;
+ sr->sr_dma_hand = NULL;
+ sr->sr_dataptr = xs->data;
+ sr->sr_datalen = xs->datalen;
+ sr->sr_flags = (flags & SCSI_POLL) ? SR_IMMED : 0;
+ sr->sr_status = -1; /* no value */
+ sc->sc_ncmds++;
+ rv = SUCCESSFULLY_QUEUED;
+
+ NCR_TRACE("scsi_cmd: new sr=0x%x\n", (long)sr);
+
+ if (flags & SCSI_POLL) {
+ /* Force this new command to be next. */
+ sc->sc_rr = i;
+ }
+
+ /*
+ * If we were idle, run some commands...
+ */
+ if (sc->sc_state == NCR_IDLE) {
+ NCR_TRACE("scsi_cmd: call sched, cur=0x%x\n",
+ (long) sc->sc_current);
+ ncr5380_sched(sc);
+ NCR_TRACE("scsi_cmd: sched done, cur=0x%x\n",
+ (long) sc->sc_current);
+ }
+
+ if (flags & SCSI_POLL) {
+ /* Make sure ncr5380_sched() finished it. */
+ if ((xs->flags & ITSDONE) == 0)
+ panic("ncr5380_scsi_cmd: poll didn't finish");
+ rv = COMPLETE;
+ }
+
+out:
+ splx(s);
+ return (rv);
+}
+
+
+/*
+ * POST PROCESSING OF SCSI_CMD (usually current)
+ * Called by ncr5380_sched(), ncr5380_machine()
+ */
+static void
+ncr5380_done(sc)
+ struct ncr5380_softc *sc;
+{
+ struct sci_req *sr;
+ struct scsi_xfer *xs;
+
+#ifdef DIAGNOSTIC
+ if ((getsr() & PSL_IPL) < PSL_IPL2)
+ panic("ncr5380_done: bad spl");
+ if (sc->sc_state == NCR_IDLE)
+ panic("ncr5380_done: state=idle");
+ if (sc->sc_current == NULL)
+ panic("ncr5380_done: current=0");
+#endif
+
+ sr = sc->sc_current;
+ xs = sr->sr_xs;
+
+ NCR_TRACE("done: top, cur=0x%x\n", (long) sc->sc_current);
+
+ /*
+ * Clean up DMA resources for this command.
+ */
+ if (sr->sr_dma_hand) {
+ NCR_TRACE("done: dma_free, dh=0x%x\n",
+ (long) sr->sr_dma_hand);
+ (*sc->sc_dma_free)(sc);
+ }
+#ifdef DIAGNOSTIC
+ if (sr->sr_dma_hand)
+ panic("ncr5380_done: dma free did not");
+#endif
+
+ if (sc->sc_state & NCR_ABORTING) {
+ NCR_TRACE("done: aborting, error=%d\n", xs->error);
+ if (xs->error == XS_NOERROR)
+ xs->error = XS_TIMEOUT;
+ }
+
+ NCR_TRACE("done: check error=%d\n", (long) xs->error);
+
+ /* If error is already set, ignore sr_status value. */
+ if (xs->error != XS_NOERROR)
+ goto finish;
+
+ NCR_TRACE("done: check status=%d\n", sr->sr_status);
+
+ switch (sr->sr_status) {
+ case SCSI_OK: /* 0 */
+ if (sr->sr_flags & SR_SENSE) {
+ if (ncr5380_debug & NCR_DBG_CMDS) {
+ ncr5380_show_sense(xs);
+ }
+ xs->error = XS_SENSE;
+ }
+ break;
+
+ case SCSI_CHECK:
+ if (sr->sr_flags & SR_SENSE) {
+ /* Sense command also asked for sense? */
+ printf("ncr5380_done: sense asked for sense\n");
+ NCR_BREAK();
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+ }
+ sr->sr_flags |= SR_SENSE;
+ NCR_TRACE("done: get sense, sr=0x%x\n", (long) sr);
+ /*
+ * Leave queued, but clear sc_current so we start over
+ * with selection. Guaranteed to get the same request.
+ */
+ sc->sc_state = NCR_IDLE;
+ sc->sc_current = NULL;
+ sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL;
+ return; /* XXX */
+
+ case SCSI_BUSY:
+ xs->error = XS_BUSY;
+ break;
+
+ case -1:
+ /* This is our "impossible" initial value. */
+ /* fallthrough */
+ default:
+ printf("%s: target %d, bad status=%d\n",
+ sc->sc_dev.dv_xname, sr->sr_target, sr->sr_status);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+ }
+
+finish:
+
+ NCR_TRACE("done: finish, error=%d\n", xs->error);
+
+ /*
+ * Dequeue the finished command, but don't clear sc_state until
+ * after the call to scsi_done(), because that may call back to
+ * ncr5380_scsi_cmd() - unwanted recursion!
+ *
+ * Keeping sc->sc_state != idle terminates the recursion.
+ */
+#ifdef DIAGNOSTIC
+ if ((sc->sc_state & NCR_WORKING) == 0)
+ panic("ncr5380_done: bad state");
+#endif
+
+ /* Clear our pointers to the request. */
+ sc->sc_current = NULL;
+ sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL;
+ untimeout(ncr5380_cmd_timeout, sr);
+
+ /* Make the request free. */
+ sr->sr_xs = NULL;
+ sc->sc_ncmds--;
+
+ /* Tell common SCSI code it is done. */
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+
+ sc->sc_state = NCR_IDLE;
+ /* Now ncr5380_sched() may be called again. */
+}
+
+
+/*
+ * Schedule a SCSI operation. This routine should return
+ * only after it achieves one of the following conditions:
+ * Busy (sc->sc_state != NCR_IDLE)
+ * No more work can be started.
+ */
+static void
+ncr5380_sched(sc)
+ struct ncr5380_softc *sc;
+{
+ struct sci_req *sr;
+ struct scsi_xfer *xs;
+ int target, lun;
+ int error, i;
+
+#ifdef DIAGNOSTIC
+ if ((getsr() & PSL_IPL) < PSL_IPL2)
+ panic("ncr5380_sched: bad spl");
+#endif
+
+ /* Another hack (Er.. hook!) for the sun3 si: */
+ if (sc->sc_intr_off) {
+ NCR_TRACE("sched: top, intr off\n", 0);
+ sc->sc_intr_off(sc);
+ }
+
+next_job:
+ /*
+ * Grab the next job from queue. Must be idle.
+ */
+#ifdef DIAGNOSTIC
+ if (sc->sc_state != NCR_IDLE)
+ panic("ncr5380_sched: not idle");
+ if (sc->sc_current)
+ panic("ncr5380_sched: current set");
+#endif
+
+ /*
+ * Always start the search where we last looked.
+ * The REQUEST_SENSE logic depends on this to
+ * choose the same job as was last picked, so it
+ * can just clear sc_current and reschedule.
+ * (Avoids loss of "contingent allegiance".)
+ */
+ i = sc->sc_rr;
+ sr = NULL;
+ do {
+ if (sc->sc_ring[i].sr_xs) {
+ target = sc->sc_ring[i].sr_target;
+ lun = sc->sc_ring[i].sr_lun;
+ if (sc->sc_matrix[target][lun] == NULL) {
+ sc->sc_matrix[target][lun] =
+ sr = &sc->sc_ring[i];
+ sc->sc_rr = i;
+ break;
+ }
+ }
+ i++;
+ if (i == SCI_OPENINGS)
+ i = 0;
+ } while (i != sc->sc_rr);
+
+ if (sr == NULL) {
+ NCR_TRACE("sched: no work, cur=0x%x\n",
+ (long) sc->sc_current);
+
+ /* Another hack (Er.. hook!) for the sun3 si: */
+ if (sc->sc_intr_on) {
+ NCR_TRACE("sched: ret, intr ON\n", 0);
+ sc->sc_intr_on(sc);
+ }
+
+ return; /* No more work to do. */
+ }
+
+ NCR_TRACE("sched: select for t/l=0x%02x\n",
+ (sr->sr_target << 4) | sr->sr_lun);
+
+ sc->sc_state = NCR_WORKING;
+ error = ncr5380_select(sc, sr);
+ if (sc->sc_current) {
+ /* Lost the race! reselected out from under us! */
+ /* Work with the reselected job. */
+ if (sr->sr_flags & SR_IMMED) {
+ printf("%s: reselected while polling (abort)\n",
+ sc->sc_dev.dv_xname);
+ /* Abort the reselected job. */
+ sc->sc_state |= NCR_ABORTING;
+ sc->sc_msgpriq |= SEND_ABORT;
+ }
+ sr = sc->sc_current;
+ xs = sr->sr_xs;
+ NCR_TRACE("sched: reselect, new sr=0x%x\n", (long)sr);
+ goto have_nexus;
+ }
+
+ /* Normal selection result */
+ sc->sc_current = sr; /* connected */
+ xs = sr->sr_xs;
+
+ /*
+ * Initialize pointers, etc. for this job
+ */
+ sc->sc_dataptr = sr->sr_dataptr;
+ sc->sc_datalen = sr->sr_datalen;
+ sc->sc_prevphase = PHASE_INVALID;
+ sc->sc_msgpriq = SEND_IDENTIFY;
+ sc->sc_msgoutq = 0;
+ sc->sc_msgout = 0;
+
+ NCR_TRACE("sched: select rv=%d\n", error);
+
+ switch (error) {
+ case XS_NOERROR:
+ break;
+
+ case XS_BUSY:
+ /* XXX - Reset and try again. */
+ printf("%s: SCSI bus busy, resetting...\n",
+ sc->sc_dev.dv_xname);
+ ncr5380_reset_scsibus(sc);
+ /* fallthrough */
+ case XS_SELTIMEOUT:
+ default:
+ xs->error = error; /* from select */
+ NCR_TRACE("sched: call done, sr=0x%x\n", (long)sr);
+ ncr5380_done(sc);
+
+ /* Paranoia: clear everything. */
+ sc->sc_dataptr = NULL;
+ sc->sc_datalen = 0;
+ sc->sc_prevphase = PHASE_INVALID;
+ sc->sc_msgpriq = 0;
+ sc->sc_msgoutq = 0;
+ sc->sc_msgout = 0;
+
+ goto next_job;
+ }
+
+ /*
+ * Selection was successful. Normally, this means
+ * we are starting a new command. However, this
+ * might be the termination of an overdue job.
+ */
+ if (sr->sr_flags & SR_OVERDUE) {
+ NCR_TRACE("sched: overdue, sr=0x%x\n", (long)sr);
+ sc->sc_state |= NCR_ABORTING;
+ sc->sc_msgpriq |= SEND_ABORT;
+ goto have_nexus;
+ }
+
+ /*
+ * This may be the continuation of some job that
+ * completed with a "check condition" code.
+ */
+ if (sr->sr_flags & SR_SENSE) {
+ NCR_TRACE("sched: get sense, sr=0x%x\n", (long)sr);
+ /* Do not allocate DMA, nor set timeout. */
+ goto have_nexus;
+ }
+
+ /*
+ * OK, we are starting a new command.
+ * Initialize and allocate resources for the new command.
+ * Device reset is special (only uses MSG_OUT phase).
+ * Normal commands start in MSG_OUT phase where we will
+ * send and IDENDIFY message, and then expect CMD phase.
+ */
+ if (ncr5380_debug & NCR_DBG_CMDS) {
+ printf("ncr5380_sched: begin, target=%d, LUN=%d\n",
+ xs->sc_link->target, xs->sc_link->lun);
+ ncr5380_show_scsi_cmd(xs);
+ }
+ if (xs->flags & SCSI_RESET) {
+ NCR_TRACE("sched: cmd=reset, sr=0x%x\n", (long)sr);
+ /* Not an error, so do not set NCR_ABORTING */
+ sc->sc_msgpriq |= SEND_DEV_RESET;
+ goto have_nexus;
+ }
+
+#ifdef DIAGNOSTIC
+ if ((xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) == 0) {
+ if (sc->sc_dataptr) {
+ printf("%s: ptr but no data in/out flags?\n");
+ NCR_BREAK();
+ sc->sc_dataptr = NULL;
+ }
+ }
+#endif
+
+ /* Allocate DMA space (maybe) */
+ if (sc->sc_dataptr && sc->sc_dma_alloc &&
+ (sc->sc_datalen >= sc->sc_min_dma_len))
+ {
+ NCR_TRACE("sched: dma_alloc, len=%d\n", sc->sc_datalen);
+ (*sc->sc_dma_alloc)(sc);
+ }
+
+ /*
+ * Initialization hook called just after select,
+ * at the beginning of COMMAND phase.
+ * (but AFTER the DMA allocation is done)
+ *
+ * The evil Sun "si" adapter (OBIO variant) needs some
+ * setup done to the DMA engine BEFORE the target puts
+ * the SCSI bus into any DATA phase.
+ */
+ if (sr->sr_dma_hand && sc->sc_dma_setup) {
+ NCR_TRACE("sched: dma_setup, dh=0x%x\n",
+ (long) sr->sr_dma_hand);
+ sc->sc_dma_setup(sc);
+ }
+
+ /*
+ * Schedule a timeout for the job we are starting.
+ */
+ if ((sr->sr_flags & SR_IMMED) == 0) {
+ i = (xs->timeout * hz) / 1000;
+ NCR_TRACE("sched: set timeout=%d\n", i);
+ timeout(ncr5380_cmd_timeout, sr, i);
+ }
+
+have_nexus:
+ NCR_TRACE("sched: call machine, cur=0x%x\n",
+ (long) sc->sc_current);
+ ncr5380_machine(sc);
+ NCR_TRACE("sched: machine done, cur=0x%x\n",
+ (long) sc->sc_current);
+
+ /*
+ * What state did ncr5380_machine() leave us in?
+ * Hopefully it sometimes completes a job...
+ */
+ if (sc->sc_state == NCR_IDLE)
+ goto next_job;
+
+ return; /* Have work in progress. */
+}
+
+
+/*
+ * Reselect handler: checks for reselection, and if we are being
+ * reselected, it sets up sc->sc_current.
+ *
+ * We are reselected when:
+ * SEL is TRUE
+ * IO is TRUE
+ * BSY is FALSE
+ */
+void
+ncr5380_reselect(sc)
+ struct ncr5380_softc *sc;
+{
+ struct sci_req *sr;
+ int target, lun, phase, timo;
+ u_char bus, data, icmd, msg;
+
+#ifdef DIAGNOSTIC
+ /*
+ * Note: sc_state will be "idle" when ncr5380_intr()
+ * calls, or "working" when ncr5380_select() calls.
+ * (So don't test that in this DIAGNOSTIC)
+ */
+ if (sc->sc_current)
+ panic("ncr5380_reselect: current set");
+#endif
+
+ /*
+ * First, check the select line.
+ * (That has to be set first.)
+ */
+ bus = *(sc->sci_bus_csr);
+ if ((bus & SCI_BUS_SEL) == 0) {
+ /* Not a selection or reselection. */
+ return;
+ }
+
+ /*
+ * The target will assert BSY first (for bus arbitration),
+ * then raise SEL, and finally drop BSY. Only then is the
+ * data bus required to have valid selection ID bits set.
+ * Wait for: SEL==1, BSY==0 before reading the data bus.
+ */
+ timo = ncr5380_wait_nrq_timo;
+ for (;;) {
+ if ((bus & SCI_BUS_BSY) == 0)
+ break;
+ /* Probably never get here... */
+ if (--timo <= 0) {
+ printf("%s: reselect, BSY stuck, bus=0x%x\n",
+ sc->sc_dev.dv_xname, bus);
+ /* Not much we can do. Reset the bus. */
+ ncr5380_reset_scsibus(sc);
+ return;
+ }
+ delay(10);
+ bus = *(sc->sci_bus_csr);
+ /* If SEL went away, forget it. */
+ if ((bus & SCI_BUS_SEL) == 0)
+ return;
+ /* Still have SEL, check BSY. */
+ }
+ NCR_TRACE("reselect, valid data after %d loops\n",
+ ncr5380_wait_nrq_timo - timo);
+
+ /*
+ * Good. We have SEL=1 and BSY=0. Now wait for a
+ * "bus settle delay" before we sample the data bus
+ */
+ delay(2);
+ data = *(sc->sci_data) & 0xFF;
+ /* XXX - Should check parity... */
+
+ /*
+ * Is this a reselect (I/O == 1) or have we been
+ * selected as a target? (I/O == 0)
+ */
+ if ((bus & SCI_BUS_IO) == 0) {
+ printf("%s: selected as target, data=0x%x\n",
+ sc->sc_dev.dv_xname, data);
+ /* Not much we can do. Reset the bus. */
+ ncr5380_reset_scsibus(sc);
+ return;
+ }
+
+ /*
+ * OK, this is a reselection.
+ */
+ for (target = 0; target < 7; target++)
+ if (data & (1 << target))
+ break;
+
+ if ((data & 0x7F) != (1 << target)) {
+ /* No selecting ID? or >2 IDs on bus? */
+ printf("%s: bad reselect, data=0x%x\n",
+ sc->sc_dev.dv_xname, data);
+ return;
+ }
+
+ NCR_TRACE("reselect: target=0x%x\n", target);
+
+ /* Raise BSY to acknowledge target reselection. */
+ SetReg ( sc->sci_icmd, SCI_ICMD_BSY );
+/* *(sc->sci_icmd) = SCI_ICMD_BSY; */
+
+ /* Wait for target to drop SEL. */
+ timo = ncr5380_wait_nrq_timo;
+ for (;;) {
+ bus = *(sc->sci_bus_csr);
+ if ((bus & SCI_BUS_SEL) == 0)
+ break; /* success */
+ if (--timo <= 0) {
+ printf("%s: reselect, SEL stuck, bus=0x%x\n",
+ sc->sc_dev.dv_xname, bus);
+ NCR_BREAK();
+ /* assume connected (fail later if not) */
+ break;
+ }
+ delay(2);
+ }
+
+ /* Now we drop BSY, and we are connected. */
+ SetReg ( sc->sci_icmd, 0 );
+ SetReg ( sc->sci_sel_enb, 0 );
+/* *(sc->sci_icmd) = 0;
+ *sc->sci_sel_enb = 0; */
+ SCI_CLR_INTR(sc);
+
+ /*
+ * At this point the target should send an IDENTIFY message,
+ * which will permit us to determine the reselecting LUN.
+ * If not, we assume LUN 0.
+ */
+ lun = 0;
+ /* Wait for REQ before reading bus phase. */
+ if (ncr5380_wait_req(sc)) {
+ printf("%s: reselect, no REQ\n",
+ sc->sc_dev.dv_xname);
+ /* Try to send an ABORT message. */
+ goto abort;
+ }
+ phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
+ if (phase != PHASE_MSG_IN) {
+ printf("%s: reselect, phase=%d\n",
+ sc->sc_dev.dv_xname, phase);
+ goto abort;
+ }
+
+ /* Ack. the change to PHASE_MSG_IN */
+ SetReg ( sc->sci_tcmd, PHASE_MSG_IN );
+/* *(sc->sci_tcmd) = PHASE_MSG_IN; */
+
+ /* Peek at the message byte without consuming it! */
+ msg = *(sc->sci_data);
+ if ((msg & 0x80) == 0) {
+ printf("%s: reselect, not identify, msg=%d\n",
+ sc->sc_dev.dv_xname, msg);
+ goto abort;
+ }
+ lun = msg & 7;
+
+ /* We now know target/LUN. Do we have the request? */
+ sr = sc->sc_matrix[target][lun];
+ if (sr) {
+ /* We now have a nexus. */
+ sc->sc_state |= NCR_WORKING;
+ sc->sc_current = sr;
+ NCR_TRACE("reselect: resume sr=0x%x\n", (long)sr);
+
+ /* Implicit restore pointers message */
+ sc->sc_dataptr = sr->sr_dataptr;
+ sc->sc_datalen = sr->sr_datalen;
+
+ sc->sc_prevphase = PHASE_INVALID;
+ sc->sc_msgpriq = 0;
+ sc->sc_msgoutq = 0;
+ sc->sc_msgout = 0;
+
+ /*
+ * Another hack for the Sun3 "si", which needs
+ * some setup done to its DMA engine before the
+ * target puts the SCSI bus into any DATA phase.
+ */
+ if (sr->sr_dma_hand && sc->sc_dma_setup) {
+ NCR_TRACE("reselect: call DMA setup, dh=0x%x\n",
+ (long) sr->sr_dma_hand);
+ sc->sc_dma_setup(sc);
+ }
+
+ /* Now consume the IDENTIFY message. */
+ ncr5380_pio_in(sc, PHASE_MSG_IN, 1, &msg);
+ return;
+ }
+
+ printf("%s: phantom reselect: target=%d, LUN=%d\n",
+ sc->sc_dev.dv_xname, target, lun);
+abort:
+ /*
+ * Try to send an ABORT message. This makes us
+ * temporarily busy, but no current command...
+ */
+ sc->sc_state |= NCR_ABORTING;
+
+ /* Raise ATN, delay, raise ACK... */
+ icmd = SCI_ICMD_ATN;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+ delay(2);
+
+ /* Now consume the IDENTIFY message. */
+ ncr5380_pio_in(sc, PHASE_MSG_IN, 1, &msg);
+
+ /* Finally try to send the ABORT. */
+ sc->sc_prevphase = PHASE_INVALID;
+ sc->sc_msgpriq = SEND_ABORT;
+ ncr5380_msg_out(sc);
+
+ SetReg ( sc->sci_tcmd, PHASE_INVALID );
+ SetReg ( sc->sci_sel_enb, 0 );
+/* *(sc->sci_tcmd) = PHASE_INVALID;
+ *sc->sci_sel_enb = 0; */
+ SCI_CLR_INTR(sc);
+ SetReg ( sc->sci_sel_enb, 0x80 );
+/* *sc->sci_sel_enb = 0x80; */
+
+ sc->sc_state &= ~NCR_ABORTING;
+}
+
+
+/*
+ * Select target: xs is the transfer that we are selecting for.
+ * sc->sc_current should be NULL.
+ *
+ * Returns:
+ * sc->sc_current != NULL ==> we were reselected (race!)
+ * XS_NOERROR ==> selection worked
+ * XS_BUSY ==> lost arbitration
+ * XS_SELTIMEOUT ==> no response to selection
+ */
+static int
+ncr5380_select(sc, sr)
+ struct ncr5380_softc *sc;
+ struct sci_req *sr;
+{
+ int timo;
+ u_char bus, data, icmd;
+
+ /* Check for reselect */
+ ncr5380_reselect(sc);
+ if (sc->sc_current) {
+ NCR_TRACE("select: reselect, cur=0x%x\n",
+ (long) sc->sc_current);
+ return XS_BUSY; /* reselected */
+ }
+
+ /*
+ * Set phase bits to 0, otherwise the 5380 won't drive the bus during
+ * selection.
+ */
+
+ SetReg ( sc->sci_tcmd, PHASE_DATA_OUT );
+ SetReg ( sc->sci_icmd, 0 );
+ SetReg ( sc->sci_mode, 0 );
+
+/* *sc->sci_tcmd = PHASE_DATA_OUT;
+ *sc->sci_icmd = icmd = 0;
+ *sc->sci_mode = 0; */
+
+ /*
+ * Arbitrate for the bus. The 5380 takes care of the
+ * time-critical bus interactions. We set our ID bit
+ * in the output data register and set MODE_ARB. The
+ * 5380 watches for the required "bus free" period.
+ * If and when the "bus free" period is detected, the
+ * 5380 then drives BSY, drives the data bus, and sets
+ * the "arbitration in progress" (AIP) bit to let us
+ * know arbitration has started. We then wait for one
+ * arbitration delay (2.2uS) and check the ICMD_LST bit,
+ * which will be set if someone else drives SEL.
+ */
+
+ SetReg ( sc->sci_odata, 0x80 );
+ SetReg ( sc->sci_mode, SCI_MODE_ARB );
+
+/* *(sc->sci_odata) = 0x80; */ /* OUR_ID */
+/* *(sc->sci_mode) = SCI_MODE_ARB; */
+
+ /* Wait for ICMD_AIP. */
+ timo = ncr5380_wait_req_timo;
+ for (;;) {
+ if (*(sc->sci_icmd) & SCI_ICMD_AIP)
+ break;
+ if (--timo <= 0) {
+ /* Did not see any "bus free" period. */
+ SetReg ( sc->sci_mode, 0 );
+/* *sc->sci_mode = 0; */
+ NCR_TRACE("select: bus busy, rc=%d\n", XS_BUSY);
+ return XS_BUSY;
+ }
+ delay(2);
+ }
+ NCR_TRACE("select: have AIP after %d loops\n",
+ ncr5380_wait_req_timo - timo);
+
+ /* Got AIP. Wait one arbitration delay (2.2 uS.) */
+ delay(3);
+
+ /* Check for ICMD_LST */
+ if (*(sc->sci_icmd) & SCI_ICMD_LST) {
+ /* Some other target asserted SEL. */
+ SetReg ( sc->sci_mode, 0 );
+/* *sc->sci_mode = 0; */
+ NCR_TRACE("select: lost one, rc=%d\n", XS_BUSY);
+ ncr5380_reselect(sc); /* XXX */
+ return XS_BUSY;
+ }
+
+ /*
+ * No other device has declared itself the winner.
+ * The spec. says to check for higher IDs, but we
+ * are always the highest (ID=7) so don't bother.
+ * We can now declare victory by asserting SEL.
+ *
+ * Note that the 5380 is asserting BSY because we
+ * asked it to do arbitration. We will now hold
+ * BSY directly so we can turn off ARB mode.
+ */
+ icmd = (SCI_ICMD_BSY | SCI_ICMD_SEL);
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ /*
+ * "The SCSI device that wins arbitration shall wait
+ * at least a bus clear delay plus a bus settle delay
+ * after asserting the SEL signal before changing
+ * any [other] signal." (1.2uS. total)
+ */
+ delay(2);
+
+#if 1
+ /*
+ * XXX: Check one last time to see if we really
+ * XXX: did win arbitration. (too paranoid?)
+ */
+ if (*(sc->sci_icmd) & SCI_ICMD_LST) {
+ SetReg ( sc->sci_icmd, 0 );
+ SetReg ( sc->sci_mode, 0 );
+/* *sc->sci_icmd = 0;
+ *sc->sci_mode = 0; */
+ NCR_TRACE("select: lost two, rc=%d\n", XS_BUSY);
+ return XS_BUSY;
+ }
+#endif
+ /* Leave ARB mode Now that we drive BSY+SEL */
+ SetReg ( sc->sci_mode, 0 );
+ SetReg ( sc->sci_sel_enb, 0 );
+/* *sc->sci_mode = 0;
+ *sc->sci_sel_enb = 0; */
+
+ /*
+ * Arbitration is complete. Now do selection:
+ * Drive the data bus with the ID bits for both
+ * the host and target. Also set ATN now, to
+ * ask the target for a messgae out phase.
+ */
+ data = 0x80 | (1 << sr->sr_target);
+ SetReg ( sc->sci_odata, data );
+/* *(sc->sci_odata) = data; */
+ icmd |= (SCI_ICMD_DATA | SCI_ICMD_ATN);
+ SetReg ( sc->sci_icmd, icmd );
+ *(sc->sci_icmd) = icmd;
+ delay(2); /* two deskew delays. */
+
+ /* De-assert BSY (targets sample the data now). */
+ icmd &= ~SCI_ICMD_BSY;
+ SetReg ( sc->sci_icmd, icmd );
+/* *(sc->sci_icmd) = icmd; */
+ delay(3); /* Bus settle delay. */
+
+ /*
+ * Wait for the target to assert BSY.
+ * SCSI spec. says wait for 250 mS.
+ */
+ for (timo = 25000;;) {
+ if (*sc->sci_bus_csr & SCI_BUS_BSY)
+ goto success;
+ if (--timo <= 0)
+ break;
+ delay(10);
+ }
+
+ /*
+ * There is no reaction from the target. Start the selection
+ * timeout procedure. We release the databus but keep SEL+ATN
+ * asserted. After that we wait a 'selection abort time' (200
+ * usecs) and 2 deskew delays (90 ns) and check BSY again.
+ * When BSY is asserted, we assume the selection succeeded,
+ * otherwise we release the bus.
+ */
+ icmd &= ~SCI_ICMD_DATA;
+ SetReg ( sc->sci_icmd, icmd );
+/* *(sc->sci_icmd) = icmd; */
+ delay(201);
+ if ((*sc->sci_bus_csr & SCI_BUS_BSY) == 0) {
+ /* Really no device on bus */
+ SetReg ( sc->sci_tcmd, PHASE_INVALID );
+ SetReg ( sc->sci_icmd, 0 );
+ SetReg ( sc->sci_mode, 0 );
+ SetReg ( sc->sci_sel_enb, 0 );
+/* *sc->sci_tcmd = PHASE_INVALID;
+ *sc->sci_icmd = 0;
+ *sc->sci_mode = 0;
+ *sc->sci_sel_enb = 0; */
+ SCI_CLR_INTR(sc);
+ SetReg ( sc->sci_sel_enb, 0x80 );
+ *sc->sci_sel_enb = 0x80;
+ NCR_TRACE("select: device down, rc=%d\n", XS_SELTIMEOUT);
+ return XS_SELTIMEOUT;
+ }
+
+success:
+ /*
+ * The target is now driving BSY, so we can stop
+ * driving SEL and the data bus (keep ATN true).
+ * Configure the ncr5380 to monitor BSY, parity.
+ */
+ icmd &= ~(SCI_ICMD_DATA | SCI_ICMD_SEL);
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ /* XXX - Make parity checking optional? */
+ SetReg ( sc->sci_mode, (SCI_MODE_MONBSY) );
+/* SetReg ( sc->sci_mode, (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK) ); */
+/* *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK); */
+
+ return XS_NOERROR;
+}
+
+
+/*****************************************************************
+ * Functions to handle each info. transfer phase:
+ *****************************************************************/
+
+/*
+ * The message system:
+ *
+ * This is a revamped message system that now should easier accomodate
+ * new messages, if necessary.
+ *
+ * Currently we accept these messages:
+ * IDENTIFY (when reselecting)
+ * COMMAND COMPLETE # (expect bus free after messages marked #)
+ * NOOP
+ * MESSAGE REJECT
+ * SYNCHRONOUS DATA TRANSFER REQUEST
+ * SAVE DATA POINTER
+ * RESTORE POINTERS
+ * DISCONNECT #
+ *
+ * We may send these messages in prioritized order:
+ * BUS DEVICE RESET # if SCSI_RESET & xs->flags (or in weird sits.)
+ * MESSAGE PARITY ERROR par. err. during MSGI
+ * MESSAGE REJECT If we get a message we don't know how to handle
+ * ABORT # send on errors
+ * INITIATOR DETECTED ERROR also on errors (SCSI2) (during info xfer)
+ * IDENTIFY At the start of each transfer
+ * SYNCHRONOUS DATA TRANSFER REQUEST if appropriate
+ * NOOP if nothing else fits the bill ...
+ */
+
+#define IS1BYTEMSG(m) (((m) != 0x01 && (m) < 0x20) || (m) >= 0x80)
+#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
+#define ISEXTMSG(m) ((m) == 0x01)
+
+/*
+ * Precondition:
+ * The SCSI bus is already in the MSGI phase and there is a message byte
+ * on the bus, along with an asserted REQ signal.
+ *
+ * Our return value determines whether our caller, ncr5380_machine()
+ * will expect to see another REQ (and possibly phase change).
+ */
+static int
+ncr5380_msg_in(sc)
+ register struct ncr5380_softc *sc;
+{
+ struct sci_req *sr = sc->sc_current;
+ int n, phase, timo;
+ int act_flags;
+ register u_char icmd;
+
+ /* acknowledge phase change */
+ SetReg ( sc->sci_tcmd, PHASE_MSG_IN );
+/* *sc->sci_tcmd = PHASE_MSG_IN; */
+
+ act_flags = ACT_CONTINUE;
+ icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
+
+ if (sc->sc_prevphase == PHASE_MSG_IN) {
+ /* This is a continuation of the previous message. */
+ n = sc->sc_imp - sc->sc_imess;
+ NCR_TRACE("msg_in: continuation, n=%d\n", n);
+ goto nextbyte;
+ }
+
+ /* This is a new MESSAGE IN phase. Clean up our state. */
+ sc->sc_state &= ~NCR_DROP_MSGIN;
+
+nextmsg:
+ n = 0;
+ sc->sc_imp = &sc->sc_imess[n];
+
+nextbyte:
+ /*
+ * Read a whole message, but don't ack the last byte. If we reject the
+ * message, we have to assert ATN during the message transfer phase
+ * itself.
+ */
+ for (;;) {
+ /*
+ * Read a message byte.
+ * First, check BSY, REQ, phase...
+ */
+ if (!SCI_BUSY(sc)) {
+ NCR_TRACE("msg_in: lost BSY, n=%d\n", n);
+ /* XXX - Assume the command completed? */
+ act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+ return (act_flags);
+ }
+ if (ncr5380_wait_req(sc)) {
+ NCR_TRACE("msg_in: BSY but no REQ, n=%d\n", n);
+ /* Just let ncr5380_machine() handle it... */
+ return (act_flags);
+ }
+ phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
+ if (phase != PHASE_MSG_IN) {
+ /*
+ * Target left MESSAGE IN, probably because it
+ * a) noticed our ATN signal, or
+ * b) ran out of messages.
+ */
+ return (act_flags);
+ }
+ /* Still in MESSAGE IN phase, and REQ is asserted. */
+ if (*sc->sci_csr & SCI_CSR_PERR) {
+ ncr_sched_msgout(sc, SEND_PARITY_ERROR);
+ sc->sc_state |= NCR_DROP_MSGIN;
+ }
+
+ /* Gather incoming message bytes if needed. */
+ if ((sc->sc_state & NCR_DROP_MSGIN) == 0) {
+ if (n >= NCR_MAX_MSG_LEN) {
+ ncr_sched_msgout(sc, SEND_REJECT);
+ sc->sc_state |= NCR_DROP_MSGIN;
+ } else {
+ *sc->sc_imp++ = *sc->sci_data;
+ n++;
+ /*
+ * This testing is suboptimal, but most
+ * messages will be of the one byte variety, so
+ * it should not affect performance
+ * significantly.
+ */
+ if (n == 1 && IS1BYTEMSG(sc->sc_imess[0]))
+ goto have_msg;
+ if (n == 2 && IS2BYTEMSG(sc->sc_imess[0]))
+ goto have_msg;
+ if (n >= 3 && ISEXTMSG(sc->sc_imess[0]) &&
+ n == sc->sc_imess[1] + 2)
+ goto have_msg;
+ }
+ }
+
+ /*
+ * If we reach this spot we're either:
+ * a) in the middle of a multi-byte message, or
+ * b) dropping bytes.
+ */
+
+ /* Ack the last byte read. */
+ icmd |= SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ if (ncr5380_wait_not_req(sc)) {
+ NCR_TRACE("msg_in: drop, stuck REQ, n=%d\n", n);
+ act_flags |= ACT_RESET_BUS;
+ }
+
+ icmd &= ~SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ if (act_flags != ACT_CONTINUE)
+ return (act_flags);
+
+ /* back to nextbyte */
+ }
+
+have_msg:
+ /* We now have a complete message. Parse it. */
+
+ switch (sc->sc_imess[0]) {
+ case MSG_CMDCOMPLETE:
+ NCR_TRACE("msg_in: CMDCOMPLETE\n", 0);
+ /* Target is about to disconnect. */
+ act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+ break;
+
+ case MSG_DISCONNECT:
+ NCR_TRACE("msg_in: DISCONNECT\n", 0);
+ /* Target is about to disconnect. */
+ act_flags |= ACT_DISCONNECT;
+ break;
+
+ case MSG_PARITY_ERROR:
+ NCR_TRACE("msg_in: PARITY_ERROR\n", 0);
+ /* Resend the last message. */
+ ncr_sched_msgout(sc, sc->sc_msgout);
+ break;
+
+ case MSG_MESSAGE_REJECT:
+ /* The target rejects the last message we sent. */
+ NCR_TRACE("msg_in: got reject for 0x%x\n", sc->sc_msgout);
+ switch (sc->sc_msgout) {
+ case SEND_IDENTIFY:
+ /* Really old target controller? */
+ /* XXX ... */
+ break;
+ case SEND_INIT_DET_ERR:
+ goto abort;
+ }
+ break;
+
+ case MSG_NOOP:
+ NCR_TRACE("msg_in: NOOP\n", 0);
+ break;
+
+ case MSG_SAVEDATAPOINTER:
+ NCR_TRACE("msg_in: SAVE_PTRS\n", 0);
+ sr->sr_dataptr = sc->sc_dataptr;
+ sr->sr_datalen = sc->sc_datalen;
+ break;
+
+ case MSG_RESTOREPOINTERS:
+ NCR_TRACE("msg_in: RESTORE_PTRS\n", 0);
+ sc->sc_dataptr = sr->sr_dataptr;
+ sc->sc_datalen = sr->sr_datalen;
+ break;
+
+ case MSG_EXTENDED:
+ switch (sc->sc_imess[2]) {
+ case MSG_EXT_SDTR:
+ case MSG_EXT_WDTR:
+ /* The ncr5380 can not do synchronous mode. */
+ goto reject;
+ default:
+ printf("%s: unrecognized MESSAGE EXTENDED; sending REJECT\n",
+ sc->sc_dev.dv_xname);
+ NCR_BREAK();
+ goto reject;
+ }
+ break;
+
+ default:
+ NCR_TRACE("msg_in: eh? imsg=0x%x\n", sc->sc_imess[0]);
+ printf("%s: unrecognized MESSAGE; sending REJECT\n",
+ sc->sc_dev.dv_xname);
+ NCR_BREAK();
+ /* fallthrough */
+ reject:
+ ncr_sched_msgout(sc, SEND_REJECT);
+ break;
+
+ abort:
+ sc->sc_state |= NCR_ABORTING;
+ ncr_sched_msgout(sc, SEND_ABORT);
+ break;
+ }
+
+ /* Ack the last byte read. */
+ icmd |= SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ if (ncr5380_wait_not_req(sc)) {
+ NCR_TRACE("msg_in: last, stuck REQ, n=%d\n", n);
+ act_flags |= ACT_RESET_BUS;
+ }
+
+ icmd &= ~SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ /* Go get the next message, if any. */
+ if (act_flags == ACT_CONTINUE)
+ goto nextmsg;
+
+ return (act_flags);
+}
+
+
+/*
+ * The message out (and in) stuff is a bit complicated:
+ * If the target requests another message (sequence) without
+ * having changed phase in between it really asks for a
+ * retransmit, probably due to parity error(s).
+ * The following messages can be sent:
+ * IDENTIFY @ These 4 stem from SCSI command activity
+ * SDTR @
+ * WDTR @
+ * DEV_RESET @
+ * REJECT if MSGI doesn't make sense
+ * PARITY_ERROR if parity error while in MSGI
+ * INIT_DET_ERR if parity error while not in MSGI
+ * ABORT if INIT_DET_ERR rejected
+ * NOOP if asked for a message and there's nothing to send
+ *
+ * Note that we call this one with (sc_current == NULL)
+ * when sending ABORT for unwanted reselections.
+ */
+static int
+ncr5380_msg_out(sc)
+ register struct ncr5380_softc *sc;
+{
+ struct sci_req *sr = sc->sc_current;
+ int n, phase, resel;
+ int progress, act_flags;
+ register u_char icmd;
+
+ /* acknowledge phase change */
+ SetReg ( sc->sci_tcmd, PHASE_MSG_OUT );
+/* *sc->sci_tcmd = PHASE_MSG_OUT; */
+
+ progress = 0; /* did we send any messages? */
+ act_flags = ACT_CONTINUE;
+
+ /*
+ * Set ATN. If we're just sending a trivial 1-byte message,
+ * we'll clear ATN later on anyway. Also drive the data bus.
+ */
+ icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
+ icmd |= (SCI_ICMD_ATN | SCI_ICMD_DATA);
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ if (sc->sc_prevphase == PHASE_MSG_OUT) {
+ if (sc->sc_omp == sc->sc_omess) {
+ /*
+ * This is a retransmission.
+ *
+ * We get here if the target stayed in MESSAGE OUT
+ * phase. Section 5.1.9.2 of the SCSI 2 spec indicates
+ * that all of the previously transmitted messages must
+ * be sent again, in the same order. Therefore, we
+ * requeue all the previously transmitted messages, and
+ * start again from the top. Our simple priority
+ * scheme keeps the messages in the right order.
+ */
+ sc->sc_msgpriq |= sc->sc_msgoutq;
+ NCR_TRACE("msg_out: retrans priq=0x%x\n", sc->sc_msgpriq);
+ } else {
+ /* This is a continuation of the previous message. */
+ n = sc->sc_omp - sc->sc_omess;
+ NCR_TRACE("msg_out: continuation, n=%d\n", n);
+ goto nextbyte;
+ }
+ }
+
+ /* No messages transmitted so far. */
+ sc->sc_msgoutq = 0;
+
+nextmsg:
+ /* Pick up highest priority message. */
+ sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq;
+ sc->sc_msgpriq &= ~sc->sc_msgout;
+ sc->sc_msgoutq |= sc->sc_msgout;
+
+ /* Build the outgoing message data. */
+ switch (sc->sc_msgout) {
+ case SEND_IDENTIFY:
+ NCR_TRACE("msg_out: SEND_IDENTIFY\n", 0);
+ if (sr == NULL) {
+ printf("%s: SEND_IDENTIFY while not connected; sending NOOP\n",
+ sc->sc_dev.dv_xname);
+ NCR_BREAK();
+ goto noop;
+ }
+ resel = (sc->sc_flags & NCR5380_PERMIT_RESELECT) ? 1 : 0;
+ resel &= (sr->sr_flags & (SR_IMMED | SR_SENSE)) ? 0 : 1;
+ sc->sc_omess[0] = MSG_IDENTIFY(sr->sr_lun, resel);
+ n = 1;
+ break;
+
+ case SEND_DEV_RESET:
+ NCR_TRACE("msg_out: SEND_DEV_RESET\n", 0);
+ /* Expect disconnect after this! */
+ /* XXX: Kill jobs for this target? */
+ act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+ sc->sc_omess[0] = MSG_BUS_DEV_RESET;
+ n = 1;
+ break;
+
+ case SEND_REJECT:
+ NCR_TRACE("msg_out: SEND_REJECT\n", 0);
+ sc->sc_omess[0] = MSG_MESSAGE_REJECT;
+ n = 1;
+ break;
+
+ case SEND_PARITY_ERROR:
+ NCR_TRACE("msg_out: SEND_PARITY_ERROR\n", 0);
+ sc->sc_omess[0] = MSG_PARITY_ERROR;
+ n = 1;
+ break;
+
+ case SEND_INIT_DET_ERR:
+ NCR_TRACE("msg_out: SEND_INIT_DET_ERR\n", 0);
+ sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
+ n = 1;
+ break;
+
+ case SEND_ABORT:
+ NCR_TRACE("msg_out: SEND_ABORT\n", 0);
+ /* Expect disconnect after this! */
+ /* XXX: Set error flag? */
+ act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+ sc->sc_omess[0] = MSG_ABORT;
+ n = 1;
+ break;
+
+ case 0:
+ printf("%s: unexpected MESSAGE OUT; sending NOOP\n",
+ sc->sc_dev.dv_xname);
+ NCR_BREAK();
+ noop:
+ NCR_TRACE("msg_out: send NOOP\n", 0);
+ sc->sc_omess[0] = MSG_NOOP;
+ n = 1;
+ break;
+
+ default:
+ printf("%s: weird MESSAGE OUT; sending NOOP\n",
+ sc->sc_dev.dv_xname);
+ NCR_BREAK();
+ goto noop;
+ }
+ sc->sc_omp = &sc->sc_omess[n];
+
+nextbyte:
+ /* Send message bytes. */
+ while (n > 0) {
+ /*
+ * Send a message byte.
+ * First check BSY, REQ, phase...
+ */
+ if (!SCI_BUSY(sc)) {
+ NCR_TRACE("msg_out: lost BSY, n=%d\n", n);
+ goto out;
+ }
+ if (ncr5380_wait_req(sc)) {
+ NCR_TRACE("msg_out: no REQ, n=%d\n", n);
+ goto out;
+ }
+ phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
+ if (phase != PHASE_MSG_OUT) {
+ /*
+ * Target left MESSAGE OUT, possibly to reject
+ * our message.
+ */
+ NCR_TRACE("msg_out: new phase=%d\n", phase);
+ goto out;
+ }
+
+ /* Yes, we can send this message byte. */
+ --n;
+
+ /* Clear ATN before last byte if this is the last message. */
+ if (n == 0 && sc->sc_msgpriq == 0) {
+ icmd &= ~SCI_ICMD_ATN;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+ /* 2 deskew delays */
+ delay(2); /* XXX */
+ }
+
+ /* Put data on the bus. */
+ sc->sc_omp--;
+ SetReg ( sc->sci_odata, *sc->sc_omp );
+/* *sc->sci_odata = *--sc->sc_omp; */
+
+ /* Raise ACK to tell target data is on the bus. */
+ icmd |= SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ /* Wait for REQ to be negated. */
+ if (ncr5380_wait_not_req(sc)) {
+ NCR_TRACE("msg_out: stuck REQ, n=%d\n", n);
+ act_flags |= ACT_RESET_BUS;
+ }
+
+ /* Finally, drop ACK. */
+ icmd &= ~SCI_ICMD_ACK;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ /* Stuck bus or something... */
+ if (act_flags & ACT_RESET_BUS)
+ goto out;
+
+ }
+ progress++;
+
+ /* We get here only if the entire message has been transmitted. */
+ if (sc->sc_msgpriq != 0) {
+ /* There are more outgoing messages. */
+ goto nextmsg;
+ }
+
+ /*
+ * The last message has been transmitted. We need to remember the last
+ * message transmitted (in case the target switches to MESSAGE IN phase
+ * and sends a MESSAGE REJECT), and the list of messages transmitted
+ * this time around (in case the target stays in MESSAGE OUT phase to
+ * request a retransmit).
+ */
+
+out:
+ /* Stop driving the data bus. */
+ icmd &= ~SCI_ICMD_DATA;
+ SetReg ( sc->sci_icmd, icmd );
+/* *sc->sci_icmd = icmd; */
+
+ if (!progress)
+ act_flags |= ACT_RESET_BUS;
+
+ return (act_flags);
+}
+
+
+/*
+ * Handle command phase.
+ */
+static int
+ncr5380_command(sc)
+ struct ncr5380_softc *sc;
+{
+ struct sci_req *sr = sc->sc_current;
+ struct scsi_xfer *xs = sr->sr_xs;
+ struct scsi_sense rqs;
+ int len;
+
+ /* acknowledge phase change */
+ SetReg ( sc->sci_tcmd, PHASE_COMMAND );
+/* *sc->sci_tcmd = PHASE_COMMAND; */
+
+ if (sr->sr_flags & SR_SENSE) {
+ rqs.opcode = REQUEST_SENSE;
+ rqs.byte2 = xs->sc_link->lun << 5;
+ rqs.length = sizeof(xs->sense);
+
+ rqs.unused[0] = rqs.unused[1] = rqs.control = 0;
+ len = ncr5380_pio_out(sc, PHASE_COMMAND, sizeof(rqs),
+ (u_char *)&rqs);
+ }
+ else {
+ /* Assume command can be sent in one go. */
+ /* XXX: Do this using DMA, and get a phase change intr? */
+ len = ncr5380_pio_out(sc, PHASE_COMMAND, xs->cmdlen,
+ (u_char *)xs->cmd);
+ }
+
+ if (len != xs->cmdlen) {
+#ifdef DEBUG
+ printf("ncr5380_command: short transfer: wanted %d got %d.\n",
+ xs->cmdlen, len);
+ ncr5380_show_scsi_cmd(xs);
+ NCR_BREAK();
+#endif
+ if (len < 6) {
+ xs->error = XS_DRIVER_STUFFUP;
+ sc->sc_state |= NCR_ABORTING;
+ ncr_sched_msgout(sc, SEND_ABORT);
+ }
+
+ }
+
+ return ACT_CONTINUE;
+}
+
+
+/*
+ * Handle either data_in or data_out
+ */
+static int
+ncr5380_data_xfer(sc, phase)
+ struct ncr5380_softc *sc;
+ int phase;
+{
+ struct sci_req *sr = sc->sc_current;
+ struct scsi_xfer *xs = sr->sr_xs;
+ int expected_phase;
+ int i, len;
+
+ if (sr->sr_flags & SR_SENSE) {
+ NCR_TRACE("data_xfer: get sense, sr=0x%x\n", (long)sr);
+ if (phase != PHASE_DATA_IN) {
+ printf("%s: sense phase error\n", sc->sc_dev.dv_xname);
+ goto abort;
+ }
+ /* acknowledge phase change */
+ SetReg ( sc->sci_tcmd, PHASE_DATA_IN );
+/* *sc->sci_tcmd = PHASE_DATA_IN; */
+ len = ncr5380_pio_in(sc, phase, sizeof(xs->sense),
+ (u_char *)&xs->sense);
+ return ACT_CONTINUE;
+ }
+
+ /*
+ * When aborting a command, disallow any data phase.
+ */
+ if (sc->sc_state & NCR_ABORTING) {
+ printf("%s: aborting, but phase=%s (reset)\n",
+ sc->sc_dev.dv_xname,
+ phase_names[phase & 7]);
+ return ACT_RESET_BUS; /* XXX */
+ }
+
+ /* Validate expected phase (data_in or data_out) */
+ expected_phase = (xs->flags & SCSI_DATA_OUT) ?
+ PHASE_DATA_OUT : PHASE_DATA_IN;
+ if (phase != expected_phase) {
+ printf("%s: data phase error\n",
+ sc->sc_dev.dv_xname);
+ goto abort;
+ }
+
+ /* Make sure we have some data to move. */
+ if (sc->sc_datalen <= 0) {
+ printf("%s: can not transfer more data\n",
+ sc->sc_dev.dv_xname);
+ goto abort;
+ }
+
+ /*
+ * Attempt DMA only if dma_alloc gave us a DMA handle AND
+ * there is enough left to transfer so DMA is worth while.
+ */
+ if (sr->sr_dma_hand &&
+ (sc->sc_datalen >= sc->sc_min_dma_len))
+ {
+ /*
+ * OK, really start DMA. Note, the MI start function
+ * is responsible for setting the TCMD register, etc.
+ * (Acknowledge the phase change there, not here.)
+ */
+ NCR_TRACE("data_xfer: dma_start, dh=0x%x\n",
+ (long) sr->sr_dma_hand);
+ (*sc->sc_dma_start)(sc);
+ return ACT_WAIT_DMA;
+ }
+
+ NCR_TRACE("data_xfer: doing PIO, len=%d\n", sc->sc_datalen);
+
+ /* acknowledge phase change */
+ SetReg ( sc->sci_tcmd, phase );
+/* *sc->sci_tcmd = phase; */
+ if (phase == PHASE_DATA_OUT) {
+ len = ncr5380_pio_out(sc, phase, sc->sc_datalen, sc->sc_dataptr);
+ } else {
+ len = ncr5380_pio_in (sc, phase, sc->sc_datalen, sc->sc_dataptr);
+ }
+ sc->sc_dataptr += len;
+ sc->sc_datalen -= len;
+
+ NCR_TRACE("data_xfer: did PIO, resid=%d\n", sc->sc_datalen);
+ return (ACT_CONTINUE);
+
+abort:
+ sc->sc_state |= NCR_ABORTING;
+ ncr_sched_msgout(sc, SEND_ABORT);
+ return (ACT_CONTINUE);
+}
+
+
+static int
+ncr5380_status(sc)
+ struct ncr5380_softc *sc;
+{
+ int len;
+ u_char status;
+ struct sci_req *sr = sc->sc_current;
+ struct scsi_xfer *xs = sr->sr_xs;
+
+ /* acknowledge phase change */
+ SetReg ( sc->sci_tcmd, PHASE_STATUS );
+/* *sc->sci_tcmd = PHASE_STATUS; */
+
+ len = ncr5380_pio_in(sc, PHASE_STATUS, 1, &status);
+ if (len) {
+ sr->sr_status = status;
+ } else {
+ printf("ncr5380_status: none?\n");
+ }
+
+ return ACT_CONTINUE;
+}
+
+
+/*
+ * This is the big state machine that follows SCSI phase changes.
+ * This is somewhat like a co-routine. It will do a SCSI command,
+ * and exit if the command is complete, or if it must wait, i.e.
+ * for DMA to complete or for reselect to resume the job.
+ *
+ * The bus must be selected, and we need to know which command is
+ * being undertaken.
+ */
+static void
+ncr5380_machine(sc)
+ struct ncr5380_softc *sc;
+{
+ struct sci_req *sr;
+ struct scsi_xfer *xs;
+ int act_flags, phase, timo;
+
+#ifdef DIAGNOSTIC
+ if ((getsr() & PSL_IPL) < PSL_IPL2)
+ panic("ncr5380_machine: bad spl");
+ if (sc->sc_state == NCR_IDLE)
+ panic("ncr5380_machine: state=idle");
+ if (sc->sc_current == NULL)
+ panic("ncr5380_machine: no current cmd");
+#endif
+
+ sr = sc->sc_current;
+ xs = sr->sr_xs;
+ act_flags = ACT_CONTINUE;
+
+ /*
+ * This will be called by ncr5380_intr() when DMA is
+ * complete. Must stop DMA before touching the 5380 or
+ * there will be "register conflict" errors.
+ */
+ if (sc->sc_state & NCR_DOINGDMA) {
+ /* Pick-up where where we left off... */
+ goto dma_done;
+ }
+
+next_phase:
+
+ if (!SCI_BUSY(sc)) {
+ /* Unexpected disconnect */
+ printf("ncr5380_machine: unexpected disconnect.\n");
+ xs->error = XS_DRIVER_STUFFUP;
+ act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
+ goto do_actions;
+ }
+
+ /*
+ * Wait for REQ before reading the phase.
+ * Need to wait longer than usual here, because
+ * some devices are just plain slow...
+ */
+ timo = ncr5380_wait_phase_timo;
+ for (;;) {
+ if (*sc->sci_bus_csr & SCI_BUS_REQ)
+ break;
+ if (--timo <= 0) {
+ if (sc->sc_state & NCR_ABORTING) {
+ printf("%s: no REQ while aborting, reset\n",
+ sc->sc_dev.dv_xname);
+ act_flags |= ACT_RESET_BUS;
+ goto do_actions;
+ }
+ printf("%s: no REQ for next phase, abort\n",
+ sc->sc_dev.dv_xname);
+ sc->sc_state |= NCR_ABORTING;
+ ncr_sched_msgout(sc, SEND_ABORT);
+ goto next_phase;
+ }
+ delay(100);
+ }
+
+ phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
+ NCR_TRACE("machine: phase=%s\n",
+ (long) phase_names[phase & 7]);
+
+ /*
+ * We assume that the device knows what it's doing,
+ * so any phase is good.
+ */
+
+#if 0
+ /*
+ * XXX: Do not ACK the phase yet! do it later...
+ * XXX: ... each phase routine does that itself.
+ * In particular, DMA needs it done LATER.
+ */
+ SetReg ( sc->sci_tcmd, phase );
+/* *sc->sci_tcmd = phase; */ /* acknowledge phase change */
+#endif
+
+ switch (phase) {
+
+ case PHASE_DATA_OUT:
+ case PHASE_DATA_IN:
+ act_flags = ncr5380_data_xfer(sc, phase);
+ break;
+
+ case PHASE_COMMAND:
+ act_flags = ncr5380_command(sc);
+ break;
+
+ case PHASE_STATUS:
+ act_flags = ncr5380_status(sc);
+ break;
+
+ case PHASE_MSG_OUT:
+ act_flags = ncr5380_msg_out(sc);
+ break;
+
+ case PHASE_MSG_IN:
+ act_flags = ncr5380_msg_in(sc);
+ break;
+
+ default:
+ printf("ncr5380_machine: Unexpected phase 0x%x\n", phase);
+ sc->sc_state |= NCR_ABORTING;
+ ncr_sched_msgout(sc, SEND_ABORT);
+ goto next_phase;
+
+ } /* switch */
+ sc->sc_prevphase = phase;
+
+do_actions:
+ __asm("_ncr5380_actions:");
+
+ if (act_flags & ACT_WAIT_DMA) {
+ act_flags &= ~ACT_WAIT_DMA;
+ /* Wait for DMA to complete (polling, or interrupt). */
+ if ((sr->sr_flags & SR_IMMED) == 0) {
+ NCR_TRACE("machine: wait for DMA intr.\n", 0);
+ return; /* will resume at dma_done */
+ }
+ /* Busy-wait for it to finish. */
+ NCR_TRACE("machine: dma_poll, dh=0x%x\n",
+ (long) sr->sr_dma_hand);
+ (*sc->sc_dma_poll)(sc);
+ dma_done:
+ /* Return here after interrupt. */
+ if (sr->sr_flags & SR_OVERDUE)
+ sc->sc_state |= NCR_ABORTING;
+ NCR_TRACE("machine: dma_stop, dh=0x%x\n",
+ (long) sr->sr_dma_hand);
+ (*sc->sc_dma_stop)(sc);
+ SCI_CLR_INTR(sc); /* XXX */
+ /*
+ * While DMA is running we can not touch the SBC,
+ * so various places just set NCR_ABORTING and
+ * expect us the "kick it" when DMA is done.
+ */
+ if (sc->sc_state & NCR_ABORTING) {
+ ncr_sched_msgout(sc, SEND_ABORT);
+ }
+ }
+
+ /*
+ * Check for parity error.
+ * XXX - better place to check?
+ */
+ if (*(sc->sci_csr) & SCI_CSR_PERR) {
+ printf("%s: parity error csr = %02x!\n",
+ sc->sc_dev.dv_xname, *(sc->sci_csr) );
+ /* XXX: sc->sc_state |= NCR_ABORTING; */
+ ncr_sched_msgout(sc, SEND_PARITY_ERROR);
+ }
+
+ if (act_flags == ACT_CONTINUE)
+ goto next_phase;
+ /* All other actions "break" from the loop. */
+
+ NCR_TRACE("machine: act_flags=0x%x\n", act_flags);
+
+ if (act_flags & ACT_RESET_BUS) {
+ act_flags |= ACT_CMD_DONE;
+ /*
+ * Reset the SCSI bus, usually due to a timeout.
+ * The error code XS_TIMEOUT allows retries.
+ */
+ sc->sc_state |= NCR_ABORTING;
+ printf("%s: reset SCSI bus for TID=%d LUN=%d\n",
+ sc->sc_dev.dv_xname,
+ sr->sr_target, sr->sr_lun);
+ ncr5380_reset_scsibus(sc);
+ }
+
+ if (act_flags & ACT_CMD_DONE) {
+ act_flags |= ACT_DISCONNECT;
+ /* Need to call scsi_done() */
+ /* XXX: from the aic6360 driver, but why? */
+ if (sc->sc_datalen < 0) {
+ printf("%s: %d extra bytes from %d:%d\n",
+ sc->sc_dev.dv_xname, -sc->sc_datalen,
+ sr->sr_target, sr->sr_lun);
+ sc->sc_datalen = 0;
+ }
+ xs->resid = sc->sc_datalen;
+ /* Note: this will clear sc_current */
+ NCR_TRACE("machine: call done, cur=0x%x\n", (long)sr);
+ ncr5380_done(sc);
+ }
+
+ if (act_flags & ACT_DISCONNECT) {
+ /*
+ * The device has dropped BSY (or will soon).
+ * Return and let ncr5380_sched() do its thing.
+ */
+ SetReg ( sc->sci_icmd, 0 );
+ SetReg ( sc->sci_mode, 0 );
+ SetReg ( sc->sci_tcmd, PHASE_INVALID );
+ SetReg ( sc->sci_sel_enb, 0 );
+
+/* *sc->sci_icmd = 0;
+ *sc->sci_mode = 0;
+ *sc->sci_tcmd = PHASE_INVALID;
+ *sc->sci_sel_enb = 0; */
+
+ SCI_CLR_INTR(sc);
+ SetReg ( sc->sci_sel_enb, 0x80 );
+ *sc->sci_sel_enb = 0x80;
+
+ if ((act_flags & ACT_CMD_DONE) == 0) {
+ __asm("_ncr5380_disconnected:");
+ NCR_TRACE("machine: discon, cur=0x%x\n", (long)sr);
+ }
+
+ /*
+ * We may be here due to a disconnect message,
+ * in which case we did NOT call ncr5380_done,
+ * and we need to clear sc_current.
+ */
+ sc->sc_state = NCR_IDLE;
+ sc->sc_current = NULL;
+
+ /* Paranoia: clear everything. */
+ sc->sc_dataptr = NULL;
+ sc->sc_datalen = 0;
+ sc->sc_prevphase = PHASE_INVALID;
+ sc->sc_msgpriq = 0;
+ sc->sc_msgoutq = 0;
+ sc->sc_msgout = 0;
+
+ /* Our caller will re-enable interrupts. */
+ }
+}
+
+
+#ifdef DEBUG
+
+static void
+ncr5380_show_scsi_cmd(xs)
+ struct scsi_xfer *xs;
+{
+ u_char *b = (u_char *) xs->cmd;
+ int i = 0;
+
+ if ( ! ( xs->flags & SCSI_RESET ) ) {
+ printf("si(%d:%d:%d)-",
+ xs->sc_link->scsibus,
+ xs->sc_link->target,
+ xs->sc_link->lun);
+ while (i < xs->cmdlen) {
+ if (i) printf(",");
+ printf("%x",b[i++]);
+ }
+ printf("-\n");
+ } else {
+ printf("si(%d:%d:%d)-RESET-\n",
+ xs->sc_link->scsibus,
+ xs->sc_link->target,
+ xs->sc_link->lun);
+ }
+}
+
+
+static void
+ncr5380_show_sense(xs)
+ struct scsi_xfer *xs;
+{
+ u_char *b = (u_char *)&xs->sense;
+ int i;
+
+ printf("sense:");
+ for (i = 0; i < sizeof(xs->sense); i++)
+ printf(" %02x", b[i]);
+ printf("\n");
+}
+
+int ncr5380_traceidx = 0;
+
+#define TRACE_MAX 1024
+struct trace_ent {
+ char *msg;
+ long val;
+} ncr5380_tracebuf[TRACE_MAX];
+
+void
+ncr5380_trace(msg, val)
+ char *msg;
+ long val;
+{
+ register struct trace_ent *tr;
+ register int s;
+
+ s = splhigh();
+
+ tr = &ncr5380_tracebuf[ncr5380_traceidx];
+
+ ncr5380_traceidx++;
+ if (ncr5380_traceidx >= TRACE_MAX)
+ ncr5380_traceidx = 0;
+
+ tr->msg = msg;
+ tr->val = val;
+
+ splx(s);
+}
+
+#ifdef DDB
+void
+ncr5380_clear_trace()
+{
+ ncr5380_traceidx = 0;
+ bzero((char*) ncr5380_tracebuf, sizeof(ncr5380_tracebuf));
+}
+
+void
+ncr5380_show_trace()
+{
+ struct trace_ent *tr;
+ int idx;
+
+ idx = ncr5380_traceidx;
+ do {
+ tr = &ncr5380_tracebuf[idx];
+ idx++;
+ if (idx >= TRACE_MAX)
+ idx = 0;
+ if (tr->msg)
+ db_printf(tr->msg, tr->val);
+ } while (idx != ncr5380_traceidx);
+}
+
+void
+ncr5380_show_req(sr)
+ struct sci_req *sr;
+{
+ struct scsi_xfer *xs = sr->sr_xs;
+
+ db_printf("TID=%d ", sr->sr_target);
+ db_printf("LUN=%d ", sr->sr_lun);
+ db_printf("dh=0x%x ", sr->sr_dma_hand);
+ db_printf("dptr=0x%x ", sr->sr_dataptr);
+ db_printf("dlen=0x%x ", sr->sr_datalen);
+ db_printf("flags=%d ", sr->sr_flags);
+ db_printf("stat=%d ", sr->sr_status);
+
+ if (xs == NULL) {
+ db_printf("(xs=NULL)\n");
+ return;
+ }
+ db_printf("\n");
+#ifdef SCSIDEBUG
+ show_scsi_xs(xs);
+#else
+ db_printf("xs=0x%x\n", xs);
+#endif
+}
+
+void
+ncr5380_show_state()
+{
+ struct ncr5380_softc *sc;
+ struct sci_req *sr;
+ int i, j, k;
+
+ sc = ncr5380_debug_sc;
+
+ if (sc == NULL) {
+ db_printf("ncr5380_debug_sc == NULL\n");
+ return;
+ }
+
+ db_printf("sc_ncmds=%d\n", sc->sc_ncmds);
+ k = -1; /* which is current? */
+ for (i = 0; i < SCI_OPENINGS; i++) {
+ sr = &sc->sc_ring[i];
+ if (sr->sr_xs) {
+ if (sr == sc->sc_current)
+ k = i;
+ db_printf("req %d: (sr=0x%x)", i, (long)sr);
+ ncr5380_show_req(sr);
+ }
+ }
+ db_printf("sc_rr=%d, current=%d\n", sc->sc_rr, k);
+
+ db_printf("Active request matrix:\n");
+ for(i = 0; i < 8; i++) { /* targets */
+ for (j = 0; j < 8; j++) { /* LUN */
+ sr = sc->sc_matrix[i][j];
+ if (sr) {
+ db_printf("TID=%d LUN=%d sr=0x%x\n", i, j, (long)sr);
+ }
+ }
+ }
+
+ db_printf("sc_state=0x%x\n", sc->sc_state);
+ db_printf("sc_current=0x%x\n", sc->sc_current);
+ db_printf("sc_dataptr=0x%x\n", sc->sc_dataptr);
+ db_printf("sc_datalen=0x%x\n", sc->sc_datalen);
+
+ db_printf("sc_prevphase=%d\n", sc->sc_prevphase);
+ db_printf("sc_msgpriq=0x%x\n", sc->sc_msgpriq);
+}
+
+#endif /* DDB */
+#endif /* DEBUG */
--- /dev/null
+/* $NetBSD: ncr5380var.h,v 1.1 1996/01/31 23:26:12 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 David Jones, Gordon W. Ross
+ * Copyright (c) 1994 Jarle Greipsland
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * 4. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by
+ * David Jones and Gordon Ross
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file defines the interface between the machine-dependent
+ * module and the machine-indepenedent ncr5380sbc.c module.
+ */
+
+#define SCI_CLR_INTR(sc) (*(sc)->sci_iack)
+#define SCI_BUSY(sc) (*sc->sci_bus_csr & SCI_BUS_BSY)
+
+/* These are NOT artibtrary, but map to bits in sci_tcmd */
+#define PHASE_DATA_OUT 0x0
+#define PHASE_DATA_IN 0x1
+#define PHASE_COMMAND 0x2
+#define PHASE_STATUS 0x3
+#define PHASE_UNSPEC1 0x4
+#define PHASE_UNSPEC2 0x5
+#define PHASE_MSG_OUT 0x6
+#define PHASE_MSG_IN 0x7
+
+/*
+ * This illegal phase is used to prevent the 5380 from having
+ * a phase-match condition when we don't want one, such as
+ * when setting up the DMA engine or whatever...
+ */
+#define PHASE_INVALID PHASE_UNSPEC1
+
+
+/* Per-request state. This is required in order to support reselection. */
+struct sci_req {
+ struct scsi_xfer *sr_xs; /* Pointer to xfer struct, NULL=unused */
+ int sr_target, sr_lun; /* For fast access */
+ void *sr_dma_hand; /* Current DMA hnadle */
+ u_char *sr_dataptr; /* Saved data pointer */
+ int sr_datalen;
+ int sr_flags; /* Internal error code */
+#define SR_IMMED 1 /* Immediate command */
+#define SR_SENSE 2 /* We are getting sense */
+#define SR_OVERDUE 4 /* Timeout while not current */
+#define SR_ERROR 8 /* Error occurred */
+ int sr_status; /* Status code from last cmd */
+};
+#define SCI_OPENINGS 16 /* How many commands we can enqueue. */
+
+
+struct ncr5380_softc {
+ struct device sc_dev;
+ struct scsi_link sc_link;
+
+ /* Pointers to 5380 registers. See ncr5380reg.h */
+ volatile u_char *sci_r0;
+ volatile u_char *sci_r1;
+ volatile u_char *sci_r2;
+ volatile u_char *sci_r3;
+ volatile u_char *sci_r4;
+ volatile u_char *sci_r5;
+ volatile u_char *sci_r6;
+ volatile u_char *sci_r7;
+
+ /* Functions set from MD code */
+ int (*sc_pio_out) __P((struct ncr5380_softc *,
+ int, int, u_char *));
+ int (*sc_pio_in) __P((struct ncr5380_softc *,
+ int, int, u_char *));
+ void (*sc_dma_alloc) __P((struct ncr5380_softc *));
+ void (*sc_dma_free) __P((struct ncr5380_softc *));
+
+ void (*sc_dma_setup) __P((struct ncr5380_softc *));
+ void (*sc_dma_start) __P((struct ncr5380_softc *));
+ void (*sc_dma_poll) __P((struct ncr5380_softc *));
+ void (*sc_dma_eop) __P((struct ncr5380_softc *));
+ void (*sc_dma_stop) __P((struct ncr5380_softc *));
+
+ void (*sc_intr_on) __P((struct ncr5380_softc *));
+ void (*sc_intr_off) __P((struct ncr5380_softc *));
+
+ int sc_flags; /* Misc. flags and capabilities */
+#define NCR5380_PERMIT_RESELECT 1 /* Allow disconnect/reselect */
+#define NCR5380_FORCE_POLLING 2 /* Do not use interrupts. */
+
+ int sc_min_dma_len; /* Smaller than this is done with PIO */
+
+ /* Begin MI shared data */
+
+ int sc_state;
+#define NCR_IDLE 0 /* Ready for new work. */
+#define NCR_WORKING 0x01 /* Some command is in progress. */
+#define NCR_ABORTING 0x02 /* Bailing out */
+#define NCR_DOINGDMA 0x04 /* The FIFO data path is active! */
+#define NCR_DROP_MSGIN 0x10 /* Discard all msgs (parity err detected) */
+
+ /* The request that has the bus now. */
+ struct sci_req *sc_current;
+
+ /* Active data pointer for current SCSI command. */
+ u_char *sc_dataptr;
+ int sc_datalen;
+
+ /* Begin MI private data */
+
+ /* The number of operations in progress on the bus */
+ volatile int sc_ncmds;
+
+ /* Ring buffer of pending/active requests */
+ struct sci_req sc_ring[SCI_OPENINGS];
+ int sc_rr; /* Round-robin scan pointer */
+
+ /* Active requests, by target/LUN */
+ struct sci_req *sc_matrix[8][8];
+
+ /* Message stuff */
+ int sc_prevphase;
+
+ u_int sc_msgpriq; /* Messages we want to send */
+ u_int sc_msgoutq; /* Messages sent during last MESSAGE OUT */
+ u_int sc_msgout; /* Message last transmitted */
+#define SEND_DEV_RESET 0x01
+#define SEND_PARITY_ERROR 0x02
+#define SEND_ABORT 0x04
+#define SEND_REJECT 0x08
+#define SEND_INIT_DET_ERR 0x10
+#define SEND_IDENTIFY 0x20
+#define SEND_SDTR 0x40
+#define SEND_WDTR 0x80
+#define NCR_MAX_MSG_LEN 8
+ u_char sc_omess[NCR_MAX_MSG_LEN];
+ u_char *sc_omp; /* Outgoing message pointer */
+ u_char sc_imess[NCR_MAX_MSG_LEN];
+ u_char *sc_imp; /* Incoming message pointer */
+
+};
+
+void ncr5380_init __P((struct ncr5380_softc *));
+void ncr5380_reset_scsibus __P((struct ncr5380_softc *));
+int ncr5380_intr __P((struct ncr5380_softc *));
+int ncr5380_scsi_cmd __P((struct scsi_xfer *));
+int ncr5380_pio_in __P((struct ncr5380_softc *, int, int, u_char *));
+int ncr5380_pio_out __P((struct ncr5380_softc *, int, int, u_char *));
+
+#ifdef DEBUG
+struct ncr5380_softc *ncr5380_debug_sc;
+void ncr5380_trace __P((char *msg, long val));
+#define NCR_TRACE(msg, val) ncr5380_trace(msg, val)
+#else
+#define NCR_TRACE(msg, val) /* nada */
+#endif
--- /dev/null
+/* $NetBSD: oak.c,v 1.3 1996/03/17 01:24:51 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1995 Melvin Tang-Richardson 1996.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by RiscBSD.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * oak.c
+ *
+ * Oak SCSI Driver.
+ */
+
+#undef USE_OWN_PIO_ROUTINES
+
+/* Some system includes *****************************************************/
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+/*#include <machine/bootconfig.h>*/
+
+/* SCSI bus includes */
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+/* Hardware related include chip/card/bus ***********************************/
+
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/ncr5380reg.h>
+#include <arm32/podulebus/ncr5380var.h>
+
+/****************************************************************************/
+/* Some useful definitions **************************************************/
+/****************************************************************************/
+
+#define MY_MANUFACTURER (0x21)
+#define MY_PODULE (0x58)
+#define MAX_DMA_LEN (0xe000)
+
+/****************************************************************************/
+/* Prototype internal data structures ***************************************/
+/****************************************************************************/
+
+struct oak_softc {
+ struct ncr5380_softc ncr_sc;
+ int sc_podule;
+ int sc_base;
+};
+
+/****************************************************************************/
+/* Function and data prototypes *********************************************/
+/****************************************************************************/
+
+int oakprobe __P(( struct device *, void *, void * ));
+void oakattach __P(( struct device *, struct device *, void * ));
+int oakprint __P(( void *, char * ));
+void oakminphys __P(( struct buf * ));
+
+#ifdef USE_OWN_PIO_ROUTINES
+int oak_pio_in __P(( struct ncr5380_softc *, int, int, unsigned char * ));
+int oak_pio_out __P(( struct ncr5380_softc *, int, int, unsigned char * ));
+#endif
+
+struct scsi_adapter oak_adapter = {
+ ncr5380_scsi_cmd,
+ oakminphys,
+ NULL,
+ NULL,
+};
+
+struct scsi_device oak_device = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+int
+oakprobe(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ struct oak_softc *sc = (void *) match;
+ struct podule_attach_args *pa = (void *) aux;
+ int podule;
+
+ podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number);
+
+ if (podule == -1)
+ return 0;
+
+ sc->sc_podule = podule;
+ sc->sc_base = podules[podule].mod_base;
+
+ return 1;
+}
+
+void
+oakattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct oak_softc *sc = (void *) self;
+ struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)sc;
+ struct podule_attach_args *pa = (void *)aux;
+
+ printf(" 16-bit");
+
+ ncr_sc->sc_link.adapter_softc = sc;
+ ncr_sc->sc_link.adapter_target = 7;
+ ncr_sc->sc_link.adapter = &oak_adapter;
+ ncr_sc->sc_link.device = &oak_device;
+
+ ncr_sc->sci_r0 = (volatile u_char *)sc->sc_base + 0x00;
+ ncr_sc->sci_r1 = (volatile u_char *)sc->sc_base + 0x04;
+ ncr_sc->sci_r2 = (volatile u_char *)sc->sc_base + 0x08;
+ ncr_sc->sci_r3 = (volatile u_char *)sc->sc_base + 0x0c;
+ ncr_sc->sci_r4 = (volatile u_char *)sc->sc_base + 0x10;
+ ncr_sc->sci_r5 = (volatile u_char *)sc->sc_base + 0x14;
+ ncr_sc->sci_r6 = (volatile u_char *)sc->sc_base + 0x18;
+ ncr_sc->sci_r7 = (volatile u_char *)sc->sc_base + 0x1c;
+
+#ifdef USE_OWN_PIO_ROUTINES
+ printf ( ", my pio" );
+ ncr_sc->sc_pio_out = oak_pio_out;
+ ncr_sc->sc_pio_in = oak_pio_in;
+#else
+ printf ( ", normal pio" );
+ ncr_sc->sc_pio_out = ncr5380_pio_out;
+ ncr_sc->sc_pio_in = ncr5380_pio_in;
+#endif
+
+ ncr_sc->sc_dma_alloc = NULL;
+ ncr_sc->sc_dma_free = NULL;
+ ncr_sc->sc_dma_poll = NULL;
+ ncr_sc->sc_dma_setup = NULL;
+ ncr_sc->sc_dma_start = NULL;
+ ncr_sc->sc_dma_eop = NULL;
+ ncr_sc->sc_dma_stop = NULL;
+
+ printf(", polling");
+ ncr_sc->sc_intr_on = NULL;
+ ncr_sc->sc_intr_off = NULL;
+
+ ncr_sc->sc_flags = NCR5380_FORCE_POLLING;
+
+ ncr5380_init(ncr_sc);
+ ncr5380_reset_scsibus(ncr_sc);
+
+ printf(" UNDER DEVELOPMENT\n");
+
+ config_found(self, &(ncr_sc->sc_link), oakprint);
+}
+
+int
+oakprint(aux, name)
+ void *aux;
+ char *name;
+{
+ if (name != NULL)
+ printf("%s: scsibus ", name);
+ return UNCONF;
+}
+
+void
+oakminphys(bp)
+ struct buf *bp;
+{
+ if (bp->b_bcount > MAX_DMA_LEN) {
+ printf("oak: DEBUG reducing dma length\n");
+ bp->b_bcount = MAX_DMA_LEN;
+ }
+ return (minphys(bp));
+}
+
+struct cfattach oak_ca = {
+ sizeof(struct oak_softc), oakprobe, oakattach
+};
+
+struct cfdriver oak_cd = {
+ NULL, "oak", DV_DISK, NULL, 0,
+};
+
+#ifdef USE_OWN_PIO_ROUTINES
+
+/****************************************************************************/
+/* Copyright (c) 1996 Melvin Tang-Richardson */
+/* Copyright (c) 1995 David Jones, Gordon W. Rose */
+/* Copyright (c) 1994 Jarle Greipsland */
+/****************************************************************************/
+
+static ncr5380_wait_req_timo = 1000 * 50; /* X2 = 100 mS */
+static ncr5380_wait_nrq_timo = 1000 * 25; /* X2 = 50 mS */
+
+/* Return zero on success. */
+static __inline__ int ncr5380_wait_req(sc)
+ struct ncr5380_softc *sc;
+{
+ register int timo = ncr5380_wait_req_timo;
+ for (;;) {
+ if (*sc->sci_bus_csr & SCI_BUS_REQ) {
+ timo = 0; /* return 0 */
+ break;
+ }
+ if (--timo < 0)
+ break; /* return -1 */
+ delay(2);
+ }
+ return (timo);
+}
+
+/* Return zero on success. */
+static __inline__ int ncr5380_wait_not_req(sc)
+ struct ncr5380_softc *sc;
+{
+ register int timo = ncr5380_wait_nrq_timo;
+ for (;;) {
+ if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0) {
+ timo = 0; /* return 0 */
+ break;
+ }
+ if (--timo < 0)
+ break; /* return -1 */
+ delay(2);
+ }
+ return (timo);
+}
+
+int
+oak_pio_out(sc, phase, count, data)
+ struct ncr5380_softc *sc;
+ int phase, count;
+ unsigned char *data;
+{
+ register u_char icmd;
+ register int resid;
+ register int error;
+
+ printf("oak: pio_out %d %d\n", phase, count);
+
+ icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
+
+ icmd |= SCI_ICMD_DATA;
+ *sc->sci_icmd = icmd;
+
+ resid = count;
+ while (resid > 0) {
+ if (!SCI_BUSY(sc)) {
+ NCR_TRACE("pio_out: lost BSY, resid=%d\n", resid);
+ break;
+ }
+ if (ncr5380_wait_req(sc)) {
+ NCR_TRACE("pio_out: no REQ, resid=%d\n", resid);
+ break;
+ }
+ if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
+ break;
+
+ /* Put the data on the bus. */
+ *sc->sci_odata = *data++;
+
+ /* Tell the target it's there. */
+ icmd |= SCI_ICMD_ACK;
+ *sc->sci_icmd = icmd;
+
+ /* Wait for target to get it. */
+ error = ncr5380_wait_not_req(sc);
+
+ /* OK, it's got it (or we gave up waiting). */
+ icmd &= ~SCI_ICMD_ACK;
+ *sc->sci_icmd = icmd;
+
+ if (error) {
+ NCR_TRACE("pio_out: stuck REQ, resid=%d\n", resid);
+ break;
+ }
+
+ --resid;
+ }
+
+ /* Stop driving the data bus. */
+ icmd &= ~SCI_ICMD_DATA;
+ *sc->sci_icmd = icmd;
+
+ return (count - resid);
+}
+
+int
+oak_pio_in(sc, phase, count, data)
+ struct ncr5380_softc *sc;
+ int phase, count;
+ unsigned char *data;
+{
+ register u_char icmd;
+ register int resid;
+ register int error;
+
+ printf("oak: pio_in %d %d\n", phase, count);
+
+ icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
+
+ resid = count;
+ while (resid > 0) {
+ if (!SCI_BUSY(sc)) {
+ NCR_TRACE("pio_in: lost BSY, resid=%d\n", resid);
+ break;
+ }
+ if (ncr5380_wait_req(sc)) {
+ NCR_TRACE("pio_in: no REQ, resid=%d\n", resid);
+ break;
+ }
+ /* A phase change is not valid until AFTER REQ rises! */
+ if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
+ break;
+
+ /* Read the data bus. */
+ *data++ = *sc->sci_data;
+
+ /* Tell target we got it. */
+ icmd |= SCI_ICMD_ACK;
+ *sc->sci_icmd = icmd;
+
+ /* Wait for target to drop REQ... */
+ error = ncr5380_wait_not_req(sc);
+
+ /* OK, we can drop ACK. */
+ icmd &= ~SCI_ICMD_ACK;
+ *sc->sci_icmd = icmd;
+
+ if (error) {
+ NCR_TRACE("pio_in: stuck REQ, resid=%d\n", resid);
+ break;
+ }
+
+ --resid;
+ }
+
+ return (count - resid);
+}
+
+#endif /* USE_OWN_PIO_ROUTINES */
+
--- /dev/null
+/* $NetBSD: podulebus.c,v 1.5 1996/03/27 22:07:26 mark Exp $ */
+
+/*
+ * Copyright (c) 1994,1995 Mark Brinicombe.
+ * Copyright (c) 1994 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * podulebus.c
+ *
+ * Podule probe and configuration routines
+ *
+ * Created : 07/11/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <machine/io.h>
+#include <machine/katelib.h>
+#include <machine/irqhandler.h>
+#include <arm32/podulebus/podulebus.h>
+
+/*
+ * Now construct the table of know podules.
+ * A podule description array is setup for each manufacturer id
+ */
+
+struct podule_description podules_0000[] = {
+ { 0x02, "SCSI interface" },
+ { 0x03, "ether 1 interface" },
+ { 0x61, "ether 2 interface" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_0004[] = {
+ { 0x14, "laser direct (Canon LBP-4)" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_0009[] = {
+ { 0x52, "hawk V9 mark2" },
+ { 0xcb, "scanlight Video256" },
+ { 0xcc, "eagle M2" },
+ { 0xce, "lark A16" },
+ { 0x200, "MIDI max" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_0011[] = {
+ { 0xa4, "ether 3 interface" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_001a[] = {
+ { 0x95, "16 bit SCSI interface" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_0021[] = {
+ { 0x58, "16 bit SCSI interface" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_002b[] = {
+ { 0x67, "SCSI interface" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_003a[] = {
+ { 0x3a, "SCSI II interface" },
+ { 0xdd, "CDFS & SLCD expansion card" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_0041[] = {
+ { 0x41, "16 bit SCSI interface" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_0042[] = {
+ { 0xea, "PC card" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_0046[] = {
+ { 0xec, "etherlan 600 network slot interface" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_0050[] = {
+ { 0x00, "BriniPort intelligent I/O interface" },
+ { 0xdf, "BriniLink transputer link adapter" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_0053[] = {
+ { 0xe4, "ether B network slot interface" },
+ { 0x00, NULL },
+};
+
+struct podule_description podules_005b[] = {
+ { 0x107, "SCSI 1 / SCSI 2 host adapter" },
+ { 0x00, NULL },
+};
+
+/* A podule list if setup for all the manufacturers */
+
+struct podule_list known_podules[] = {
+ { 0x00, "Acorn", podules_0000 },
+ { 0x04, "CConcepts", podules_0004 }, /* Two codes ??? */
+ { 0x09, "CConcepts", podules_0009 },
+ { 0x11, "Atomwide", podules_0011 },
+ { 0x1a, "Lingenuity", podules_001a },
+ { 0x21, "Oak", podules_0021 },
+ { 0x2b, "Morley", podules_002b },
+ { 0x3a, "Cumana", podules_003a },
+ { 0x41, "ARXE", podules_0041 },
+ { 0x42, "Aleph1", podules_0042 },
+ { 0x46, "I-Cubed", podules_0046 },
+ { 0x50, "Brini", podules_0050 },
+ { 0x53, "ANT", podules_0053 },
+ { 0x5b, "Power-tec", podules_005b },
+};
+
+/* Array of podule structures, one per possible podule */
+
+podule_t podules[MAX_PODULES + MAX_NETSLOTS];
+irqhandler_t poduleirq;
+extern u_int actual_mask;
+extern irqhandler_t *irqhandlers[NIRQS];
+
+/* Declare prototypes */
+
+void map_section __P((vm_offset_t, vm_offset_t, vm_offset_t));
+int poduleirqhandler __P((void));
+u_int poduleread __P((u_int /*address*/, int /*offset*/, int /*slottype*/));
+
+
+/*
+ * int podulebusmatch(struct device *parent, void *match, void *aux)
+ *
+ * Probe for the podule bus. Currently all this does is return 1 to
+ * indicate that the podule bus was found.
+ */
+
+int
+podulebusmatch(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ return (1);
+}
+
+
+int
+podulebusprint(aux, podulebus)
+ void *aux;
+ char *podulebus;
+{
+ struct podule_attach_args *pa = aux;
+
+ if (pa->pa_podule != NULL) {
+ if (pa->pa_podule->slottype == SLOT_POD)
+ printf(" [ podule %d ]:", pa->pa_podule_number);
+ else if (pa->pa_podule->slottype == SLOT_NET)
+ printf(" [ netslot %d ]:", pa->pa_podule_number - MAX_PODULES);
+ else
+ panic("Invalid slot type\n");
+ }
+
+/* XXXX print flags */
+ return (QUIET);
+}
+
+
+void
+podulebusscan(parent, match)
+ struct device *parent;
+ void *match;
+{
+ struct device *dev = match;
+ struct cfdata *cf = dev->dv_cfdata;
+ struct podule_attach_args pa;
+
+ if (cf->cf_fstate == FSTATE_STAR)
+ panic("nope cannot handle this");
+
+ pa.pa_podule = NULL;
+ pa.pa_podule_number = -1;
+
+ if (cf->cf_loc[0] != -1) {
+ pa.pa_podule_number = cf->cf_loc[0];
+ }
+
+ if ((*cf->cf_attach->ca_match)(parent, dev, &pa) > 0)
+ config_attach(parent, dev, &pa, podulebusprint);
+ else
+ free(dev, M_DEVBUF);
+}
+
+
+void
+dump_podule(podule)
+ podule_t *podule;
+{
+ printf("podule%d: ", podule->podulenum);
+ printf("flags0=%02x ", podule->flags0);
+ printf("flags1=%02x ", podule->flags1);
+ printf("reserved=%02x ", podule->reserved);
+ printf("product=%02x ", podule->product);
+ printf("manufacturer=%02x ", podule->manufacturer);
+ printf("country=%02x ", podule->country);
+ printf("irq_addr=%08x ", podule->irq_addr);
+ printf("irq_mask=%02x ", podule->irq_mask);
+ printf("fiq_addr=%08x ", podule->fiq_addr);
+ printf("fiq_mask=%02x ", podule->fiq_mask);
+ printf("fast_base=%08x ", podule->fast_base);
+ printf("medium_base=%08x ", podule->medium_base);
+ printf("slow_base=%08x ", podule->slow_base);
+ printf("sync_base=%08x ", podule->sync_base);
+ printf("mod_base=%08x ", podule->mod_base);
+ printf("easi_base=%08x ", podule->easi_base);
+ printf("attached=%d ", podule->attached);
+ printf("slottype=%d ", podule->slottype);
+ printf("podulenum=%d ", podule->podulenum);
+ printf("\n");
+}
+
+
+void
+podulechunkdirectory(podule)
+ podule_t *podule;
+{
+ u_int address;
+ u_int id;
+ u_int size;
+ u_int addr;
+ int loop;
+
+ address = 0x40;
+
+ do {
+ id = poduleread(podule->slow_base, address, podule->slottype);
+ size = poduleread(podule->slow_base, address + 4, podule->slottype);
+ size |= (poduleread(podule->slow_base, address + 8, podule->slottype) << 8);
+ size |= (poduleread(podule->slow_base, address + 12, podule->slottype) << 16);
+ if (id == 0xf5) {
+ addr = poduleread(podule->slow_base, address + 16, podule->slottype);
+ addr |= (poduleread(podule->slow_base, address + 20, podule->slottype) << 8);
+ addr |= (poduleread(podule->slow_base, address + 24, podule->slottype) << 16);
+ addr |= (poduleread(podule->slow_base, address + 28, podule->slottype) << 24);
+ if (addr < 0x800) {
+ for (loop = 0; loop < size; ++loop)
+ printf("%c", poduleread(podule->slow_base, (addr + loop)*4, podule->slottype));
+ printf("\n");
+ }
+ }
+ address += 32;
+ } while (id != 0 && address < 0x800);
+}
+
+
+void
+poduleexamine(podule, dev, slottype)
+ podule_t *podule;
+ struct device *dev;
+ int slottype;
+{
+ struct podule_list *pod_list;
+ struct podule_description *pod_desc;
+
+/* Test to see if the podule is present */
+
+ if ((podule->flags0 & 0x02) == 0x00) {
+ podule->slottype = slottype;
+ if (slottype == SLOT_NET)
+ printf("netslot%d at %s : ", podule->podulenum - MAX_PODULES,
+ dev->dv_xname);
+ else
+ printf("podule%d at %s : ", podule->podulenum,
+ dev->dv_xname);
+
+/* Is it Acorn conformant ? */
+
+ if (podule->flags0 & 0x80)
+ printf("Non-Acorn conformant expansion card\n");
+ else {
+ int id;
+
+/* Is it a simple podule ? */
+
+ id = (podule->flags0 >> 3) & 0x0f;
+ if (id != 0)
+ printf("Simple expansion card <%x>\n", id);
+ else {
+/* Do we know this manufacturer ? */
+ pod_list = known_podules;
+ while (pod_list->description) {
+ if (pod_list->manufacturer_id == podule->manufacturer)
+ break;
+ ++pod_list;
+ }
+ if (!pod_list->description)
+ printf("man=%04x : ", podule->manufacturer);
+ else
+ printf("%10s : ", pod_list->description);
+
+/* Do we know this product ? */
+
+ pod_desc = pod_list->products;
+ while (pod_desc->description) {
+ if (pod_desc->product_id == podule->product)
+ break;
+ ++pod_desc;
+ }
+ if (!pod_desc->description)
+ printf("prod=%04x\n", podule->product);
+ else
+ printf("%s\n", pod_desc->description);
+
+ if (pod_desc->description == NULL
+ && podule->flags1 & PODULE_FLAGS_CD)
+ podulechunkdirectory(podule);
+ }
+ }
+ }
+}
+
+
+u_int
+poduleread(address, offset, slottype)
+ u_int address;
+ int offset;
+ int slottype;
+{
+ static u_int netslotoffset;
+
+ if (slottype == SLOT_NET) {
+ offset = offset >> 2;
+ if (offset < netslotoffset) {
+ WriteWord(address, 0);
+ netslotoffset = 0;
+ }
+ while (netslotoffset < offset) {
+ slottype = ReadWord(address);
+ ++netslotoffset;
+ }
+ ++netslotoffset;
+ return(ReadByte(address));
+ }
+ return(ReadByte(address + offset));
+}
+
+
+void
+podulescan(dev)
+ struct device *dev;
+{
+ int loop;
+ podule_t *podule;
+ u_char *address;
+ u_int offset = 0;
+
+/* Loop round all the podules */
+
+ for (loop = 0; loop < MAX_PODULES; ++loop, offset += SIMPLE_PODULE_SIZE) {
+ if (loop == 4) offset += PODULE_GAP;
+ address = ((u_char *)SLOW_PODULE_BASE) + offset;
+
+ podule = &podules[loop];
+
+/* Get information from the podule header */
+
+ podule->flags0 = address[0];
+ podule->flags1 = address[4];
+ podule->reserved = address[8];
+ podule->product = address[12] + (address[16] << 8);
+ podule->manufacturer = address[20] + (address[24] << 8);
+ podule->country = address[28];
+ if (podule->flags1 & PODULE_FLAGS_IS) {
+ podule->irq_addr = address[52] + (address[56] << 8) + (address[60] << 16);
+ podule->irq_mask = address[48];
+ podule->fiq_addr = address[36] + (address[40] << 8) + (address[44] << 16);
+ podule->fiq_mask = address[32];
+ } else {
+ podule->irq_addr = 0;
+ podule->irq_mask = 0;
+ podule->fiq_addr = 0;
+ podule->fiq_mask = 0;
+ }
+ podule->fast_base = FAST_PODULE_BASE + offset;
+ podule->medium_base = MEDIUM_PODULE_BASE + offset;
+ podule->slow_base = SLOW_PODULE_BASE + offset;
+ podule->sync_base = SYNC_PODULE_BASE + offset;
+ podule->mod_base = MOD_PODULE_BASE + offset;
+ podule->easi_base = EASI_BASE + loop * EASI_SIZE;
+ podule->attached = 0;
+ podule->slottype = SLOT_NONE;
+ podule->podulenum = loop;
+
+ poduleexamine(podule, dev, SLOT_POD);
+ }
+}
+
+
+void
+netslotscan(dev)
+ struct device *dev;
+{
+ podule_t *podule;
+ volatile u_char *address;
+
+/* Only one netslot atm */
+
+/* Reset the address counter */
+
+ WriteByte(NETSLOT_BASE, 0x00);
+
+ address = (u_char *)NETSLOT_BASE;
+
+ podule = &podules[MAX_PODULES];
+
+/* Get information from the podule header */
+
+ podule->flags0 = *address;
+ podule->flags1 = *address;
+ podule->reserved = *address;
+ podule->product = *address + (*address << 8);
+ podule->manufacturer = *address + (*address << 8);
+ podule->country = *address;
+ if (podule->flags1 & PODULE_FLAGS_IS) {
+ podule->irq_mask = *address;
+ podule->irq_addr = *address + (*address << 8) + (*address << 16);
+ podule->fiq_mask = *address;
+ podule->fiq_addr = *address + (*address << 8) + (*address << 16);
+ } else {
+ podule->irq_addr = 0;
+ podule->irq_mask = 0;
+ podule->fiq_addr = 0;
+ podule->fiq_mask = 0;
+ }
+ podule->fast_base = NETSLOT_BASE;
+ podule->medium_base = NETSLOT_BASE;
+ podule->slow_base = NETSLOT_BASE;
+ podule->sync_base = NETSLOT_BASE;
+ podule->mod_base = NETSLOT_BASE;
+ podule->easi_base = 0;
+ podule->attached = 0;
+ podule->slottype = SLOT_NONE;
+ podule->podulenum = MAX_PODULES;
+
+ poduleexamine(podule, dev, SLOT_NET);
+}
+
+
+/*
+ * void podulebusattach(struct device *parent, struct device *dev, void *aux)
+ *
+ * Attach podulebus.
+ * This probes all the podules and sets up the podules array with
+ * information found in the podule headers.
+ * After identifing all the podules, all the children of the podulebus
+ * are probed and attached.
+ */
+
+void
+podulebusattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ int loop;
+
+ printf("\n");
+
+/* Ok we need to map in the podulebus */
+
+/* Map the FAST and SYNC simple podules */
+
+ map_section(PAGE_DIRS_BASE, SYNC_PODULE_BASE & 0xfff00000,
+ SYNC_PODULE_HW_BASE & 0xfff00000);
+
+/* Now map the EASI space */
+
+ for (loop = 0; loop < MAX_PODULES; ++loop) {
+ int loop1;
+
+ for (loop1 = loop * EASI_SIZE; loop1 < ((loop + 1) * EASI_SIZE); loop1 += (1 << 20))
+ map_section(PAGE_DIRS_BASE, EASI_BASE + loop1, EASI_HW_BASE + loop1);
+ }
+
+/*
+ * The MEDIUM and SLOW simple podules and the module space will have been
+ * mapped when the IOMD and COMBO we mapped in for the RPC
+ */
+
+/* Install an podule IRQ handler */
+
+ poduleirq.ih_func = poduleirqhandler;
+ poduleirq.ih_arg = NULL;
+ poduleirq.ih_level = IPL_NONE;
+ poduleirq.ih_name = "podulebus";
+
+ if (irq_claim(IRQ_PODULE, &poduleirq))
+ panic("Cannot claim IRQ for podulebus%d\n", IRQ_PODULE, parent->dv_unit);
+
+/* Find out what hardware is bolted on */
+
+ podulescan(self);
+ netslotscan(self);
+
+/* Look for drivers */
+
+ config_scan(podulebusscan, self);
+}
+
+
+/*
+ * int podule_irqhandler(void *arg)
+ *
+ * text irq handler to service expansion card IRQ's
+ *
+ * There is currently a problem here.
+ * The spl_mask may mask out certain expansion card IRQ's e.g. SCSI
+ * but allow others e.g. Ethernet.
+ */
+
+int
+poduleirqhandler()
+{
+ int loop;
+ irqhandler_t *handler;
+
+ printf("eek ! Unknown podule IRQ received - Blocking all podule interrupts\n");
+ disable_irq(IRQ_PODULE);
+ return(1);
+
+/* Loop round the expansion card handlers */
+
+ for (loop = IRQ_EXPCARD0; loop <= IRQ_EXPCARD7; ++loop) {
+
+/* Is the IRQ currently allowable */
+
+ if (actual_mask & (1 << loop)) {
+ handler = irqhandlers[loop];
+
+ if (handler && handler->ih_irqmask) {
+ if ((*handler->ih_irqmask) & handler->ih_irqbit)
+ handler->ih_func(handler->ih_arg);
+ }
+ }
+ }
+ return(1);
+}
+
+struct cfattach podulebus_ca = {
+ sizeof(struct device), podulebusmatch, podulebusattach
+};
+
+struct cfdriver podulebus_cd = {
+ NULL, "podulebus", DV_DULL, 1
+};
+
+
+/* Useful functions that drivers may share */
+
+/*
+ * Search the podule list for the specified manufacturer and product.
+ * Return the podule number if the podule is not already attach and
+ * the podule was in the required slot.
+ * A required slot of -1 means any slot.
+ */
+
+int
+findpodule(manufacturer, product, required_slot)
+ int manufacturer;
+ int product;
+ int required_slot;
+{
+ int loop;
+
+ for (loop = 0; loop < MAX_PODULES+MAX_NETSLOTS; ++loop) {
+ if (podules[loop].slottype != SLOT_NONE
+ && !podules[loop].attached
+ && podules[loop].manufacturer == manufacturer
+ && podules[loop].product == product
+ && (required_slot == -1 || required_slot == loop))
+ return(loop);
+ }
+
+ return(-1);
+}
+
+/* End of podulebus.c */
--- /dev/null
+/* $NetBSD: podulebus.h,v 1.2 1996/03/18 21:23:18 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * Copyright (c) 1995 Brini.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Brini.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * RiscBSD kernel project
+ *
+ * podulebus.h
+ *
+ * Podule bus header file
+ *
+ * Created : 26/04/95
+ */
+
+#include <sys/param.h>
+
+/* Define the structures used to describe the "known" podules */
+
+struct podule_description {
+ int product_id;
+ char *description;
+};
+
+struct podule_list {
+ int manufacturer_id;
+ char *description;
+ struct podule_description *products;
+};
+
+/* Define the structure used to describe a podule */
+
+typedef struct {
+/* The podule header, read from the on board ROM */
+
+ u_char flags0;
+ u_char flags1;
+ u_char reserved;
+ u_short product;
+ u_short manufacturer;
+ u_char country;
+ u_int irq_addr;
+ u_int irq_mask;
+ u_int fiq_addr;
+ u_int fiq_mask;
+
+/* The base addresses for this podule */
+
+ u_int fast_base;
+ u_int medium_base;
+ u_int slow_base;
+ u_int sync_base;
+ u_int mod_base;
+ u_int easi_base;
+
+/* Flags */
+
+ int podulenum;
+ int slottype;
+ int attached;
+} podule_t;
+
+#define PODULE_FLAGS_CD 0x01
+#define PODULE_FLAGS_IS 0x02
+
+#define SLOT_NONE 0x00
+#define SLOT_POD 0x01
+#define SLOT_NET 0x02
+
+struct podule_attach_args {
+ podule_t *pa_podule;
+ int pa_podule_number;
+ int pa_slottype;
+};
+
+#ifdef _KERNEL
+
+/* Array of podule structures, one per possible podule */
+
+extern podule_t podules[MAX_PODULES + MAX_NETSLOTS];
+
+int findpodule __P((int, int, int));
+
+#endif
+
+/* End of podulebus.h */
--- /dev/null
+/* $NetBSD: ptsc.c,v 1.2 1996/03/17 01:24:54 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ * Copyright (c) 1995 Daniel Widenfalk
+ * Copyright (c) 1994 Christian E. Hopps
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ptsc.c
+ */
+/*
+ * Power-tec SCSI-2 driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <machine/pmap.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/sfasreg.h>
+#include <arm32/podulebus/sfasvar.h>
+#include <arm32/podulebus/ptscreg.h>
+#include <arm32/podulebus/ptscvar.h>
+
+int ptscprint __P((void *auxp, char *));
+void ptscattach __P((struct device *, struct device *, void *));
+int ptscmatch __P((struct device *, void *, void *));
+int ptsc_scsicmd __P((struct scsi_xfer *));
+
+struct scsi_adapter ptsc_scsiswitch = {
+ ptsc_scsicmd,
+ sfas_minphys,
+ 0, /* no lun support */
+ 0, /* no lun support */
+};
+
+struct scsi_device ptsc_scsidev = {
+ NULL, /* use default error handler */
+ NULL, /* do not have a start functio */
+ NULL, /* have no async handler */
+ NULL, /* Use default done routine */
+};
+
+struct cfattach ptsc_ca = {
+ sizeof(struct ptsc_softc), ptscmatch, ptscattach
+};
+
+struct cfdriver ptsc_cd = {
+ NULL, "ptsc", DV_DULL, NULL, 0
+};
+
+int ptsc_intr __P((struct sfas_softc *dev));
+int ptsc_setup_dma __P((struct sfas_softc *sc, void *ptr, int len,
+ int mode));
+int ptsc_build_dma_chain __P((struct sfas_softc *sc,
+ struct sfas_dma_chain *chain, void *p, int l));
+int ptsc_need_bump __P((struct sfas_softc *sc, void *ptr, int len));
+void ptsc_led __P((struct sfas_softc *sc, int mode));
+
+/*
+ * if we are a Power-tec SCSI-2 card
+ */
+int
+ptscmatch(pdp, match, auxp)
+ struct device *pdp;
+ void *match, *auxp;
+{
+ struct podule_attach_args *pa = (struct podule_attach_args *)auxp;
+ int podule;
+
+ podule = findpodule(0x5b, 0x107, pa->pa_podule_number);
+
+ if (podule == -1)
+ return(0);
+
+ pa->pa_podule_number = podule;
+ pa->pa_podule = &podules[podule];
+
+ return(1);
+}
+
+void
+ptscattach(pdp, dp, auxp)
+ struct device *pdp;
+ struct device *dp;
+ void *auxp;
+{
+ struct ptsc_softc *sc = (struct ptsc_softc *)dp;
+ struct podule_attach_args *pa;
+ ptsc_regmap_p rp = &sc->sc_regmap;
+ vu_char *fas;
+
+ pa = (struct podule_attach_args *)auxp;
+ sc->sc_specific.sc_podule_number = pa->pa_podule_number;
+ if (sc->sc_specific.sc_podule_number == -1)
+ panic("Podule has disappeared !");
+
+ sc->sc_specific.sc_podule = &podules[sc->sc_specific.sc_podule_number];
+ sc->sc_specific.sc_iobase =
+ (vu_char *)sc->sc_specific.sc_podule->fast_base;
+
+ rp->chipreset = &sc->sc_specific.sc_iobase[PTSC_CONTROL_CHIPRESET];
+ rp->inten = &sc->sc_specific.sc_iobase[PTSC_CONTROL_INTEN];
+ rp->status = &sc->sc_specific.sc_iobase[PTSC_STATUS];
+ rp->term = &sc->sc_specific.sc_iobase[PTSC_CONTROL_TERM];
+ rp->led = &sc->sc_specific.sc_iobase[PTSC_CONTROL_LED];
+ fas = &sc->sc_specific.sc_iobase[PTSC_FASOFFSET_BASE];
+
+ rp->FAS216.sfas_tc_low = &fas[PTSC_FASOFFSET_TCL];
+ rp->FAS216.sfas_tc_mid = &fas[PTSC_FASOFFSET_TCM];
+ rp->FAS216.sfas_fifo = &fas[PTSC_FASOFFSET_FIFO];
+ rp->FAS216.sfas_command = &fas[PTSC_FASOFFSET_COMMAND];
+ rp->FAS216.sfas_dest_id = &fas[PTSC_FASOFFSET_DESTID];
+ rp->FAS216.sfas_timeout = &fas[PTSC_FASOFFSET_TIMEOUT];
+ rp->FAS216.sfas_syncper = &fas[PTSC_FASOFFSET_PERIOD];
+ rp->FAS216.sfas_syncoff = &fas[PTSC_FASOFFSET_OFFSET];
+ rp->FAS216.sfas_config1 = &fas[PTSC_FASOFFSET_CONFIG1];
+ rp->FAS216.sfas_clkconv = &fas[PTSC_FASOFFSET_CLOCKCONV];
+ rp->FAS216.sfas_test = &fas[PTSC_FASOFFSET_TEST];
+ rp->FAS216.sfas_config2 = &fas[PTSC_FASOFFSET_CONFIG2];
+ rp->FAS216.sfas_config3 = &fas[PTSC_FASOFFSET_CONFIG3];
+ rp->FAS216.sfas_tc_high = &fas[PTSC_FASOFFSET_TCH];
+ rp->FAS216.sfas_fifo_bot = &fas[PTSC_FASOFFSET_FIFOBOTTOM];
+
+ sc->sc_softc.sc_fas = (sfas_regmap_p)rp;
+ sc->sc_softc.sc_spec = &sc->sc_specific;
+
+ sc->sc_softc.sc_led = ptsc_led;
+
+ sc->sc_softc.sc_setup_dma = ptsc_setup_dma;
+ sc->sc_softc.sc_build_dma_chain = ptsc_build_dma_chain;
+ sc->sc_softc.sc_need_bump = ptsc_need_bump;
+
+ sc->sc_softc.sc_clock_freq = 8; /* Power-Tec runs at 8MHz */
+ sc->sc_softc.sc_timeout = 250; /* Set default timeout to 250ms */
+ sc->sc_softc.sc_config_flags = SFAS_NO_DMA /*| SFAS_NF_DEBUG*/;
+ sc->sc_softc.sc_host_id = 7; /* Should check the jumpers */
+
+ sc->sc_softc.sc_bump_sz = NBPG;
+ sc->sc_softc.sc_bump_pa = 0x0;
+
+ sfasinitialize((struct sfas_softc *)sc);
+
+ sc->sc_softc.sc_link.adapter_softc = sc;
+ sc->sc_softc.sc_link.adapter_target = sc->sc_softc.sc_host_id;
+ sc->sc_softc.sc_link.adapter = &ptsc_scsiswitch;
+ sc->sc_softc.sc_link.device = &ptsc_scsidev;
+ sc->sc_softc.sc_link.openings = 1;
+
+ sc->sc_softc.sc_ih.ih_func = ptsc_intr;
+ sc->sc_softc.sc_ih.ih_arg = &sc->sc_softc;
+ sc->sc_softc.sc_ih.ih_level = IPL_BIO;
+
+/* initialise the card */
+ *rp->term = 0;
+ *rp->inten = (PTSC_POLL?0:1);
+ *rp->led = 0;
+
+#if PTSC_POLL == 0
+ if (irq_claim(IRQ_PODULE /*IRQ_EXPCARD0 + sc->sc_specific.sc_podule_number */,
+ &sc->sc_softc.sc_ih))
+ panic("ptsc: Cannot install IRQ handler\n");
+#endif
+
+ printf("\n");
+
+/* attach all scsi units on us */
+ config_found(dp, &sc->sc_softc.sc_link, ptscprint);
+}
+
+/* print diag if pnp is NULL else just extra */
+int
+ptscprint(auxp, pnp)
+ void *auxp;
+ char *pnp;
+{
+ if (pnp == NULL)
+ return(UNCONF);
+
+ return(QUIET);
+}
+
+int
+ptsc_intr(dev)
+ struct sfas_softc *dev;
+{
+ ptsc_regmap_p rp;
+ int quickints;
+
+ rp = (ptsc_regmap_p)dev->sc_fas;
+
+ if (*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) {
+ quickints = 16;
+ do {
+ dev->sc_status = *rp->FAS216.sfas_status;
+ dev->sc_interrupt = *rp->FAS216.sfas_interrupt;
+
+ if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
+ dev->sc_resel[0] = *rp->FAS216.sfas_fifo;
+ dev->sc_resel[1] = *rp->FAS216.sfas_fifo;
+ }
+
+ sfasintr(dev);
+
+ } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING)
+ && --quickints);
+ }
+
+ return(1);
+}
+
+/* Load transfer address into dma register */
+void
+ptsc_set_dma_adr(sc, ptr)
+ struct sfas_softc *sc;
+ void *ptr;
+{
+ ptsc_regmap_p rp;
+ unsigned int *p;
+ unsigned int d;
+
+#if 0
+ printf("ptsc_set_dma_adr(sc = 0x%08x, ptr = 0x%08x)\n", (u_int)sc, (u_int)ptr);
+#endif
+ return;
+#if 0
+ rp = (ptsc_regmap_p)sc->sc_fas;
+
+ d = (unsigned int)ptr;
+ p = (unsigned int *)((d & 0xFFFFFF) + (int)rp->dmabase);
+
+ *rp->clear=0;
+ *p = d;
+#endif
+}
+
+/* Set DMA transfer counter */
+void
+ptsc_set_dma_tc(sc, len)
+ struct sfas_softc *sc;
+ unsigned int len;
+{
+ printf("ptsc_set_dma_tc(sc, len = 0x%08x)", len);
+
+ *sc->sc_fas->sfas_tc_low = len; len >>= 8;
+ *sc->sc_fas->sfas_tc_mid = len; len >>= 8;
+ *sc->sc_fas->sfas_tc_high = len;
+}
+
+/* Set DMA mode */
+void
+ptsc_set_dma_mode(sc, mode)
+ struct sfas_softc *sc;
+ int mode;
+{
+ struct csc_specific *spec;
+
+#if 0
+ spec = sc->sc_spec;
+
+ spec->portbits = (spec->portbits & ~FLSC_PB_DMA_BITS) | mode;
+ *((flsc_regmap_p)sc->sc_fas)->hardbits = spec->portbits;
+#endif
+}
+
+/* Initialize DMA for transfer */
+int
+ptsc_setup_dma(sc, ptr, len, mode)
+ struct sfas_softc *sc;
+ void *ptr;
+ int len;
+ int mode;
+{
+ int retval;
+
+ retval = 0;
+
+#if 0
+ printf("ptsc_setup_dma(sc, ptr = 0x%08x, len = 0x%08x, mode = 0x%08x)\n", (u_int)ptr, len, mode);
+#endif
+ return(0);
+
+#if 0
+ switch(mode) {
+ case SFAS_DMA_READ:
+ case SFAS_DMA_WRITE:
+ flsc_set_dma_adr(sc, ptr);
+ if (mode == SFAS_DMA_READ)
+ flsc_set_dma_mode(sc,FLSC_PB_ENABLE_DMA | FLSC_PB_DMA_READ);
+ else
+ flsc_set_dma_mode(sc,FLSC_PB_ENABLE_DMA | FLSC_PB_DMA_WRITE);
+
+ flsc_set_dma_tc(sc, len);
+ break;
+
+ case SFAS_DMA_CLEAR:
+ default:
+ flsc_set_dma_mode(sc, FLSC_PB_DISABLE_DMA);
+ flsc_set_dma_adr(sc, 0);
+
+ retval = (*sc->sc_fas->sfas_tc_high << 16) |
+ (*sc->sc_fas->sfas_tc_mid << 8) |
+ *sc->sc_fas->sfas_tc_low;
+
+ flsc_set_dma_tc(sc, 0);
+ break;
+ }
+
+ return(retval);
+#endif
+}
+
+/* Check if address and len is ok for DMA transfer */
+int
+ptsc_need_bump(sc, ptr, len)
+ struct sfas_softc *sc;
+ void *ptr;
+ int len;
+{
+ int p;
+
+ p = (int)ptr & 0x03;
+
+ if (p) {
+ p = 4-p;
+
+ if (len < 256)
+ p = len;
+ }
+
+ return(p);
+}
+
+/* Interrupt driven routines */
+int
+ptsc_build_dma_chain(sc, chain, p, l)
+ struct sfas_softc *sc;
+ struct sfas_dma_chain *chain;
+ void *p;
+ int l;
+{
+ vm_offset_t pa, lastpa;
+ char *ptr;
+ int len, prelen, postlen, max_t, n;
+
+#if 0
+ printf("ptsc_build_dma_chain()\n");
+#endif
+ return(0);
+
+#if 0
+ if (l == 0)
+ return(0);
+
+#define set_link(n, p, l, f)\
+do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0)
+
+ n = 0;
+
+ if (l < 512)
+ set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP);
+ else if ((p >= (void *)0xFF000000)
+#if M68040
+ && ((mmutype == MMU_68040) && (p >= (void *)0xFFFC0000))
+#endif
+ ) {
+ while(l != 0) {
+ len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l);
+
+ set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP);
+
+ p += len;
+ l -= len;
+ }
+ } else {
+ ptr = p;
+ len = l;
+
+ pa = kvtop(ptr);
+ prelen = ((int)ptr & 0x03);
+
+ if (prelen) {
+ prelen = 4-prelen;
+ set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP);
+ ptr += prelen;
+ len -= prelen;
+ }
+
+ lastpa = 0;
+ while(len > 3) {
+ pa = kvtop(ptr);
+ max_t = NBPG - (pa & PGOFSET);
+ if (max_t > len)
+ max_t = len;
+
+ max_t &= ~3;
+
+ if (lastpa == pa)
+ sc->sc_chain[n-1].len += max_t;
+ else
+ set_link(n, pa, max_t, SFAS_CHAIN_DMA);
+
+ lastpa = pa+max_t;
+
+ ptr += max_t;
+ len -= max_t;
+ }
+
+ if (len)
+ set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP);
+ }
+
+ return(n);
+#endif
+}
+
+/* Turn on/off led */
+void
+ptsc_led(sc, mode)
+ struct sfas_softc *sc;
+ int mode;
+{
+ ptsc_regmap_p rp;
+
+ rp = (ptsc_regmap_p)sc->sc_fas;
+
+ if (mode) {
+ sc->sc_led_status++;
+ } else {
+ if (sc->sc_led_status)
+ sc->sc_led_status--;
+ }
+ *rp->led = (sc->sc_led_status?1:0);
+}
+
+int
+ptsc_scsicmd(xs)
+ struct scsi_xfer *xs;
+{
+ /* ensure command is polling for the moment */
+#if PTSC_POLL > 0
+ xs->flags |= SCSI_POLL;
+#endif
+#if 0
+ printf("Opcode %d\n", (int)(xs->cmd->opcode));
+#endif
+ return(sfas_scsicmd(xs));
+}
--- /dev/null
+/* $NetBSD: ptscreg.h,v 1.1 1996/01/31 23:26:35 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ * Copyright (c) 1995 Daniel Widenfalk
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Daniel Widenfalk
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Power-tec SCSI-2 with FAS216 SCSI interface hardware description.
+ */
+
+#ifndef _PTSCREG_H_
+#define _PTSCREG_H_
+
+#include <arm32/podulebus/sfasvar.h>
+
+typedef volatile unsigned short vu_short;
+
+typedef struct ptsc_regmap {
+ sfas_regmap_t FAS216;
+ vu_char *chipreset;
+ vu_char *inten;
+ vu_char *status;
+ vu_char *term;
+ vu_char *led;
+} ptsc_regmap_t;
+typedef ptsc_regmap_t *ptsc_regmap_p;
+
+/* NDA Information */
+#define PTSC_CONTROL_CHIPRESET 0x1018
+#define PTSC_CONTROL_INTEN 0x101c
+#define PTSC_STATUS 0x2000
+#define PTSC_CONTROL_TERM 0x2018
+#define PTSC_CONTROL_LED 0x201c
+#define PTSC_FASOFFSET_BASE 0x3000
+#define PTSC_FASOFFSET_TCL 0x0000
+#define PTSC_FASOFFSET_TCM 0x0040
+#define PTSC_FASOFFSET_FIFO 0x0080
+#define PTSC_FASOFFSET_COMMAND 0x00c0
+#define PTSC_FASOFFSET_DESTID 0x0100
+#define PTSC_FASOFFSET_TIMEOUT 0x0140
+#define PTSC_FASOFFSET_PERIOD 0x0180
+#define PTSC_FASOFFSET_OFFSET 0x01c0
+#define PTSC_FASOFFSET_CONFIG1 0x0200
+#define PTSC_FASOFFSET_CLOCKCONV 0x0240
+#define PTSC_FASOFFSET_TEST 0x0280
+#define PTSC_FASOFFSET_CONFIG2 0x02c0
+#define PTSC_FASOFFSET_CONFIG3 0x0300
+#define PTSC_FASOFFSET_TCH 0x0380
+#define PTSC_FASOFFSET_FIFOBOTTOM 0x03c0
+/* NDA Info end */
+#endif
--- /dev/null
+/* $NetBSD: ptscvar.h,v 1.1 1996/01/31 23:26:38 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Daniel Widenfalk
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _PTSCVAR_H_
+#define _PTSCVAR_H_
+
+#include <arm32/podulebus/sfasvar.h>
+#include <arm32/podulebus/ptscreg.h>
+
+#define PTSC_POLL 1
+
+struct ptsc_specific {
+ vu_char *sc_iobase;
+ int sc_podule_number;
+ podule_t *sc_podule;
+};
+
+struct ptsc_softc {
+ struct sfas_softc sc_softc;
+ ptsc_regmap_t sc_regmap;
+ struct ptsc_specific sc_specific;
+};
+
+#endif /* _PTSCVAR_H_ */
--- /dev/null
+/* $NetBSD: sbic.c,v 1.2 1996/04/19 20:09:50 mark Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: sbic.c,v 1.21 1996/01/07 22:01:54
+ */
+#define DEBUG
+/*#define SBIC_DEBUG*/
+/*
+ * AMIGA AMD 33C93 scsi adaptor driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h> /* For hz */
+#include <sys/disklabel.h>
+#include <sys/dkstat.h>
+#include <sys/buf.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+/*#include <machine/pmap.h>
+#include <machine/cpu.h>*/
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/sbicreg.h>
+#include <arm32/podulebus/sbicvar.h>
+#include <arm32/podulebus/ascreg.h>
+
+/* These are for bounce buffers */
+
+/*#include <vm/pmap.h>*/
+
+/* Since I can't find this in any other header files */
+#define SCSI_PHASE(reg) (reg&0x07)
+
+/*
+ * SCSI delays
+ * In u-seconds, primarily for state changes on the SPC.
+ */
+#define SBIC_CMD_WAIT 50000 /* wait per step of 'immediate' cmds */
+#define SBIC_DATA_WAIT 50000 /* wait per data in/out step */
+#define SBIC_INIT_WAIT 50000 /* wait per step (both) during init */
+
+#define b_cylin b_resid
+#define SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__)
+
+extern u_int kvtop();
+
+int sbicicmd __P((struct sbic_softc *, int, int, void *, int, void *, int));
+int sbicgo __P((struct sbic_softc *, struct scsi_xfer *));
+int sbicdmaok __P((struct sbic_softc *, struct scsi_xfer *));
+int sbicwait __P((sbic_regmap_p, char, int , int));
+int sbiccheckdmap __P((void *, u_long, u_long));
+int sbicselectbus __P((struct sbic_softc *, sbic_regmap_p, u_char, u_char, u_char));
+int sbicxfstart __P((sbic_regmap_p, int, u_char, int));
+int sbicxfout __P((sbic_regmap_p regs, int, void *, int));
+int sbicfromscsiperiod __P((struct sbic_softc *, sbic_regmap_p, int));
+int sbictoscsiperiod __P((struct sbic_softc *, sbic_regmap_p, int));
+int sbicintr __P((struct sbic_softc *));
+int sbicpoll __P((struct sbic_softc *));
+int sbicnextstate __P((struct sbic_softc *, u_char, u_char));
+int sbicmsgin __P((struct sbic_softc *));
+int sbicxfin __P((sbic_regmap_p regs, int, void *));
+int sbicabort __P((struct sbic_softc *, sbic_regmap_p, char *));
+void sbicxfdone __P((struct sbic_softc *, sbic_regmap_p, int));
+void sbicerror __P((struct sbic_softc *, sbic_regmap_p, u_char));
+void sbicstart __P((struct sbic_softc *));
+void sbicreset __P((struct sbic_softc *));
+void sbic_scsidone __P((struct sbic_acb *, int));
+void sbic_sched __P((struct sbic_softc *));
+void sbic_save_ptrs __P((struct sbic_softc *, sbic_regmap_p,int,int));
+void sbic_load_ptrs __P((struct sbic_softc *, sbic_regmap_p,int,int));
+
+/*
+ * Synch xfer parameters, and timing conversions
+ */
+int sbic_min_period = SBIC_SYN_MIN_PERIOD; /* in cycles = f(ICLK,FSn) */
+int sbic_max_offset = SBIC_SYN_MAX_OFFSET; /* pure number */
+
+int sbic_cmd_wait = SBIC_CMD_WAIT;
+int sbic_data_wait = SBIC_DATA_WAIT;
+int sbic_init_wait = SBIC_INIT_WAIT;
+
+/*
+ * was broken before.. now if you want this you get it for all drives
+ * on sbic controllers.
+ */
+u_char sbic_inhibit_sync[8];
+int sbic_enable_reselect = 1;
+int sbic_clock_override = 0;
+int sbic_no_dma = 1; /* was 0 */
+int sbic_parallel_operations = 1;
+
+#ifdef DEBUG
+sbic_regmap_p debug_sbic_regs;
+int sbicdma_ops = 0; /* total DMA operations */
+int sbicdma_bounces = 0; /* number operations using bounce buffer */
+int sbicdma_hits = 0; /* number of DMA chains that were contiguous */
+int sbicdma_misses = 0; /* number of DMA chains that were not contiguous */
+int sbicdma_saves = 0;
+#define QPRINTF(a) if (sbic_debug > 1) printf a
+int sbic_debug = 0;
+int sync_debug = 0;
+int sbic_dma_debug = 0;
+int reselect_debug = 0;
+int report_sense = 0;
+int data_pointer_debug = 0;
+u_char debug_asr, debug_csr, routine;
+void sbictimeout __P((struct sbic_softc *dev));
+void sbic_dump __P((struct sbic_softc *dev));
+
+#define CSR_TRACE_SIZE 32
+#if CSR_TRACE_SIZE
+#define CSR_TRACE(w,c,a,x) do { \
+ int s = splbio(); \
+ csr_trace[csr_traceptr].whr = (w); csr_trace[csr_traceptr].csr = (c); \
+ csr_trace[csr_traceptr].asr = (a); csr_trace[csr_traceptr].xtn = (x); \
+/* dma_cachectl(&csr_trace[csr_traceptr], sizeof(csr_trace[0]));*/ \
+ csr_traceptr = (csr_traceptr + 1) & (CSR_TRACE_SIZE - 1); \
+/* dma_cachectl(&csr_traceptr, sizeof(csr_traceptr));*/ \
+ splx(s); \
+} while (0)
+int csr_traceptr;
+int csr_tracesize = CSR_TRACE_SIZE;
+struct {
+ u_char whr;
+ u_char csr;
+ u_char asr;
+ u_char xtn;
+} csr_trace[CSR_TRACE_SIZE];
+#else
+#define CSR_TRACE
+#endif
+
+#define SBIC_TRACE_SIZE 0
+#if SBIC_TRACE_SIZE
+#define SBIC_TRACE(dev) do { \
+ int s = splbio(); \
+ sbic_trace[sbic_traceptr].sp = &s; \
+ sbic_trace[sbic_traceptr].line = __LINE__; \
+ sbic_trace[sbic_traceptr].sr = s; \
+ sbic_trace[sbic_traceptr].csr = csr_traceptr; \
+/* dma_cachectl(&sbic_trace[sbic_traceptr], sizeof(sbic_trace[0]));*/ \
+ sbic_traceptr = (sbic_traceptr + 1) & (SBIC_TRACE_SIZE - 1); \
+/* dma_cachectl(&sbic_traceptr, sizeof(sbic_traceptr));*/ \
+ if (dev) dma_cachectl(dev, sizeof(*dev)); \
+ splx(s); \
+} while (0)
+int sbic_traceptr;
+int sbic_tracesize = SBIC_TRACE_SIZE;
+struct {
+ void *sp;
+ u_short line;
+ u_short sr;
+ int csr;
+} sbic_trace[SBIC_TRACE_SIZE];
+#else
+#define SBIC_TRACE
+#endif
+
+#else
+#define QPRINTF
+#define CSR_TRACE
+#define SBIC_TRACE
+#endif
+
+/*
+ * default minphys routine for sbic based controllers
+ */
+void
+sbic_minphys(bp)
+ struct buf *bp;
+{
+
+ /*
+ * No max transfer at this level.
+ */
+ minphys(bp);
+}
+
+/*
+ * Save DMA pointers. Take into account partial transfer. Shut down DMA.
+ */
+void
+sbic_save_ptrs(dev, regs, target, lun)
+ struct sbic_softc *dev;
+ sbic_regmap_p regs;
+ int target, lun;
+{
+ int count, asr, csr, s;
+ unsigned long ptr;
+ char *vptr;
+ struct sbic_acb* acb;
+
+ extern vm_offset_t vm_first_phys;
+
+ SBIC_TRACE(dev);
+ if( !dev->sc_cur ) return;
+ if( !(dev->sc_flags & SBICF_INDMA) ) return; /* DMA not active */
+
+ s = splbio();
+
+ acb = dev->sc_nexus;
+ count = -1;
+ do {
+ GET_SBIC_asr(regs, asr);
+ if( asr & SBIC_ASR_DBR ) {
+ printf("sbic_save_ptrs: asr %02x canceled!\n", asr);
+ splx(s);
+ SBIC_TRACE(dev);
+ return;
+ }
+ } while( asr & (SBIC_ASR_BSY|SBIC_ASR_CIP) );
+
+ /* Save important state */
+ /* must be done before dmastop */
+ acb->sc_dmacmd = dev->sc_dmacmd;
+ SBIC_TC_GET(regs, count);
+
+ /* Shut down DMA ====CAREFUL==== */
+ dev->sc_dmastop(dev);
+ dev->sc_flags &= ~SBICF_INDMA;
+ SBIC_TC_PUT(regs, 0);
+
+#ifdef DEBUG
+ if(!count && sbic_debug) printf("%dcount0",target);
+ if(data_pointer_debug == -1)
+ printf("SBIC saving target %d data pointers from (%x,%x)%xASR:%02x",
+ target, dev->sc_cur->dc_addr, dev->sc_cur->dc_count,
+ acb->sc_dmacmd, asr);
+#endif
+
+ /* Fixup partial xfers */
+ acb->sc_kv.dc_addr += (dev->sc_tcnt - count);
+ acb->sc_kv.dc_count -= (dev->sc_tcnt - count);
+ acb->sc_pa.dc_addr += (dev->sc_tcnt - count);
+ acb->sc_pa.dc_count -= ((dev->sc_tcnt - count)>>1);
+
+ acb->sc_tcnt = dev->sc_tcnt = count;
+#ifdef DEBUG
+ if(data_pointer_debug)
+ printf(" at (%x,%x):%x\n",
+ dev->sc_cur->dc_addr, dev->sc_cur->dc_count,count);
+ sbicdma_saves++;
+#endif
+ splx(s);
+ SBIC_TRACE(dev);
+}
+
+
+/*
+ * DOES NOT RESTART DMA!!!
+ */
+void sbic_load_ptrs(dev, regs, target, lun)
+ struct sbic_softc *dev;
+ sbic_regmap_p regs;
+ int target, lun;
+{
+ int i, s, asr, count;
+ char* vaddr, * paddr;
+ struct sbic_acb *acb;
+
+ SBIC_TRACE(dev);
+ acb = dev->sc_nexus;
+ if( !acb->sc_kv.dc_count ) {
+ /* No data to xfer */
+ SBIC_TRACE(dev);
+ return;
+ }
+
+ s = splbio();
+
+ dev->sc_last = dev->sc_cur = &acb->sc_pa;
+ dev->sc_tcnt = acb->sc_tcnt;
+ dev->sc_dmacmd = acb->sc_dmacmd;
+
+#ifdef DEBUG
+ sbicdma_ops++;
+#endif
+ if( !dev->sc_tcnt ) {
+ /* sc_tcnt == 0 implies end of segment */
+
+ /* do kvm to pa mappings */
+#if 0 /* mark */
+ paddr = acb->sc_pa.dc_addr =
+ (char *) kvtop(acb->sc_kv.dc_addr);
+#endif
+ vaddr = acb->sc_kv.dc_addr;
+ count = acb->sc_kv.dc_count;
+#if 0 /* mark */
+ for(count = (NBPG - ((int)vaddr & PGOFSET));
+ count < acb->sc_kv.dc_count
+ && (char*)kvtop(vaddr + count + 4) == paddr + count + 4;
+ count += NBPG);
+#endif
+ /* If it's all contiguous... */
+ if(count > acb->sc_kv.dc_count ) {
+ count = acb->sc_kv.dc_count;
+#ifdef DEBUG
+ sbicdma_hits++;
+#endif
+ } else {
+#ifdef DEBUG
+ sbicdma_misses++;
+#endif
+ }
+ acb->sc_tcnt = count;
+ acb->sc_pa.dc_count = count >> 1;
+
+#ifdef DEBUG
+ if(data_pointer_debug)
+ printf("DMA recalc:kv(%x,%x)pa(%x,%x)\n",
+ acb->sc_kv.dc_addr,
+ acb->sc_kv.dc_count,
+ acb->sc_pa.dc_addr,
+ acb->sc_tcnt);
+#endif
+ }
+ splx(s);
+#ifdef DEBUG
+ if(data_pointer_debug)
+ printf("SBIC restoring target %d data pointers at (%x,%x)%x\n",
+ target, dev->sc_cur->dc_addr, dev->sc_cur->dc_count,
+ dev->sc_dmacmd);
+#endif
+ SBIC_TRACE(dev);
+}
+
+/*
+ * used by specific sbic controller
+ *
+ * it appears that the higher level code does nothing with LUN's
+ * so I will too. I could plug it in, however so could they
+ * in scsi_scsi_cmd().
+ */
+int
+sbic_scsicmd(xs)
+ struct scsi_xfer *xs;
+{
+ struct sbic_acb *acb;
+ struct sbic_softc *dev;
+ struct scsi_link *slp;
+ int flags, s, stat;
+
+ slp = xs->sc_link;
+ dev = slp->adapter_softc;
+ SBIC_TRACE(dev);
+ flags = xs->flags;
+
+ if (flags & SCSI_DATA_UIO)
+ panic("sbic: scsi data uio requested");
+
+ if (dev->sc_nexus && flags & SCSI_POLL)
+ panic("sbic_scsicmd: busy");
+
+ if (slp->target == slp->adapter_target)
+ return ESCAPE_NOT_SUPPORTED;
+
+ s = splbio();
+ acb = dev->free_list.tqh_first;
+ if (acb)
+ TAILQ_REMOVE(&dev->free_list, acb, chain);
+ splx(s);
+
+ if (acb == NULL) {
+#ifdef DEBUG
+ printf("sbic_scsicmd: unable to queue request for target %d\n",
+ slp->target);
+#ifdef DDB
+ Debugger();
+#endif
+#endif
+ xs->error = XS_DRIVER_STUFFUP;
+ SBIC_TRACE(dev);
+ return(TRY_AGAIN_LATER);
+ }
+
+ acb->flags = ACB_ACTIVE;
+ if (flags & SCSI_DATA_IN)
+ acb->flags |= ACB_DATAIN;
+ acb->xs = xs;
+ bcopy(xs->cmd, &acb->cmd, xs->cmdlen);
+ acb->clen = xs->cmdlen;
+ acb->sc_kv.dc_addr = xs->data;
+ acb->sc_kv.dc_count = xs->datalen;
+#if 0
+ acb->pa_addr = xs->data ? (char *)kvtop(xs->data) : 0; /* XXXX check */
+#endif
+ if (flags & SCSI_POLL) {
+ s = splbio();
+ /*
+ * This has major side effects -- it locks up the machine
+ */
+
+ dev->sc_flags |= SBICF_ICMD;
+ do {
+ while(dev->sc_nexus)
+ sbicpoll(dev);
+ dev->sc_nexus = acb;
+ dev->sc_stat[0] = -1;
+ dev->sc_xs = xs;
+ dev->target = slp->target;
+ dev->lun = slp->lun;
+ stat = sbicicmd(dev, slp->target, slp->lun,
+ &acb->cmd, acb->clen,
+ acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
+ } while (dev->sc_nexus != acb);
+ sbic_scsidone(acb, stat);
+
+ splx(s);
+ SBIC_TRACE(dev);
+ return(COMPLETE);
+ }
+
+ s = splbio();
+ TAILQ_INSERT_TAIL(&dev->ready_list, acb, chain);
+
+ if (dev->sc_nexus) {
+ splx(s);
+ SBIC_TRACE(dev);
+ return(SUCCESSFULLY_QUEUED);
+ }
+
+ /*
+ * nothing is active, try to start it now.
+ */
+ sbic_sched(dev);
+ splx(s);
+
+ SBIC_TRACE(dev);
+/* TODO: add sbic_poll to do SCSI_POLL operations */
+#if 0
+ if (flags & SCSI_POLL)
+ return(COMPLETE);
+#endif
+ return(SUCCESSFULLY_QUEUED);
+}
+
+/*
+ * attempt to start the next available command
+ */
+void
+sbic_sched(dev)
+ struct sbic_softc *dev;
+{
+ struct scsi_xfer *xs;
+ struct scsi_link *slp;
+ struct sbic_acb *acb;
+ int flags, /*phase,*/ stat, i;
+
+ SBIC_TRACE(dev);
+ if (dev->sc_nexus)
+ return; /* a command is current active */
+
+ SBIC_TRACE(dev);
+ for (acb = dev->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) {
+ slp = acb->xs->sc_link;
+ i = slp->target;
+ if (!(dev->sc_tinfo[i].lubusy & (1 << slp->lun))) {
+ struct sbic_tinfo *ti = &dev->sc_tinfo[i];
+
+ TAILQ_REMOVE(&dev->ready_list, acb, chain);
+ dev->sc_nexus = acb;
+ slp = acb->xs->sc_link;
+ ti = &dev->sc_tinfo[slp->target];
+ ti->lubusy |= (1 << slp->lun);
+ acb->sc_pa.dc_addr = acb->pa_addr; /* XXXX check */
+ break;
+ }
+ }
+
+ SBIC_TRACE(dev);
+ if (acb == NULL)
+ return; /* did not find an available command */
+
+ dev->sc_xs = xs = acb->xs;
+ slp = xs->sc_link;
+ flags = xs->flags;
+
+ if (flags & SCSI_RESET)
+ sbicreset(dev);
+
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("sbic_sched(%d,%d)\n",slp->target,slp->lun);
+#endif
+ dev->sc_stat[0] = -1;
+ dev->target = slp->target;
+ dev->lun = slp->lun;
+ if ( flags & SCSI_POLL || ( !sbic_parallel_operations
+ && (/*phase == STATUS_PHASE ||*/
+ sbicdmaok(dev, xs) == 0) ) )
+ stat = sbicicmd(dev, slp->target, slp->lun, &acb->cmd,
+ acb->clen, acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
+ else if (sbicgo(dev, xs) == 0) {
+ SBIC_TRACE(dev);
+ return;
+ } else
+ stat = dev->sc_stat[0];
+
+ sbic_scsidone(acb, stat);
+ SBIC_TRACE(dev);
+}
+
+void
+sbic_scsidone(acb, stat)
+ struct sbic_acb *acb;
+ int stat;
+{
+ struct scsi_xfer *xs;
+ struct scsi_link *slp;
+ struct sbic_softc *dev;
+ int s, dosched = 0;
+
+ xs = acb->xs;
+ slp = xs->sc_link;
+ dev = slp->adapter_softc;
+ SBIC_TRACE(dev);
+#ifdef DIAGNOSTIC
+ if (acb == NULL || xs == NULL) {
+ printf("sbic_scsidone -- (%d,%d) no scsi_xfer\n",
+ dev->target, dev->lun);
+#ifdef DDB
+ Debugger();
+#endif
+ return;
+ }
+#endif
+ /*
+ * XXX Support old-style instrumentation for now.
+ * IS THIS REALLY THE RIGHT PLACE FOR THIS? --thorpej
+ */
+ if (slp->device_softc &&
+ ((struct device *)(slp->device_softc))->dv_unit < dk_ndrive)
+ ++dk_xfer[((struct device *)(slp->device_softc))->dv_unit];
+ /*
+ * is this right?
+ */
+ xs->status = stat;
+
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("scsidone: (%d,%d)->(%d,%d)%02x\n",
+ slp->target, slp->lun,
+ dev->target, dev->lun, stat);
+ if( xs->sc_link->target == dev->sc_link.adapter_target )
+ panic("target == hostid");
+#endif
+
+ if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) {
+ if (stat == SCSI_CHECK) {
+ /* Schedule a REQUEST SENSE */
+ struct scsi_sense *ss = (void *)&acb->cmd;
+#ifdef DEBUG
+ if (report_sense)
+ printf("sbic_scsidone: autosense %02x targ %d lun %d",
+ acb->cmd.opcode, slp->target, slp->lun);
+#endif
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = slp->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+ acb->clen = sizeof(*ss);
+ acb->sc_kv.dc_addr = (char *)&xs->sense;
+ acb->sc_kv.dc_count = sizeof(struct scsi_sense_data);
+#if 0
+ acb->pa_addr = (char *)kvtop(&xs->sense); /* XXX check */
+#endif
+ acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN;
+ TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain);
+ dev->sc_tinfo[slp->target].lubusy &=
+ ~(1 << slp->lun);
+ dev->sc_tinfo[slp->target].senses++;
+ if (dev->sc_nexus == acb) {
+ dev->sc_nexus = NULL;
+ dev->sc_xs = NULL;
+ sbic_sched(dev);
+ }
+ SBIC_TRACE(dev);
+ return;
+ }
+ }
+ if (xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE)) {
+ xs->error = XS_SENSE;
+#ifdef DEBUG
+ if (report_sense)
+ printf(" => %02x %02x\n", xs->sense.flags,
+ xs->sense.extra_bytes[3]);
+#endif
+ } else {
+ xs->resid = 0; /* XXXX */
+ }
+#if whataboutthisone
+ case SCSI_BUSY:
+ xs->error = XS_BUSY;
+ break;
+#endif
+ xs->flags |= ITSDONE;
+
+ /*
+ * Remove the ACB from whatever queue it's on. We have to do a bit of
+ * a hack to figure out which queue it's on. Note that it is *not*
+ * necessary to cdr down the ready queue, but we must cdr down the
+ * nexus queue and see if it's there, so we can mark the unit as no
+ * longer busy. This code is sickening, but it works.
+ */
+ if (acb == dev->sc_nexus) {
+ dev->sc_nexus = NULL;
+ dev->sc_xs = NULL;
+ dev->sc_tinfo[slp->target].lubusy &= ~(1<<slp->lun);
+ if (dev->ready_list.tqh_first)
+ dosched = 1; /* start next command */
+ } else if (dev->ready_list.tqh_last == &acb->chain.tqe_next) {
+ TAILQ_REMOVE(&dev->ready_list, acb, chain);
+ } else {
+ register struct sbic_acb *acb2;
+ for (acb2 = dev->nexus_list.tqh_first; acb2;
+ acb2 = acb2->chain.tqe_next) {
+ if (acb2 == acb) {
+ TAILQ_REMOVE(&dev->nexus_list, acb, chain);
+ dev->sc_tinfo[slp->target].lubusy
+ &= ~(1<<slp->lun);
+ break;
+ }
+ }
+ if (acb2)
+ ;
+ else if (acb->chain.tqe_next) {
+ TAILQ_REMOVE(&dev->ready_list, acb, chain);
+ } else {
+ printf("%s: can't find matching acb\n",
+ dev->sc_dev.dv_xname);
+#ifdef DDB
+ Debugger();
+#endif
+ }
+ }
+ /* Put it on the free list. */
+ acb->flags = ACB_FREE;
+ TAILQ_INSERT_HEAD(&dev->free_list, acb, chain);
+
+ dev->sc_tinfo[slp->target].cmds++;
+
+ scsi_done(xs);
+
+ if (dosched)
+ sbic_sched(dev);
+ SBIC_TRACE(dev);
+}
+
+int
+sbicdmaok(dev, xs)
+ struct sbic_softc *dev;
+ struct scsi_xfer *xs;
+{
+ if (sbic_no_dma || xs->datalen & 0x1 || (u_int)xs->data & 0x3)
+ return(0);
+ /*
+ * controller supports dma to any addresses?
+ */
+ else if ((dev->sc_flags & SBICF_BADDMA) == 0)
+ return(1);
+ /*
+ * this address is ok for dma?
+ */
+ else if (sbiccheckdmap(xs->data, xs->datalen, dev->sc_dmamask) == 0)
+ return(1);
+ /*
+ * we have a bounce buffer?
+ */
+ else if (dev->sc_tinfo[xs->sc_link->target].bounce)
+ return(1);
+ /*
+ * try to get one
+ */
+ else if (dev->sc_tinfo[xs->sc_link->target].bounce
+ = (char *)alloc_z2mem(MAXPHYS)) {
+ if (isztwomem(dev->sc_tinfo[xs->sc_link->target].bounce))
+ printf("alloc ZII target %d bounce pa 0x%x\n",
+ xs->sc_link->target,
+ kvtop(dev->sc_tinfo[xs->sc_link->target].bounce));
+ else if (dev->sc_tinfo[xs->sc_link->target].bounce)
+ printf("alloc CHIP target %d bounce pa 0x%x\n",
+ xs->sc_link->target,
+ PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->target].bounce));
+ return(1);
+ }
+
+ return(0);
+}
+
+
+int
+sbicwait(regs, until, timeo, line)
+ sbic_regmap_p regs;
+ char until;
+ int timeo;
+ int line;
+{
+ u_char val;
+ int csr;
+
+ SBIC_TRACE((struct sbic_softc *)0);
+ if (timeo == 0)
+ timeo = 1000000; /* some large value.. */
+
+ GET_SBIC_asr(regs,val);
+ while ((val & until) == 0) {
+ if (timeo-- == 0) {
+ GET_SBIC_csr(regs, csr);
+ printf("sbicwait TIMEO @%d with asr=x%x csr=x%x\n",
+ line, val, csr);
+#if defined(DDB) && defined(DEBUG)
+ Debugger();
+#endif
+ return(val); /* Maybe I should abort */
+ break;
+ }
+ DELAY(1);
+ GET_SBIC_asr(regs,val);
+ }
+ SBIC_TRACE((struct sbic_softc *)0);
+ return(val);
+}
+
+int
+sbicabort(dev, regs, where)
+ struct sbic_softc *dev;
+ sbic_regmap_p regs;
+ char *where;
+{
+ u_char csr, asr;
+
+ GET_SBIC_asr(regs, asr);
+ GET_SBIC_csr(regs, csr);
+
+ printf ("%s: abort %s: csr = 0x%02x, asr = 0x%02x\n",
+ dev->sc_dev.dv_xname, where, csr, asr);
+
+
+#if 0
+ /* Clean up running command */
+ if (dev->sc_nexus != NULL) {
+ dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP;
+ sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]);
+ }
+ while (acb = dev->nexus_list.tqh_first) {
+ acb->xs->error = XS_DRIVER_STUFFUP;
+ sbic_scsidone(acb, -1 /*acb->stat[0]*/);
+ }
+#endif
+
+ /* Clean up chip itself */
+ if (dev->sc_flags & SBICF_SELECTED) {
+ while( asr & SBIC_ASR_DBR ) {
+ /* sbic is jammed w/data. need to clear it */
+ /* But we don't know what direction it needs to go */
+ GET_SBIC_data(regs, asr);
+ printf("%s: abort %s: clearing data buffer 0x%02x\n",
+ dev->sc_dev.dv_xname, where, asr);
+ GET_SBIC_asr(regs, asr);
+ if( asr & SBIC_ASR_DBR ) /* Not the read direction, then */
+ SET_SBIC_data(regs, asr);
+ GET_SBIC_asr(regs, asr);
+ }
+ WAIT_CIP(regs);
+printf("%s: sbicabort - sending ABORT command\n", dev->sc_dev.dv_xname);
+ SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
+ WAIT_CIP(regs);
+
+ GET_SBIC_asr(regs, asr);
+ if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) {
+ /* ok, get more drastic.. */
+
+printf("%s: sbicabort - asr %x, trying to reset\n", dev->sc_dev.dv_xname, asr);
+ sbicreset(dev);
+ dev->sc_flags &= ~SBICF_SELECTED;
+ return -1;
+ }
+printf("%s: sbicabort - sending DISC command\n", dev->sc_dev.dv_xname);
+ SET_SBIC_cmd(regs, SBIC_CMD_DISC);
+
+ do {
+ asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0);
+ GET_SBIC_csr (regs, csr);
+ CSR_TRACE('a',csr,asr,0);
+ } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
+ && (csr != SBIC_CSR_CMD_INVALID));
+
+ /* lets just hope it worked.. */
+ dev->sc_flags &= ~SBICF_SELECTED;
+ }
+ return -1;
+}
+
+
+/*
+ * Initialize driver-private structures
+ */
+
+void
+sbicinit(dev)
+ struct sbic_softc *dev;
+{
+ sbic_regmap_p regs;
+ u_int my_id, i, s;
+ u_char csr;
+ struct sbic_acb *acb;
+ u_int inhibit_sync;
+
+ extern u_long scsi_nosync;
+ extern int shift_nosync;
+
+#ifdef SBIC_DEBUG
+ printf("sbicinit:\n");
+#endif
+
+ regs = dev->sc_sbicp;
+
+ if ((dev->sc_flags & SBICF_ALIVE) == 0) {
+ TAILQ_INIT(&dev->ready_list);
+ TAILQ_INIT(&dev->nexus_list);
+ TAILQ_INIT(&dev->free_list);
+ dev->sc_nexus = NULL;
+ dev->sc_xs = NULL;
+ acb = dev->sc_acb;
+ bzero(acb, sizeof(dev->sc_acb));
+#ifdef SBIC_DEBUG
+ printf("sbicinit: %d\n", __LINE__);
+#endif
+
+ for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
+ TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
+ acb++;
+ }
+ bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo));
+#ifdef DEBUG
+ /* make sure timeout is really not needed */
+ timeout((void *)sbictimeout, dev, 30 * hz);
+#endif
+
+ } else panic("sbic: reinitializing driver!");
+
+#ifdef SBIC_DEBUG
+ printf("sbicinit: %d\n", __LINE__);
+#endif
+
+ dev->sc_flags |= SBICF_ALIVE;
+ dev->sc_flags &= ~SBICF_SELECTED;
+
+ /* initialize inhibit array */
+ if (scsi_nosync) {
+#ifdef SBIC_DEBUG
+ printf("sbicinit: %d\n", __LINE__);
+#endif
+ inhibit_sync = (scsi_nosync >> shift_nosync) & 0xff;
+ shift_nosync += 8;
+#ifdef DEBUG
+ if (inhibit_sync)
+ printf("%s: Inhibiting synchronous transfer %02x\n",
+ dev->sc_dev.dv_xname, inhibit_sync);
+#endif
+ for (i = 0; i < 8; ++i)
+ if (inhibit_sync & (1 << i))
+ sbic_inhibit_sync[i] = 1;
+ }
+
+#ifdef SBIC_DEBUG
+ printf("sbicinit: %d\n", __LINE__);
+#endif
+
+ sbicreset(dev);
+}
+
+void
+sbicreset(dev)
+ struct sbic_softc *dev;
+{
+ sbic_regmap_p regs;
+ u_int my_id, i, s;
+ u_char csr;
+ struct sbic_acb *acb;
+
+#ifdef SBIC_DEBUG
+ printf("sbicreset: %d\n", __LINE__);
+#endif
+
+ regs = dev->sc_sbicp;
+
+#ifdef SBIC_DEBUG
+ printf("sbicreset: regs = %08x\n", regs);
+#endif
+#if 0
+ if (dev->sc_flags & SBICF_ALIVE) {
+ SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
+ WAIT_CIP(regs);
+ }
+#else
+ SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
+#ifdef SBIC_DEBUG
+ printf("sbicreset: %d\n", __LINE__);
+#endif
+ WAIT_CIP(regs);
+#ifdef SBIC_DEBUG
+ printf("sbicreset: %d\n", __LINE__);
+#endif
+#endif
+ s = splbio();
+ my_id = dev->sc_link.adapter_target & SBIC_ID_MASK;
+
+ /* Enable advanced mode */
+ my_id |= SBIC_ID_EAF /*| SBIC_ID_EHP*/ ;
+ SET_SBIC_myid(regs, my_id);
+#ifdef SBIC_DEBUG
+ printf("sbicreset: %d\n", __LINE__);
+#endif
+
+ /*
+ * Disable interrupts (in dmainit) then reset the chip
+ */
+ SET_SBIC_cmd(regs, SBIC_CMD_RESET);
+ DELAY(25);
+ SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+ GET_SBIC_csr(regs, csr); /* clears interrupt also */
+
+ if (dev->sc_clkfreq < 110)
+ my_id |= SBIC_ID_FS_8_10;
+ else if (dev->sc_clkfreq < 160)
+ my_id |= SBIC_ID_FS_12_15;
+ else if (dev->sc_clkfreq < 210)
+ my_id |= SBIC_ID_FS_16_20;
+
+ SET_SBIC_myid(regs, my_id);
+#ifdef SBIC_DEBUG
+ printf("sbicreset: %d\n", __LINE__);
+#endif
+
+ /*
+ * Set up various chip parameters
+ */
+ SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /* | SBIC_CTL_HSP */
+ | SBIC_MACHINE_DMA_MODE);
+ /*
+ * don't allow (re)selection (SBIC_RID_ES)
+ * until we can handle target mode!!
+ */
+ SET_SBIC_rselid(regs, SBIC_RID_ER);
+ SET_SBIC_syn(regs, 0); /* asynch for now */
+
+ /*
+ * anything else was zeroed by reset
+ */
+ splx(s);
+
+#if 0
+ if ((dev->sc_flags & SBICF_ALIVE) == 0) {
+ TAILQ_INIT(&dev->ready_list);
+ TAILQ_INIT(&dev->nexus_list);
+ TAILQ_INIT(&dev->free_list);
+ dev->sc_nexus = NULL;
+ dev->sc_xs = NULL;
+ acb = dev->sc_acb;
+ bzero(acb, sizeof(dev->sc_acb));
+ for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
+ TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
+ acb++;
+ }
+ bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo));
+ } else {
+ if (dev->sc_nexus != NULL) {
+ dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP;
+ sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]);
+ }
+ while (acb = dev->nexus_list.tqh_first) {
+ acb->xs->error = XS_DRIVER_STUFFUP;
+ sbic_scsidone(acb, -1 /*acb->stat[0]*/);
+ }
+ }
+
+ dev->sc_flags |= SBICF_ALIVE;
+#endif
+ dev->sc_flags &= ~SBICF_SELECTED;
+}
+
+void
+sbicerror(dev, regs, csr)
+ struct sbic_softc *dev;
+ sbic_regmap_p regs;
+ u_char csr;
+{
+ struct scsi_xfer *xs;
+
+ xs = dev->sc_xs;
+
+#ifdef DIAGNOSTIC
+ if (xs == NULL)
+ panic("sbicerror");
+#endif
+ if (xs->flags & SCSI_SILENT)
+ return;
+
+ printf("%s: ", dev->sc_dev.dv_xname);
+ printf("csr == 0x%02x\n", csr); /* XXX */
+}
+
+/*
+ * select the bus, return when selected or error.
+ */
+int
+sbicselectbus(dev, regs, target, lun, our_addr)
+ struct sbic_softc *dev;
+ sbic_regmap_p regs;
+ u_char target, lun, our_addr;
+{
+ u_char asr, csr, id;
+
+ SBIC_TRACE(dev);
+ QPRINTF(("sbicselectbus %d\n", target));
+
+ /*
+ * if we're already selected, return (XXXX panic maybe?)
+ */
+ if (dev->sc_flags & SBICF_SELECTED) {
+ SBIC_TRACE(dev);
+ return(1);
+ }
+
+ /*
+ * issue select
+ */
+ SBIC_TC_PUT(regs, 0);
+ SET_SBIC_selid(regs, target);
+ SET_SBIC_timeo(regs, SBIC_TIMEOUT(250,dev->sc_clkfreq));
+
+ /*
+ * set sync or async
+ */
+ if (dev->sc_sync[target].state == SYNC_DONE)
+ SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[target].offset,
+ dev->sc_sync[target].period));
+ else
+ SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
+
+ GET_SBIC_asr(regs, asr);
+ if( asr & (SBIC_ASR_INT|SBIC_ASR_BSY) ) {
+ /* This means we got ourselves reselected upon */
+/* printf("sbicselectbus: INT/BSY asr %02x\n", asr);*/
+#ifdef DDB
+/* Debugger();*/
+#endif
+ SBIC_TRACE(dev);
+ return 1;
+ }
+
+ SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN);
+
+ /*
+ * wait for select (merged from seperate function may need
+ * cleanup)
+ */
+ WAIT_CIP(regs);
+ do {
+ asr = SBIC_WAIT(regs, SBIC_ASR_INT | SBIC_ASR_LCI, 0);
+ if (asr & SBIC_ASR_LCI) {
+#ifdef DEBUG
+ if (reselect_debug)
+ printf("sbicselectbus: late LCI asr %02x\n", asr);
+#endif
+ SBIC_TRACE(dev);
+ return 1;
+ }
+ GET_SBIC_csr (regs, csr);
+ CSR_TRACE('s',csr,asr,target);
+ QPRINTF(("%02x ", csr));
+ if( csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY) {
+#ifdef DEBUG
+ if(reselect_debug)
+ printf("sbicselectbus: reselected asr %02x\n", asr);
+#endif
+ /* We need to handle this now so we don't lock up later */
+ sbicnextstate(dev, csr, asr);
+ SBIC_TRACE(dev);
+ return 1;
+ }
+ if( csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN) {
+ panic("sbicselectbus: target issued select!");
+ return 1;
+ }
+ } while (csr != (SBIC_CSR_MIS_2|MESG_OUT_PHASE)
+ && csr != (SBIC_CSR_MIS_2|CMD_PHASE) && csr != SBIC_CSR_SEL_TIMEO);
+
+ /* Enable (or not) reselection */
+ if(!sbic_enable_reselect && dev->nexus_list.tqh_first == NULL)
+ SET_SBIC_rselid (regs, 0);
+ else
+ SET_SBIC_rselid (regs, SBIC_RID_ER);
+
+ if (csr == (SBIC_CSR_MIS_2|CMD_PHASE)) {
+ dev->sc_flags |= SBICF_SELECTED; /* device ignored ATN */
+ GET_SBIC_selid(regs, id);
+ dev->target = id;
+ GET_SBIC_tlun(regs,dev->lun);
+ if( dev->lun & SBIC_TLUN_VALID )
+ dev->lun &= SBIC_TLUN_MASK;
+ else
+ dev->lun = lun;
+ } else if (csr == (SBIC_CSR_MIS_2|MESG_OUT_PHASE)) {
+ /*
+ * Send identify message
+ * (SCSI-2 requires an identify msg (?))
+ */
+ GET_SBIC_selid(regs, id);
+ dev->target = id;
+ GET_SBIC_tlun(regs,dev->lun);
+ if( dev->lun & SBIC_TLUN_VALID )
+ dev->lun &= SBIC_TLUN_MASK;
+ else
+ dev->lun = lun;
+ /*
+ * handle drives that don't want to be asked
+ * whether to go sync at all.
+ */
+ if (sbic_inhibit_sync[id]
+ && dev->sc_sync[id].state == SYNC_START) {
+#ifdef DEBUG
+ if (sync_debug)
+ printf("Forcing target %d asynchronous.\n", id);
+#endif
+ dev->sc_sync[id].offset = 0;
+ dev->sc_sync[id].period = sbic_min_period;
+ dev->sc_sync[id].state = SYNC_DONE;
+ }
+
+
+ if (dev->sc_sync[id].state != SYNC_START){
+ if( dev->sc_xs->flags & SCSI_POLL
+ || (dev->sc_flags & SBICF_ICMD)
+ || !sbic_enable_reselect )
+ SEND_BYTE (regs, MSG_IDENTIFY | lun);
+ else
+ SEND_BYTE (regs, MSG_IDENTIFY_DR | lun);
+ } else {
+ /*
+ * try to initiate a sync transfer.
+ * So compose the sync message we're going
+ * to send to the target
+ */
+
+#ifdef DEBUG
+ if (sync_debug)
+ printf("Sending sync request to target %d ... ",
+ id);
+#endif
+ /*
+ * setup scsi message sync message request
+ */
+ dev->sc_msg[0] = MSG_IDENTIFY | lun;
+ dev->sc_msg[1] = MSG_EXT_MESSAGE;
+ dev->sc_msg[2] = 3;
+ dev->sc_msg[3] = MSG_SYNC_REQ;
+ dev->sc_msg[4] = sbictoscsiperiod(dev, regs,
+ sbic_min_period);
+ dev->sc_msg[5] = sbic_max_offset;
+
+ if (sbicxfstart(regs, 6, MESG_OUT_PHASE, sbic_cmd_wait))
+ sbicxfout(regs, 6, dev->sc_msg, MESG_OUT_PHASE);
+
+ dev->sc_sync[id].state = SYNC_SENT;
+#ifdef DEBUG
+ if (sync_debug)
+ printf ("sent\n");
+#endif
+ }
+
+ asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0);
+ GET_SBIC_csr (regs, csr);
+ CSR_TRACE('y',csr,asr,target);
+ QPRINTF(("[%02x]", csr));
+#ifdef DEBUG
+ if (sync_debug && dev->sc_sync[id].state == SYNC_SENT)
+ printf("csr-result of last msgout: 0x%x\n", csr);
+#endif
+
+ if (csr != SBIC_CSR_SEL_TIMEO)
+ dev->sc_flags |= SBICF_SELECTED;
+ }
+ if (csr == SBIC_CSR_SEL_TIMEO)
+ dev->sc_xs->error = XS_SELTIMEOUT;
+
+ QPRINTF(("\n"));
+
+ SBIC_TRACE(dev);
+ return(csr == SBIC_CSR_SEL_TIMEO);
+}
+
+int
+sbicxfstart(regs, len, phase, wait)
+ sbic_regmap_p regs;
+ int len, wait;
+ u_char phase;
+{
+ u_char id;
+
+ switch (phase) {
+ case DATA_IN_PHASE:
+ case MESG_IN_PHASE:
+ GET_SBIC_selid (regs, id);
+ id |= SBIC_SID_FROM_SCSI;
+ SET_SBIC_selid (regs, id);
+ SBIC_TC_PUT (regs, (unsigned)len);
+ break;
+ case DATA_OUT_PHASE:
+ case MESG_OUT_PHASE:
+ case CMD_PHASE:
+ GET_SBIC_selid (regs, id);
+ id &= ~SBIC_SID_FROM_SCSI;
+ SET_SBIC_selid (regs, id);
+ SBIC_TC_PUT (regs, (unsigned)len);
+ break;
+ default:
+ SBIC_TC_PUT (regs, 0);
+ }
+ QPRINTF(("sbicxfstart %d, %d, %d\n", len, phase, wait));
+
+ return(1);
+}
+
+int
+sbicxfout(regs, len, bp, phase)
+ sbic_regmap_p regs;
+ int len;
+ void *bp;
+ int phase;
+{
+ u_char orig_csr, csr, asr, *buf;
+ int wait;
+
+ buf = bp;
+ wait = sbic_data_wait;
+
+ QPRINTF(("sbicxfout {%d} %02x %02x %02x %02x %02x "
+ "%02x %02x %02x %02x %02x\n", len, buf[0], buf[1], buf[2],
+ buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]));
+
+ GET_SBIC_csr (regs, orig_csr);
+ CSR_TRACE('>',orig_csr,0,0);
+
+ /*
+ * sigh.. WD-PROTO strikes again.. sending the command in one go
+ * causes the chip to lock up if talking to certain (misbehaving?)
+ * targets. Anyway, this procedure should work for all targets, but
+ * it's slightly slower due to the overhead
+ */
+ WAIT_CIP (regs);
+ SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
+ for (;len > 0; len--) {
+ GET_SBIC_asr (regs, asr);
+ while ((asr & SBIC_ASR_DBR) == 0) {
+ if ((asr & SBIC_ASR_INT) || --wait < 0) {
+#ifdef DEBUG
+ if (sbic_debug)
+ printf("sbicxfout fail: l%d i%x w%d\n",
+ len, asr, wait);
+#endif
+ return (len);
+ }
+/* DELAY(1);*/
+ GET_SBIC_asr (regs, asr);
+ }
+
+ SET_SBIC_data (regs, *buf);
+ buf++;
+ }
+ SBIC_TC_GET(regs, len);
+ QPRINTF(("sbicxfout done %d bytes\n", len));
+ /*
+ * this leaves with one csr to be read
+ */
+ return(0);
+}
+
+/* returns # bytes left to read */
+int
+sbicxfin(regs, len, bp)
+ sbic_regmap_p regs;
+ int len;
+ void *bp;
+{
+ int wait, read;
+ u_char *obp, *buf;
+ u_char orig_csr, csr, asr;
+
+ wait = sbic_data_wait;
+ obp = bp;
+ buf = bp;
+
+ GET_SBIC_csr (regs, orig_csr);
+ CSR_TRACE('<',orig_csr,0,0);
+
+ QPRINTF(("sbicxfin %d, csr=%02x\n", len, orig_csr));
+
+ WAIT_CIP (regs);
+ SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
+ for (;len > 0; len--) {
+ GET_SBIC_asr (regs, asr);
+ if((asr & SBIC_ASR_PE)) {
+#ifdef DEBUG
+ printf("sbicxfin parity error: l%d i%x w%d\n",
+ len, asr, wait);
+/* return ((unsigned long)buf - (unsigned long)bp); */
+#ifdef DDB
+ Debugger();
+#endif
+#endif
+ }
+ while ((asr & SBIC_ASR_DBR) == 0) {
+ if ((asr & SBIC_ASR_INT) || --wait < 0) {
+#ifdef DEBUG
+ if (sbic_debug) {
+ QPRINTF(("sbicxfin fail:{%d} %02x %02x %02x %02x %02x %02x "
+ "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
+ obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
+ printf("sbicxfin fail: l%d i%x w%d\n",
+ len, asr, wait);
+}
+#endif
+ return len;
+ }
+
+ if( ! asr & SBIC_ASR_BSY ) {
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('<',csr,asr,len);
+ QPRINTF(("[CSR%02xASR%02x]", csr, asr));
+ }
+
+/* DELAY(1);*/
+ GET_SBIC_asr (regs, asr);
+ }
+
+ GET_SBIC_data (regs, *buf);
+/* QPRINTF(("asr=%02x, csr=%02x, data=%02x\n", asr, csr, *buf));*/
+ buf++;
+ }
+
+ QPRINTF(("sbicxfin {%d} %02x %02x %02x %02x %02x %02x "
+ "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
+ obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
+
+ /* this leaves with one csr to be read */
+ return len;
+}
+
+/*
+ * SCSI 'immediate' command: issue a command to some SCSI device
+ * and get back an 'immediate' response (i.e., do programmed xfer
+ * to get the response data). 'cbuf' is a buffer containing a scsi
+ * command of length clen bytes. 'buf' is a buffer of length 'len'
+ * bytes for data. The transfer direction is determined by the device
+ * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the
+ * command must supply no data.
+ */
+int
+sbicicmd(dev, target, lun, cbuf, clen, buf, len)
+ struct sbic_softc *dev;
+ void *cbuf, *buf;
+ int clen, len;
+{
+ sbic_regmap_p regs;
+ u_char phase, csr, asr;
+ int wait, newtarget, cmd_sent, parity_err;
+ struct sbic_acb *acb;
+
+ int discon;
+ int i;
+
+#define CSR_LOG_BUF_SIZE 0
+#if CSR_LOG_BUF_SIZE
+ int bufptr;
+ int csrbuf[CSR_LOG_BUF_SIZE];
+ bufptr=0;
+#endif
+
+ SBIC_TRACE(dev);
+ regs = dev->sc_sbicp;
+ acb = dev->sc_nexus;
+
+ /* Make sure pointers are OK */
+ dev->sc_last = dev->sc_cur = &acb->sc_pa;
+ dev->sc_tcnt = acb->sc_tcnt = 0;
+ acb->sc_pa.dc_count = 0; /* No DMA */
+ acb->sc_kv.dc_addr = buf;
+ acb->sc_kv.dc_count = len;
+
+#ifdef DEBUG
+ routine = 3;
+ debug_sbic_regs = regs; /* store this to allow debug calls */
+ if( data_pointer_debug > 1 )
+ printf("sbicicmd(%d,%d):%d\n", target, lun,
+ acb->sc_kv.dc_count);
+#endif
+
+ /*
+ * set the sbic into non-DMA mode
+ */
+ SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /*| SBIC_CTL_HSP*/);
+
+ dev->sc_stat[0] = 0xff;
+ dev->sc_msg[0] = 0xff;
+ i = 1; /* pre-load */
+
+ /* We're stealing the SCSI bus */
+ dev->sc_flags |= SBICF_ICMD;
+
+ do {
+ /*
+ * select the SCSI bus (it's an error if bus isn't free)
+ */
+ if (!( dev->sc_flags & SBICF_SELECTED )
+ && sbicselectbus(dev, regs, target, lun, dev->sc_scsiaddr)) {
+ /*printf("sbicicmd trying to select busy bus!\n");*/
+ dev->sc_flags &= ~SBICF_ICMD;
+ return(-1);
+ }
+
+ /*
+ * Wait for a phase change (or error) then let the device sequence
+ * us through the various SCSI phases.
+ */
+
+ wait = sbic_cmd_wait;
+
+ asr = GET_SBIC_asr (regs, asr);
+ GET_SBIC_csr (regs, csr);
+ CSR_TRACE('I',csr,asr,target);
+ QPRINTF((">ASR:%02xCSR:%02x<", asr, csr));
+
+#if CSR_LOG_BUF_SIZE
+ csrbuf[bufptr++] = csr;
+#endif
+
+
+ switch (csr) {
+ case SBIC_CSR_S_XFERRED:
+ case SBIC_CSR_DISC:
+ case SBIC_CSR_DISC_1:
+ dev->sc_flags &= ~SBICF_SELECTED;
+ GET_SBIC_cmd_phase (regs, phase);
+ if (phase == 0x60) {
+ GET_SBIC_tlun (regs, dev->sc_stat[0]);
+ i = 0; /* done */
+/* break; /* Bypass all the state gobldygook */
+ } else {
+#ifdef DEBUG
+ if(reselect_debug>1)
+ printf("sbicicmd: handling disconnect\n");
+#endif
+ i = SBIC_STATE_DISCONNECT;
+ }
+ break;
+
+ case SBIC_CSR_XFERRED|CMD_PHASE:
+ case SBIC_CSR_MIS|CMD_PHASE:
+ case SBIC_CSR_MIS_1|CMD_PHASE:
+ case SBIC_CSR_MIS_2|CMD_PHASE:
+ if (sbicxfstart(regs, clen, CMD_PHASE, sbic_cmd_wait))
+ if (sbicxfout(regs, clen,
+ cbuf, CMD_PHASE))
+ i = sbicabort(dev, regs,"icmd sending cmd");
+#if 0
+ GET_SBIC_csr(regs, csr); /* Lets us reload tcount */
+ WAIT_CIP(regs);
+ GET_SBIC_asr(regs, asr);
+ CSR_TRACE('I',csr,asr,target);
+ if( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI|SBIC_ASR_CIP) )
+ printf("next: cmd sent asr %02x, csr %02x\n",
+ asr, csr);
+#endif
+ break;
+
+#if 0
+ case SBIC_CSR_XFERRED|DATA_OUT_PHASE:
+ case SBIC_CSR_XFERRED|DATA_IN_PHASE:
+ case SBIC_CSR_MIS|DATA_OUT_PHASE:
+ case SBIC_CSR_MIS|DATA_IN_PHASE:
+ case SBIC_CSR_MIS_1|DATA_OUT_PHASE:
+ case SBIC_CSR_MIS_1|DATA_IN_PHASE:
+ case SBIC_CSR_MIS_2|DATA_OUT_PHASE:
+ case SBIC_CSR_MIS_2|DATA_IN_PHASE:
+ if (acb->sc_kv.dc_count <= 0)
+ i = sbicabort(dev, regs, "icmd out of data");
+ else {
+ wait = sbic_data_wait;
+ if (sbicxfstart(regs,
+ acb->sc_kv.dc_count,
+ SBIC_PHASE(csr), wait))
+ if (csr & 0x01)
+ /* data in? */
+ i=sbicxfin(regs,
+ acb->sc_kv.dc_count,
+ acb->sc_kv.dc_addr);
+ else
+ i=sbicxfout(regs,
+ acb->sc_kv.dc_count,
+ acb->sc_kv.dc_addr,
+ SBIC_PHASE(csr));
+ acb->sc_kv.dc_addr +=
+ (acb->sc_kv.dc_count - i);
+ acb->sc_kv.dc_count = i;
+ i = 1;
+ }
+ break;
+
+#endif
+ case SBIC_CSR_XFERRED|STATUS_PHASE:
+ case SBIC_CSR_MIS|STATUS_PHASE:
+ case SBIC_CSR_MIS_1|STATUS_PHASE:
+ case SBIC_CSR_MIS_2|STATUS_PHASE:
+ /*
+ * the sbic does the status/cmd-complete reading ok,
+ * so do this with its hi-level commands.
+ */
+#ifdef DEBUG
+ if(sbic_debug)
+ printf("SBICICMD status phase\n");
+#endif
+ SBIC_TC_PUT(regs, 0);
+ SET_SBIC_cmd_phase(regs, 0x46);
+ SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
+ break;
+
+#if THIS_IS_A_RESERVED_STATE
+ case BUS_FREE_PHASE: /* This is not legal */
+ if( dev->sc_stat[0] != 0xff )
+ goto out;
+ break;
+#endif
+
+ default:
+ i = sbicnextstate(dev, csr, asr);
+ }
+
+ /*
+ * make sure the last command was taken,
+ * ie. we're not hunting after an ignored command..
+ */
+ GET_SBIC_asr(regs, asr);
+
+ /* tapes may take a loooong time.. */
+ while (asr & SBIC_ASR_BSY){
+ if(asr & SBIC_ASR_DBR) {
+ printf("sbicicmd: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n",
+ csr,asr);
+#ifdef DDB
+ Debugger();
+#endif
+ /* SBIC is jammed */
+ /* DUNNO which direction */
+ /* Try old direction */
+ GET_SBIC_data(regs,i);
+ GET_SBIC_asr(regs, asr);
+ if( asr & SBIC_ASR_DBR) /* Wants us to write */
+ SET_SBIC_data(regs,i);
+ }
+ GET_SBIC_asr(regs, asr);
+ }
+
+ /*
+ * wait for last command to complete
+ */
+ if (asr & SBIC_ASR_LCI) {
+ printf("sbicicmd: last command ignored\n");
+ }
+ else if( i == 1 ) /* Bsy */
+ SBIC_WAIT (regs, SBIC_ASR_INT, wait);
+
+ /*
+ * do it again
+ */
+ } while ( i > 0 && dev->sc_stat[0] == 0xff);
+
+ /* Sometimes we need to do an extra read of the CSR */
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('I',csr,asr,0xff);
+
+#if CSR_LOG_BUF_SIZE
+ if(reselect_debug>1)
+ for(i=0; i<bufptr; i++)
+ printf("CSR:%02x", csrbuf[i]);
+#endif
+
+#ifdef DEBUG
+ if(data_pointer_debug > 1)
+ printf("sbicicmd done(%d,%d):%d =%d=\n",
+ dev->target, lun,
+ acb->sc_kv.dc_count,
+ dev->sc_stat[0]);
+#endif
+
+ QPRINTF(("=STS:%02x=", dev->sc_stat[0]));
+ dev->sc_flags &= ~SBICF_ICMD;
+
+ SBIC_TRACE(dev);
+ return(dev->sc_stat[0]);
+}
+
+/*
+ * Finish SCSI xfer command: After the completion interrupt from
+ * a read/write operation, sequence through the final phases in
+ * programmed i/o. This routine is a lot like sbicicmd except we
+ * skip (and don't allow) the select, cmd out and data in/out phases.
+ */
+void
+sbicxfdone(dev, regs, target)
+ struct sbic_softc *dev;
+ sbic_regmap_p regs;
+ int target;
+{
+ u_char phase, asr, csr;
+ int s;
+
+ SBIC_TRACE(dev);
+ QPRINTF(("{"));
+ s = splbio();
+
+ /*
+ * have the sbic complete on its own
+ */
+ SBIC_TC_PUT(regs, 0);
+ SET_SBIC_cmd_phase(regs, 0x46);
+ SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
+
+ do {
+ asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0);
+ GET_SBIC_csr (regs, csr);
+ CSR_TRACE('f',csr,asr,target);
+ QPRINTF(("%02x:", csr));
+ } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
+ && (csr != SBIC_CSR_S_XFERRED));
+
+ dev->sc_flags &= ~SBICF_SELECTED;
+
+ GET_SBIC_cmd_phase (regs, phase);
+ QPRINTF(("}%02x", phase));
+ if (phase == 0x60)
+ GET_SBIC_tlun(regs, dev->sc_stat[0]);
+ else
+ sbicerror(dev, regs, csr);
+
+ QPRINTF(("=STS:%02x=\n", dev->sc_stat[0]));
+ splx(s);
+ SBIC_TRACE(dev);
+}
+
+ /*
+ * No DMA chains
+ */
+
+int
+sbicgo(dev, xs)
+ struct sbic_softc *dev;
+ struct scsi_xfer *xs;
+{
+ int i, dmaflags, count, wait, usedma;
+ u_char csr, asr, cmd, *addr;
+ sbic_regmap_p regs;
+ struct sbic_acb *acb;
+
+ SBIC_TRACE(dev);
+ dev->target = xs->sc_link->target;
+ dev->lun = xs->sc_link->lun;
+ acb = dev->sc_nexus;
+ regs = dev->sc_sbicp;
+
+ usedma = sbicdmaok(dev, xs);
+#ifdef DEBUG
+ routine = 1;
+ debug_sbic_regs = regs; /* store this to allow debug calls */
+ if( data_pointer_debug > 1 )
+ printf("sbicgo(%d,%d)\n", dev->target, dev->lun);
+#endif
+
+ /*
+ * set the sbic into DMA mode
+ */
+ if( usedma )
+ SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI |
+ SBIC_MACHINE_DMA_MODE);
+ else
+ SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+
+
+ /*
+ * select the SCSI bus (it's an error if bus isn't free)
+ */
+ if (sbicselectbus(dev, regs, dev->target, dev->lun,
+ dev->sc_scsiaddr)) {
+/* printf("sbicgo: Trying to select busy bus!\n"); */
+ SBIC_TRACE(dev);
+ return(0); /* Not done: needs to be rescheduled */
+ }
+ dev->sc_stat[0] = 0xff;
+
+ /*
+ * Calculate DMA chains now
+ */
+
+ dmaflags = 0;
+ if (acb->flags & ACB_DATAIN)
+ dmaflags |= DMAGO_READ;
+
+
+ /*
+ * Deal w/bounce buffers.
+ */
+
+ addr = acb->sc_kv.dc_addr;
+ count = acb->sc_kv.dc_count;
+#if 0 /* mark */
+ if (count && (char *)kvtop(addr) != acb->sc_pa.dc_addr) { /* XXXX check */
+ printf("sbic: DMA buffer mapping changed %x->%x\n",
+ acb->sc_pa.dc_addr, kvtop(addr));
+#ifdef DDB
+ Debugger();
+#endif
+ }
+#endif
+
+#ifdef DEBUG
+ ++sbicdma_ops; /* count total DMA operations */
+#endif
+ if (count && usedma && dev->sc_flags & SBICF_BADDMA &&
+ sbiccheckdmap(addr, count, dev->sc_dmamask)) {
+ /*
+ * need to bounce the dma.
+ */
+ if (dmaflags & DMAGO_READ) {
+ acb->flags |= ACB_BBUF;
+ acb->sc_dmausrbuf = addr;
+ acb->sc_dmausrlen = count;
+ acb->sc_usrbufpa = (u_char *)kvtop(addr);
+ if(!dev->sc_tinfo[dev->target].bounce) {
+ printf("sbicgo: HELP! no bounce allocated for %d\n",
+ dev->target);
+ printf("xfer: (%x->%x,%x)\n", acb->sc_dmausrbuf,
+ acb->sc_usrbufpa, acb->sc_dmausrlen);
+ dev->sc_tinfo[xs->sc_link->target].bounce
+ = (char *)alloc_z2mem(MAXPHYS);
+ if (isztwomem(dev->sc_tinfo[xs->sc_link->target].bounce))
+ printf("alloc ZII target %d bounce pa 0x%x\n",
+ xs->sc_link->target,
+ kvtop(dev->sc_tinfo[xs->sc_link->target].bounce));
+ else if (dev->sc_tinfo[xs->sc_link->target].bounce)
+ printf("alloc CHIP target %d bounce pa 0x%x\n",
+ xs->sc_link->target,
+ PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->target].bounce));
+
+ printf("Allocating %d bounce at %x\n",
+ dev->target,
+ kvtop(dev->sc_tinfo[dev->target].bounce));
+ }
+ } else { /* write: copy to dma buffer */
+#ifdef DEBUG
+ if(data_pointer_debug)
+ printf("sbicgo: copying %x bytes to target %d bounce %x\n",
+ count, dev->target,
+ kvtop(dev->sc_tinfo[dev->target].bounce));
+#endif
+ bcopy (addr, dev->sc_tinfo[dev->target].bounce, count);
+ }
+ addr = dev->sc_tinfo[dev->target].bounce;/* and use dma buffer */
+ acb->sc_kv.dc_addr = addr;
+#ifdef DEBUG
+ ++sbicdma_bounces; /* count number of bounced */
+#endif
+ }
+
+ /*
+ * Allocate the DMA chain
+ */
+
+ /* Set start KVM addresses */
+#if 0
+ acb->sc_kv.dc_addr = addr;
+ acb->sc_kv.dc_count = count;
+#endif
+
+ /* Mark end of segment */
+ acb->sc_tcnt = dev->sc_tcnt = 0;
+ acb->sc_pa.dc_count = 0;
+
+ sbic_load_ptrs(dev, regs, dev->target, dev->lun);
+ SBIC_TRACE(dev);
+ /* Enable interrupts but don't do any DMA */
+ dev->sc_enintr(dev);
+ if (usedma) {
+ dev->sc_tcnt = dev->sc_dmago(dev, acb->sc_pa.dc_addr,
+ acb->sc_pa.dc_count,
+ dmaflags);
+#ifdef DEBUG
+ dev->sc_dmatimo = dev->sc_tcnt ? 1 : 0;
+#endif
+ } else
+ dev->sc_dmacmd = 0; /* Don't use DMA */
+ dev->sc_flags |= SBICF_INDMA;
+/* SBIC_TC_PUT(regs, dev->sc_tcnt); /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+ SBIC_TRACE(dev);
+ sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+
+ /*
+ * push the data cache ( I think this won't work (EH))
+ */
+#if defined(M68040)
+ if (mmutype == MMU_68040 && usedma && count) {
+ dma_cachectl(addr, count);
+ if (((u_int)addr & 0xF) || (((u_int)addr + count) & 0xF))
+ dev->sc_flags |= SBICF_DCFLUSH;
+ }
+#endif
+
+ /*
+ * enintr() also enables interrupts for the sbic
+ */
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("sbicgo dmago:%d(%x:%x)\n",
+ dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
+ debug_asr = asr;
+ debug_csr = csr;
+#endif
+
+ /*
+ * Lets cycle a while then let the interrupt handler take over
+ */
+
+ asr = GET_SBIC_asr(regs, asr);
+ do {
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('g',csr,asr,dev->target);
+#ifdef DEBUG
+ debug_csr = csr;
+ routine = 1;
+#endif
+ QPRINTF(("go[0x%x]", csr));
+
+ i = sbicnextstate(dev, csr, asr);
+
+ WAIT_CIP(regs);
+ GET_SBIC_asr(regs, asr);
+#ifdef DEBUG
+ debug_asr = asr;
+#endif
+ if(asr & SBIC_ASR_LCI) printf("sbicgo: LCI asr:%02x csr:%02x\n",
+ asr,csr);
+ } while( i == SBIC_STATE_RUNNING
+ && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) );
+
+ CSR_TRACE('g',csr,asr,i<<4);
+ SBIC_TRACE(dev);
+if (i == SBIC_STATE_DONE && dev->sc_stat[0] == 0xff) printf("sbicgo: done & stat = 0xff\n");
+ if (i == SBIC_STATE_DONE && dev->sc_stat[0] != 0xff) {
+/* if( i == SBIC_STATE_DONE && dev->sc_stat[0] ) { */
+ /* Did we really finish that fast? */
+ return 1;
+ }
+ return 0;
+}
+
+
+int
+sbicintr(dev)
+ struct sbic_softc *dev;
+{
+ sbic_regmap_p regs;
+ struct dma_chain *df, *dl;
+ u_char asr, csr, *tmpaddr;
+ struct sbic_acb *acb;
+ int i, newtarget, newlun;
+ unsigned tcnt;
+
+ regs = dev->sc_sbicp;
+
+ /*
+ * pending interrupt?
+ */
+ GET_SBIC_asr (regs, asr);
+ if ((asr & SBIC_ASR_INT) == 0)
+ return(0);
+
+ SBIC_TRACE(dev);
+ do {
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('i',csr,asr,dev->target);
+#ifdef DEBUG
+ debug_csr = csr;
+ routine = 2;
+#endif
+ QPRINTF(("intr[0x%x]", csr));
+
+ i = sbicnextstate(dev, csr, asr);
+
+ WAIT_CIP(regs);
+ GET_SBIC_asr(regs, asr);
+#ifdef DEBUG
+ debug_asr = asr;
+#endif
+#if 0
+ if(asr & SBIC_ASR_LCI) printf("sbicintr: LCI asr:%02x csr:%02x\n",
+ asr,csr);
+#endif
+ } while(i == SBIC_STATE_RUNNING &&
+ asr & (SBIC_ASR_INT|SBIC_ASR_LCI));
+ CSR_TRACE('i',csr,asr,i<<4);
+ SBIC_TRACE(dev);
+ return(1);
+}
+
+/*
+ * Run commands and wait for disconnect
+ */
+int
+sbicpoll(dev)
+ struct sbic_softc *dev;
+{
+ sbic_regmap_p regs;
+ u_char asr, csr;
+ struct sbic_pending* pendp;
+ int i;
+ unsigned tcnt;
+
+ SBIC_TRACE(dev);
+ regs = dev->sc_sbicp;
+
+ do {
+ GET_SBIC_asr (regs, asr);
+#ifdef DEBUG
+ debug_asr = asr;
+#endif
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('p',csr,asr,dev->target);
+#ifdef DEBUG
+ debug_csr = csr;
+ routine = 2;
+#endif
+ QPRINTF(("poll[0x%x]", csr));
+
+ i = sbicnextstate(dev, csr, asr);
+
+ WAIT_CIP(regs);
+ GET_SBIC_asr(regs, asr);
+ /* tapes may take a loooong time.. */
+ while (asr & SBIC_ASR_BSY){
+ if(asr & SBIC_ASR_DBR) {
+ printf("sbipoll: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n",
+ csr,asr);
+#ifdef DDB
+ Debugger();
+#endif
+ /* SBIC is jammed */
+ /* DUNNO which direction */
+ /* Try old direction */
+ GET_SBIC_data(regs,i);
+ GET_SBIC_asr(regs, asr);
+ if( asr & SBIC_ASR_DBR) /* Wants us to write */
+ SET_SBIC_data(regs,i);
+ }
+ GET_SBIC_asr(regs, asr);
+ }
+
+ if(asr & SBIC_ASR_LCI) printf("sbicpoll: LCI asr:%02x csr:%02x\n",
+ asr,csr);
+ else if( i == 1 ) /* BSY */
+ SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
+ } while(i == SBIC_STATE_RUNNING);
+ CSR_TRACE('p',csr,asr,i<<4);
+ SBIC_TRACE(dev);
+ return(1);
+}
+
+/*
+ * Handle a single msgin
+ */
+
+int
+sbicmsgin(dev)
+ struct sbic_softc *dev;
+{
+ sbic_regmap_p regs;
+ int recvlen;
+ u_char asr, csr, *tmpaddr;
+
+ regs = dev->sc_sbicp;
+
+ dev->sc_msg[0] = 0xff;
+ dev->sc_msg[1] = 0xff;
+
+ GET_SBIC_asr(regs, asr);
+#ifdef DEBUG
+ if(reselect_debug>1)
+ printf("sbicmsgin asr=%02x\n", asr);
+#endif
+
+ sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+
+ GET_SBIC_selid (regs, csr);
+ SET_SBIC_selid (regs, csr | SBIC_SID_FROM_SCSI);
+
+ SBIC_TC_PUT(regs, 0);
+ tmpaddr = dev->sc_msg;
+ recvlen = 1;
+ do {
+ while( recvlen-- ) {
+ asr = GET_SBIC_asr(regs, asr);
+ GET_SBIC_csr(regs, csr);
+ QPRINTF(("sbicmsgin ready to go (csr,asr)=(%02x,%02x)\n",
+ csr, asr));
+
+ RECV_BYTE(regs, *tmpaddr);
+ CSR_TRACE('m',csr,asr,*tmpaddr);
+#if 1
+ /*
+ * get the command completion interrupt, or we
+ * can't send a new command (LCI)
+ */
+ SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('X',csr,asr,dev->target);
+#else
+ WAIT_CIP(regs);
+ do {
+ GET_SBIC_asr(regs, asr);
+ csr = 0xff;
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('X',csr,asr,dev->target);
+ if( csr == 0xff )
+ printf("sbicmsgin waiting: csr %02x asr %02x\n", csr, asr);
+ } while( csr == 0xff );
+#endif
+#ifdef DEBUG
+ if(reselect_debug>1)
+ printf("sbicmsgin: got %02x csr %02x asr %02x\n",
+ *tmpaddr, csr, asr);
+#endif
+#if do_parity_check
+ if( asr & SBIC_ASR_PE ) {
+ printf ("Parity error");
+ /* This code simply does not work. */
+ WAIT_CIP(regs);
+ SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
+ WAIT_CIP(regs);
+ GET_SBIC_asr(regs, asr);
+ WAIT_CIP(regs);
+ SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+ WAIT_CIP(regs);
+ if( !(asr & SBIC_ASR_LCI) )
+ /* Target wants to send garbled msg*/
+ continue;
+ printf("--fixing\n");
+ /* loop until a msgout phase occurs on target */
+ while(csr & 0x07 != MESG_OUT_PHASE) {
+ while( asr & SBIC_ASR_BSY &&
+ !(asr & SBIC_ASR_DBR|SBIC_ASR_INT) )
+ GET_SBIC_asr(regs, asr);
+ if( asr & SBIC_ASR_DBR )
+ panic("msgin: jammed again!\n");
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('e',csr,asr,dev->target);
+ if( csr & 0x07 != MESG_OUT_PHASE ) {
+ sbicnextstate(dev, csr, asr);
+ sbic_save_ptrs(dev, regs,
+ dev->target,
+ dev->lun);
+ }
+ }
+ /* Should be msg out by now */
+ SEND_BYTE(regs, MSG_PARITY_ERROR);
+ }
+ else
+#endif
+ tmpaddr++;
+
+ if(recvlen) {
+ /* Clear ACK */
+ WAIT_CIP(regs);
+ GET_SBIC_asr(regs, asr);
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('X',csr,asr,dev->target);
+ QPRINTF(("sbicmsgin pre byte CLR_ACK (csr,asr)=(%02x,%02x)\n",
+ csr, asr));
+ SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+ SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+ }
+
+ };
+
+ if(dev->sc_msg[0] == 0xff) {
+ printf("sbicmsgin: sbic swallowed our message\n");
+ break;
+ }
+#ifdef DEBUG
+ if (sync_debug)
+ printf("msgin done csr 0x%x asr 0x%x msg 0x%x\n",
+ csr, asr, dev->sc_msg[0]);
+#endif
+ /*
+ * test whether this is a reply to our sync
+ * request
+ */
+ if (MSG_ISIDENTIFY(dev->sc_msg[0])) {
+ QPRINTF(("IFFY"));
+#if 0
+ /* There is an implied load-ptrs here */
+ sbic_load_ptrs(dev, regs, dev->target, dev->lun);
+#endif
+ /* Got IFFY msg -- ack it */
+ } else if (dev->sc_msg[0] == MSG_REJECT
+ && dev->sc_sync[dev->target].state == SYNC_SENT) {
+ QPRINTF(("REJECT of SYN"));
+#ifdef DEBUG
+ if (sync_debug)
+ printf("target %d rejected sync, going async\n",
+ dev->target);
+#endif
+ dev->sc_sync[dev->target].period = sbic_min_period;
+ dev->sc_sync[dev->target].offset = 0;
+ dev->sc_sync[dev->target].state = SYNC_DONE;
+ SET_SBIC_syn(regs,
+ SBIC_SYN(dev->sc_sync[dev->target].offset,
+ dev->sc_sync[dev->target].period));
+ } else if ((dev->sc_msg[0] == MSG_REJECT)) {
+ QPRINTF(("REJECT"));
+ /*
+ * we'll never REJECt a REJECT message..
+ */
+ } else if ((dev->sc_msg[0] == MSG_SAVE_DATA_PTR)) {
+ QPRINTF(("MSG_SAVE_DATA_PTR"));
+ /*
+ * don't reject this either.
+ */
+ } else if ((dev->sc_msg[0] == MSG_DISCONNECT)) {
+ QPRINTF(("DISCONNECT"));
+#ifdef DEBUG
+ if( reselect_debug>1 && dev->sc_msg[0] == MSG_DISCONNECT )
+ printf("sbicmsgin: got disconnect msg %s\n",
+ (dev->sc_flags & SBICF_ICMD)?"rejecting":"");
+#endif
+ if( dev->sc_flags & SBICF_ICMD ) {
+ /* We're in immediate mode. Prevent disconnects. */
+ /* prepare to reject the message, NACK */
+ SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
+ WAIT_CIP(regs);
+ }
+ } else if (dev->sc_msg[0] == MSG_CMD_COMPLETE ) {
+ QPRINTF(("CMD_COMPLETE"));
+ /* !! KLUDGE ALERT !! quite a few drives don't seem to
+ * really like the current way of sending the
+ * sync-handshake together with the ident-message, and
+ * they react by sending command-complete and
+ * disconnecting right after returning the valid sync
+ * handshake. So, all I can do is reselect the drive,
+ * and hope it won't disconnect again. I don't think
+ * this is valid behavior, but I can't help fixing a
+ * problem that apparently exists.
+ *
+ * Note: we should not get here on `normal' command
+ * completion, as that condition is handled by the
+ * high-level sel&xfer resume command used to walk
+ * thru status/cc-phase.
+ */
+
+#ifdef DEBUG
+ if (sync_debug)
+ printf ("GOT MSG %d! target %d acting weird.."
+ " waiting for disconnect...\n",
+ dev->sc_msg[0], dev->target);
+#endif
+ /* Check to see if sbic is handling this */
+ GET_SBIC_asr(regs, asr);
+ if(asr & SBIC_ASR_BSY)
+ return SBIC_STATE_RUNNING;
+
+ /* Let's try this: Assume it works and set status to 00 */
+ dev->sc_stat[0] = 0;
+ } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE
+ && tmpaddr == &dev->sc_msg[1]) {
+ QPRINTF(("ExtMSG\n"));
+ /* Read in whole extended message */
+ SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+ SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+ GET_SBIC_asr(regs, asr);
+ GET_SBIC_csr(regs, csr);
+ QPRINTF(("CLR ACK asr %02x, csr %02x\n", asr, csr));
+ RECV_BYTE(regs, *tmpaddr);
+ CSR_TRACE('x',csr,asr,*tmpaddr);
+ /* Wait for command completion IRQ */
+ SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+ recvlen = *tmpaddr++;
+ QPRINTF(("Recving ext msg, asr %02x csr %02x len %02x\n",
+ asr, csr, recvlen));
+ } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE && dev->sc_msg[1] == 3
+ && dev->sc_msg[2] == MSG_SYNC_REQ) {
+ QPRINTF(("SYN"));
+ dev->sc_sync[dev->target].period =
+ sbicfromscsiperiod(dev,
+ regs, dev->sc_msg[3]);
+ dev->sc_sync[dev->target].offset = dev->sc_msg[4];
+ dev->sc_sync[dev->target].state = SYNC_DONE;
+ SET_SBIC_syn(regs,
+ SBIC_SYN(dev->sc_sync[dev->target].offset,
+ dev->sc_sync[dev->target].period));
+ printf("%s: target %d now synchronous,"
+ " period=%dns, offset=%d.\n",
+ dev->sc_dev.dv_xname, dev->target,
+ dev->sc_msg[3] * 4, dev->sc_msg[4]);
+ } else {
+#ifdef DEBUG
+ if (sbic_debug || sync_debug)
+ printf ("sbicmsgin: Rejecting message 0x%02x\n",
+ dev->sc_msg[0]);
+#endif
+ /* prepare to reject the message, NACK */
+ SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
+ WAIT_CIP(regs);
+ }
+ /* Clear ACK */
+ WAIT_CIP(regs);
+ GET_SBIC_asr(regs, asr);
+ GET_SBIC_csr(regs, csr);
+ CSR_TRACE('X',csr,asr,dev->target);
+ QPRINTF(("sbicmsgin pre CLR_ACK (csr,asr)=(%02x,%02x)%d\n",
+ csr, asr, recvlen));
+ SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+ SBIC_WAIT(regs, SBIC_ASR_INT, 0);
+ }
+#if 0
+ while((csr == SBIC_CSR_MSGIN_W_ACK)
+ || (SBIC_PHASE(csr) == MESG_IN_PHASE));
+#else
+ while (recvlen>0);
+#endif
+
+ QPRINTF(("sbicmsgin finished: csr %02x, asr %02x\n",csr, asr));
+
+ /* Should still have one CSR to read */
+ return SBIC_STATE_RUNNING;
+}
+
+
+/*
+ * sbicnextstate()
+ * return:
+ * 0 == done
+ * 1 == working
+ * 2 == disconnected
+ * -1 == error
+ */
+int
+sbicnextstate(dev, csr, asr)
+ struct sbic_softc *dev;
+ u_char csr, asr;
+{
+ sbic_regmap_p regs;
+ struct dma_chain *df, *dl;
+ struct sbic_acb *acb;
+ int i, newtarget, newlun, wait;
+ unsigned tcnt;
+
+ SBIC_TRACE(dev);
+ regs = dev->sc_sbicp;
+ acb = dev->sc_nexus;
+
+ QPRINTF(("next[%02x,%02x]",asr,csr));
+
+ switch (csr) {
+ case SBIC_CSR_XFERRED|CMD_PHASE:
+ case SBIC_CSR_MIS|CMD_PHASE:
+ case SBIC_CSR_MIS_1|CMD_PHASE:
+ case SBIC_CSR_MIS_2|CMD_PHASE:
+ sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+ if (sbicxfstart(regs, acb->clen, CMD_PHASE, sbic_cmd_wait))
+ if (sbicxfout(regs, acb->clen,
+ &acb->cmd, CMD_PHASE))
+ goto abort;
+ break;
+
+ case SBIC_CSR_XFERRED|STATUS_PHASE:
+ case SBIC_CSR_MIS|STATUS_PHASE:
+ case SBIC_CSR_MIS_1|STATUS_PHASE:
+ case SBIC_CSR_MIS_2|STATUS_PHASE:
+ /*
+ * this should be the normal i/o completion case.
+ * get the status & cmd complete msg then let the
+ * device driver look at what happened.
+ */
+ sbicxfdone(dev,regs,dev->target);
+ /*
+ * check for overlapping cache line, flush if so
+ */
+#ifdef M68040
+ if (dev->sc_flags & SBICF_DCFLUSH) {
+#if 0
+ printf("sbic: 68040 DMA cache flush needs fixing? %x:%x\n",
+ dev->sc_xs->data, dev->sc_xs->datalen);
+#endif
+ }
+#endif
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("next dmastop: %d(%x:%x)\n",
+ dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
+ dev->sc_dmatimo = 0;
+#endif
+ dev->sc_dmastop(dev); /* was dmafree */
+ if (acb->flags & ACB_BBUF) {
+ if ((u_char *)kvtop(acb->sc_dmausrbuf) != acb->sc_usrbufpa)
+ printf("%s: WARNING - buffer mapping changed %x->%x\n",
+ dev->sc_dev.dv_xname, acb->sc_usrbufpa,
+ kvtop(acb->sc_dmausrbuf));
+#ifdef DEBUG
+ if(data_pointer_debug)
+ printf("sbicgo:copying %x bytes from target %d bounce %x\n",
+ acb->sc_dmausrlen,
+ dev->target,
+ kvtop(dev->sc_tinfo[dev->target].bounce));
+#endif
+ bcopy(dev->sc_tinfo[dev->target].bounce,
+ acb->sc_dmausrbuf,
+ acb->sc_dmausrlen);
+ }
+ dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH);
+ sbic_scsidone(acb, dev->sc_stat[0]);
+ SBIC_TRACE(dev);
+ return SBIC_STATE_DONE;
+
+ case SBIC_CSR_XFERRED|DATA_OUT_PHASE:
+ case SBIC_CSR_XFERRED|DATA_IN_PHASE:
+ case SBIC_CSR_MIS|DATA_OUT_PHASE:
+ case SBIC_CSR_MIS|DATA_IN_PHASE:
+ case SBIC_CSR_MIS_1|DATA_OUT_PHASE:
+ case SBIC_CSR_MIS_1|DATA_IN_PHASE:
+ case SBIC_CSR_MIS_2|DATA_OUT_PHASE:
+ case SBIC_CSR_MIS_2|DATA_IN_PHASE:
+ if( dev->sc_xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD
+ || acb->sc_dmacmd == 0 ) {
+ /* Do PIO */
+ SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+ if (acb->sc_kv.dc_count <= 0) {
+ printf("sbicnextstate:xfer count %d asr%x csr%x\n",
+ acb->sc_kv.dc_count, asr, csr);
+ goto abort;
+ }
+ wait = sbic_data_wait;
+ if( sbicxfstart(regs,
+ acb->sc_kv.dc_count,
+ SBIC_PHASE(csr), wait))
+ if( SBIC_PHASE(csr) == DATA_IN_PHASE )
+ /* data in? */
+ i=sbicxfin(regs,
+ acb->sc_kv.dc_count,
+ acb->sc_kv.dc_addr);
+ else
+ i=sbicxfout(regs,
+ acb->sc_kv.dc_count,
+ acb->sc_kv.dc_addr,
+ SBIC_PHASE(csr));
+ acb->sc_kv.dc_addr +=
+ (acb->sc_kv.dc_count - i);
+ acb->sc_kv.dc_count = i;
+ } else {
+ if (acb->sc_kv.dc_count <= 0) {
+ printf("sbicnextstate:xfer count %d asr%x csr%x\n",
+ acb->sc_kv.dc_count, asr, csr);
+ goto abort;
+ }
+ /*
+ * do scatter-gather dma
+ * hacking the controller chip, ouch..
+ */
+ SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI |
+ SBIC_MACHINE_DMA_MODE);
+ /*
+ * set next dma addr and dec count
+ */
+#if 0
+ SBIC_TC_GET(regs, tcnt);
+ dev->sc_cur->dc_count -= ((dev->sc_tcnt - tcnt) >> 1);
+ dev->sc_cur->dc_addr += (dev->sc_tcnt - tcnt);
+ dev->sc_tcnt = acb->sc_tcnt = tcnt;
+#else
+ sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+ sbic_load_ptrs(dev, regs, dev->target, dev->lun);
+#endif
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("next dmanext: %d(%x:%x)\n",
+ dev->target,dev->sc_cur->dc_addr,
+ dev->sc_tcnt);
+ dev->sc_dmatimo = 1;
+#endif
+ dev->sc_tcnt = dev->sc_dmanext(dev);
+ SBIC_TC_PUT(regs, (unsigned)dev->sc_tcnt);
+ SET_SBIC_cmd(regs, SBIC_CMD_XFER_INFO);
+ dev->sc_flags |= SBICF_INDMA;
+ }
+ break;
+
+ case SBIC_CSR_XFERRED|MESG_IN_PHASE:
+ case SBIC_CSR_MIS|MESG_IN_PHASE:
+ case SBIC_CSR_MIS_1|MESG_IN_PHASE:
+ case SBIC_CSR_MIS_2|MESG_IN_PHASE:
+ SBIC_TRACE(dev);
+ return sbicmsgin(dev);
+
+ case SBIC_CSR_MSGIN_W_ACK:
+ SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); /* Dunno what I'm ACKing */
+ printf("Acking unknown msgin CSR:%02x",csr);
+ break;
+
+ case SBIC_CSR_XFERRED|MESG_OUT_PHASE:
+ case SBIC_CSR_MIS|MESG_OUT_PHASE:
+ case SBIC_CSR_MIS_1|MESG_OUT_PHASE:
+ case SBIC_CSR_MIS_2|MESG_OUT_PHASE:
+#ifdef DEBUG
+ if (sync_debug)
+ printf ("sending REJECT msg to last msg.\n");
+#endif
+
+ sbic_save_ptrs(dev, regs, dev->target, dev->lun);
+ /*
+ * should only get here on reject,
+ * since it's always US that
+ * initiate a sync transfer
+ */
+ SEND_BYTE(regs, MSG_REJECT);
+ WAIT_CIP(regs);
+ if( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI|SBIC_ASR_CIP) )
+ printf("next: REJECT sent asr %02x\n", asr);
+ SBIC_TRACE(dev);
+ return SBIC_STATE_RUNNING;
+
+ case SBIC_CSR_DISC:
+ case SBIC_CSR_DISC_1:
+ dev->sc_flags &= ~(SBICF_INDMA|SBICF_SELECTED);
+
+ /* Try to schedule another target */
+#ifdef DEBUG
+ if(reselect_debug>1)
+ printf("sbicnext target %d disconnected\n", dev->target);
+#endif
+ TAILQ_INSERT_HEAD(&dev->nexus_list, acb, chain);
+ ++dev->sc_tinfo[dev->target].dconns;
+ dev->sc_nexus = NULL;
+ dev->sc_xs = NULL;
+
+ if( acb->xs->flags & SCSI_POLL
+ || (dev->sc_flags & SBICF_ICMD)
+ || !sbic_parallel_operations ) {
+ SBIC_TRACE(dev);
+ return SBIC_STATE_DISCONNECT;
+ }
+ sbic_sched(dev);
+ SBIC_TRACE(dev);
+ return SBIC_STATE_DISCONNECT;
+
+ case SBIC_CSR_RSLT_NI:
+ case SBIC_CSR_RSLT_IFY:
+ GET_SBIC_rselid(regs, newtarget);
+ /* check SBIC_RID_SIV? */
+ newtarget &= SBIC_RID_MASK;
+ if (csr == SBIC_CSR_RSLT_IFY) {
+ /* Read IFY msg to avoid lockup */
+ GET_SBIC_data(regs, newlun);
+ WAIT_CIP(regs);
+ newlun &= SBIC_TLUN_MASK;
+ CSR_TRACE('r',csr,asr,newtarget);
+ } else {
+ /* Need to get IFY message */
+ for (newlun = 256; newlun; --newlun) {
+ GET_SBIC_asr(regs, asr);
+ if (asr & SBIC_ASR_INT)
+ break;
+ delay(1);
+ }
+ newlun = 0; /* XXXX */
+ if ((asr & SBIC_ASR_INT) == 0) {
+#ifdef DEBUG
+ if (reselect_debug)
+ printf("RSLT_NI - no IFFY message? asr %x\n", asr);
+#endif
+ } else {
+ GET_SBIC_csr(regs,csr);
+ CSR_TRACE('n',csr,asr,newtarget);
+ if (csr == SBIC_CSR_MIS|MESG_IN_PHASE ||
+ csr == SBIC_CSR_MIS_1|MESG_IN_PHASE ||
+ csr == SBIC_CSR_MIS_2|MESG_IN_PHASE) {
+ sbicmsgin(dev);
+ newlun = dev->sc_msg[0] & 7;
+ } else {
+ printf("RSLT_NI - not MESG_IN_PHASE %x\n",
+ csr);
+ }
+ }
+ }
+#ifdef DEBUG
+ if(reselect_debug>1 || (reselect_debug && csr==SBIC_CSR_RSLT_NI))
+ printf("sbicnext: reselect %s from targ %d lun %d\n",
+ csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY",
+ newtarget, newlun);
+#endif
+ if (dev->sc_nexus) {
+#ifdef DEBUG
+ if (reselect_debug > 1)
+ printf("%s: reselect %s with active command\n",
+ dev->sc_dev.dv_xname,
+ csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY");
+#ifdef DDB
+/* Debugger();*/
+#endif
+#endif
+ TAILQ_INSERT_HEAD(&dev->ready_list, dev->sc_nexus, chain);
+ dev->sc_tinfo[dev->target].lubusy &= ~(1 << dev->lun);
+ dev->sc_nexus = NULL;
+ dev->sc_xs = NULL;
+ }
+ /* Reload sync values for this target */
+ if (dev->sc_sync[newtarget].state == SYNC_DONE)
+ SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[newtarget].offset,
+ dev->sc_sync[newtarget].period));
+ else
+ SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
+ for (acb = dev->nexus_list.tqh_first; acb;
+ acb = acb->chain.tqe_next) {
+ if (acb->xs->sc_link->target != newtarget ||
+ acb->xs->sc_link->lun != newlun)
+ continue;
+ TAILQ_REMOVE(&dev->nexus_list, acb, chain);
+ dev->sc_nexus = acb;
+ dev->sc_xs = acb->xs;
+ dev->sc_flags |= SBICF_SELECTED;
+ dev->target = newtarget;
+ dev->lun = newlun;
+ break;
+ }
+ if (acb == NULL) {
+ printf("%s: reselect %s targ %d not in nexus_list %x\n",
+ dev->sc_dev.dv_xname,
+ csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget,
+ &dev->nexus_list.tqh_first);
+ panic("bad reselect in sbic");
+ }
+ if (csr == SBIC_CSR_RSLT_IFY)
+ SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
+ break;
+
+ default:
+ abort:
+ /*
+ * Something unexpected happened -- deal with it.
+ */
+ printf("sbicnextstate: aborting csr %02x asr %02x\n", csr, asr);
+#ifdef DDB
+ Debugger();
+#endif
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("next dmastop: %d(%x:%x)\n",
+ dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
+ dev->sc_dmatimo = 0;
+#endif
+ dev->sc_dmastop(dev);
+ SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
+ sbicerror(dev, regs, csr);
+ sbicabort(dev, regs, "next");
+ if (dev->sc_flags & SBICF_INDMA) {
+ /*
+ * check for overlapping cache line, flush if so
+ */
+#ifdef M68040
+ if (dev->sc_flags & SBICF_DCFLUSH) {
+#if 0
+ printf("sibc: 68040 DMA cache flush needs fixing? %x:%x\n",
+ dev->sc_xs->data, dev->sc_xs->datalen);
+#endif
+ }
+#endif
+ dev->sc_flags &=
+ ~(SBICF_INDMA | SBICF_DCFLUSH);
+#ifdef DEBUG
+ if( data_pointer_debug > 1 )
+ printf("next dmastop: %d(%x:%x)\n",
+ dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt);
+ dev->sc_dmatimo = 0;
+#endif
+ dev->sc_dmastop(dev);
+ sbic_scsidone(acb, -1);
+ }
+ SBIC_TRACE(dev);
+ return SBIC_STATE_ERROR;
+ }
+
+ SBIC_TRACE(dev);
+ return(SBIC_STATE_RUNNING);
+}
+
+
+/*
+ * Check if DMA can not be used with specified buffer
+ */
+
+int
+sbiccheckdmap(bp, len, mask)
+ void *bp;
+ u_long len, mask;
+{
+ u_char *buffer;
+ u_long phy_buf;
+ u_long phy_len;
+
+ buffer = bp;
+
+ if (len == 0)
+ return(0);
+
+ while (len) {
+ phy_buf = kvtop(buffer);
+ if (len < (phy_len = NBPG - ((int) buffer & PGOFSET)))
+ phy_len = len;
+ if (phy_buf & mask)
+ return(1);
+ buffer += phy_len;
+ len -= phy_len;
+ }
+ return(0);
+}
+
+int
+sbictoscsiperiod(dev, regs, a)
+ struct sbic_softc *dev;
+ sbic_regmap_p regs;
+ int a;
+{
+ unsigned int fs;
+
+ /*
+ * cycle = DIV / (2*CLK)
+ * DIV = FS+2
+ * best we can do is 200ns at 20Mhz, 2 cycles
+ */
+
+ GET_SBIC_myid(regs,fs);
+ fs = (fs >>6) + 2; /* DIV */
+ fs = (fs * 10000) / (dev->sc_clkfreq<<1); /* Cycle, in ns */
+ if (a < 2) a = 8; /* map to Cycles */
+ return ((fs*a)>>2); /* in 4 ns units */
+}
+
+int
+sbicfromscsiperiod(dev, regs, p)
+ struct sbic_softc *dev;
+ sbic_regmap_p regs;
+ int p;
+{
+ register unsigned int fs, ret;
+
+ /* Just the inverse of the above */
+
+ GET_SBIC_myid(regs,fs);
+ fs = (fs >>6) + 2; /* DIV */
+ fs = (fs * 10000) / (dev->sc_clkfreq<<1); /* Cycle, in ns */
+
+ ret = p << 2; /* in ns units */
+ ret = ret / fs; /* in Cycles */
+ if (ret < sbic_min_period)
+ return(sbic_min_period);
+
+ /* verify rounding */
+ if (sbictoscsiperiod(dev, regs, ret) < p)
+ ret++;
+ return (ret >= 8) ? 0 : ret;
+}
+
+#ifdef DEBUG
+
+void sbicdumpstate()
+{
+ u_char csr, asr;
+
+ GET_SBIC_asr(debug_sbic_regs,asr);
+ GET_SBIC_csr(debug_sbic_regs,csr);
+ printf("%s: asr:csr(%02x:%02x)->(%02x:%02x)\n",
+ (routine==1)?"sbicgo":
+ (routine==2)?"sbicintr":
+ (routine==3)?"sbicicmd":
+ (routine==4)?"sbicnext":"unknown",
+ debug_asr, debug_csr, asr, csr);
+
+}
+
+void sbictimeout(dev)
+ struct sbic_softc *dev;
+{
+ int s, asr;
+
+ s = splbio();
+ if (dev->sc_dmatimo) {
+ if (dev->sc_dmatimo > 1) {
+ printf("%s: dma timeout #%d\n",
+ dev->sc_dev.dv_xname, dev->sc_dmatimo - 1);
+ GET_SBIC_asr(dev->sc_sbicp, asr);
+ if( asr & SBIC_ASR_INT ) {
+ /* We need to service a missed IRQ */
+ printf("Servicing a missed int:(%02x,%02x)->(%02x,??)\n",
+ debug_asr, debug_csr, asr);
+ sbicintr(dev);
+ }
+ sbicdumpstate();
+ }
+ dev->sc_dmatimo++;
+ }
+ splx(s);
+ timeout((void *)sbictimeout, dev, 30 * hz);
+}
+
+void
+sbic_dump_acb(acb)
+ struct sbic_acb *acb;
+{
+ u_char *b = (u_char *) &acb->cmd;
+ int i;
+
+ printf("acb@%x ", acb);
+ if (acb->xs == NULL) {
+ printf("<unused>\n");
+ return;
+ }
+ printf("(%d:%d) flags %2x clen %2d cmd ", acb->xs->sc_link->target,
+ acb->xs->sc_link->lun, acb->flags, acb->clen);
+ for (i = acb->clen; i; --i)
+ printf(" %02x", *b++);
+ printf("\n");
+ printf(" xs: %08x data %8x:%04x ", acb->xs, acb->xs->data,
+ acb->xs->datalen);
+ printf("va %8x:%04x ", acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
+ printf("pa %8x:%04x tcnt %x\n", acb->sc_pa.dc_addr, acb->sc_pa.dc_count,
+ acb->sc_tcnt);
+}
+
+void
+sbic_dump(dev)
+ struct sbic_softc *dev;
+{
+ sbic_regmap_p regs;
+ u_char csr, asr;
+ struct sbic_acb *acb;
+ int s;
+ int i;
+
+ s = splbio();
+ regs = dev->sc_sbicp;
+#if CSR_TRACE_SIZE
+ printf("csr trace: ");
+ i = csr_traceptr;
+ do {
+ printf("%c%02x%02x%02x ", csr_trace[i].whr,
+ csr_trace[i].csr, csr_trace[i].asr, csr_trace[i].xtn);
+ switch(csr_trace[i].whr) {
+ case 'g':
+ printf("go "); break;
+ case 's':
+ printf("select "); break;
+ case 'y':
+ printf("select+ "); break;
+ case 'i':
+ printf("intr "); break;
+ case 'f':
+ printf("finish "); break;
+ case '>':
+ printf("out "); break;
+ case '<':
+ printf("in "); break;
+ case 'm':
+ printf("msgin "); break;
+ case 'x':
+ printf("msginx "); break;
+ case 'X':
+ printf("msginX "); break;
+ case 'r':
+ printf("reselect "); break;
+ case 'I':
+ printf("icmd "); break;
+ case 'a':
+ printf("abort "); break;
+ default:
+ printf("? ");
+ }
+ switch(csr_trace[i].csr) {
+ case 0x11:
+ printf("INITIATOR"); break;
+ case 0x16:
+ printf("S_XFERRED"); break;
+ case 0x20:
+ printf("MSGIN_ACK"); break;
+ case 0x41:
+ printf("DISC"); break;
+ case 0x42:
+ printf("SEL_TIMEO"); break;
+ case 0x80:
+ printf("RSLT_NI"); break;
+ case 0x81:
+ printf("RSLT_IFY"); break;
+ case 0x85:
+ printf("DISC_1"); break;
+ case 0x18: case 0x19: case 0x1a:
+ case 0x1b: case 0x1e: case 0x1f:
+ case 0x28: case 0x29: case 0x2a:
+ case 0x2b: case 0x2e: case 0x2f:
+ case 0x48: case 0x49: case 0x4a:
+ case 0x4b: case 0x4e: case 0x4f:
+ case 0x88: case 0x89: case 0x8a:
+ case 0x8b: case 0x8e: case 0x8f:
+ switch(csr_trace[i].csr & 0xf0) {
+ case 0x10:
+ printf("DONE_"); break;
+ case 0x20:
+ printf("STOP_"); break;
+ case 0x40:
+ printf("ERR_"); break;
+ case 0x80:
+ printf("REQ_"); break;
+ }
+ switch(csr_trace[i].csr & 7) {
+ case 0:
+ printf("DATA_OUT"); break;
+ case 1:
+ printf("DATA_IN"); break;
+ case 2:
+ printf("CMD"); break;
+ case 3:
+ printf("STATUS"); break;
+ case 6:
+ printf("MSG_OUT"); break;
+ case 7:
+ printf("MSG_IN"); break;
+ default:
+ printf("invld phs");
+ }
+ break;
+ default: printf("****"); break;
+ }
+ if (csr_trace[i].asr & SBIC_ASR_INT)
+ printf(" ASR_INT");
+ if (csr_trace[i].asr & SBIC_ASR_LCI)
+ printf(" ASR_LCI");
+ if (csr_trace[i].asr & SBIC_ASR_BSY)
+ printf(" ASR_BSY");
+ if (csr_trace[i].asr & SBIC_ASR_CIP)
+ printf(" ASR_CIP");
+ printf("\n");
+ i = (i + 1) & (CSR_TRACE_SIZE - 1);
+ } while (i != csr_traceptr);
+#endif
+ GET_SBIC_asr(regs, asr);
+ if ((asr & SBIC_ASR_INT) == 0)
+ GET_SBIC_csr(regs, csr);
+ else
+ csr = 0;
+ printf("%s@%x regs %x asr %x csr %x\n", dev->sc_dev.dv_xname,
+ dev, regs, asr, csr);
+ if (acb = dev->free_list.tqh_first) {
+ printf("Free list:\n");
+ while (acb) {
+ sbic_dump_acb(acb);
+ acb = acb->chain.tqe_next;
+ }
+ }
+ if (acb = dev->ready_list.tqh_first) {
+ printf("Ready list:\n");
+ while (acb) {
+ sbic_dump_acb(acb);
+ acb = acb->chain.tqe_next;
+ }
+ }
+ if (acb = dev->nexus_list.tqh_first) {
+ printf("Nexus list:\n");
+ while (acb) {
+ sbic_dump_acb(acb);
+ acb = acb->chain.tqe_next;
+ }
+ }
+ if (dev->sc_nexus) {
+ printf("nexus:\n");
+ sbic_dump_acb(dev->sc_nexus);
+ }
+ printf("sc_xs %x targ %d lun %d flags %x tcnt %x dmacmd %x mask %x\n",
+ dev->sc_xs, dev->target, dev->lun, dev->sc_flags, dev->sc_tcnt,
+ dev->sc_dmacmd, dev->sc_dmamask);
+ for (i = 0; i < 8; ++i) {
+ if (dev->sc_tinfo[i].cmds > 2) {
+ printf("tgt %d: cmds %d disc %d senses %d lubusy %x\n",
+ i, dev->sc_tinfo[i].cmds,
+ dev->sc_tinfo[i].dconns,
+ dev->sc_tinfo[i].senses,
+ dev->sc_tinfo[i].lubusy);
+ }
+ }
+ splx(s);
+}
+
+#endif
--- /dev/null
+/* $NetBSD: sbicreg.h,v 1.1 1996/03/06 23:44:09 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)scsireg.h 7.3 (Berkeley) 2/5/91
+ */
+
+/*
+ * AMD AM33C93A SCSI interface hardware description.
+ *
+ * Using parts of the Mach scsi driver for the 33C93
+ */
+
+#define SBIC_myid 0
+#define SBIC_cdbsize 0
+#define SBIC_control 1
+#define SBIC_timeo 2
+#define SBIC_cdb1 3
+#define SBIC_tsecs 3
+#define SBIC_cdb2 4
+#define SBIC_theads 4
+#define SBIC_cdb3 5
+#define SBIC_tcyl_hi 5
+#define SBIC_cdb4 6
+#define SBIC_tcyl_lo 6
+#define SBIC_cdb5 7
+#define SBIC_addr_hi 7
+#define SBIC_cdb6 8
+#define SBIC_addr_2 8
+#define SBIC_cdb7 9
+#define SBIC_addr_3 9
+#define SBIC_cdb8 10
+#define SBIC_addr_lo 10
+#define SBIC_cdb9 11
+#define SBIC_secno 11
+#define SBIC_cdb10 12
+#define SBIC_headno 12
+#define SBIC_cdb11 13
+#define SBIC_cylno_hi 13
+#define SBIC_cdb12 14
+#define SBIC_cylno_lo 14
+#define SBIC_tlun 15
+#define SBIC_cmd_phase 16
+#define SBIC_syn 17
+#define SBIC_count_hi 18
+#define SBIC_count_med 19
+#define SBIC_count_lo 20
+#define SBIC_selid 21
+#define SBIC_rselid 22
+#define SBIC_csr 23
+#define SBIC_cmd 24
+#define SBIC_data 25
+/* sbic_asr is addressed directly */
+
+/*
+ * Register defines
+ */
+
+/*
+ * Auxiliary Status Register
+ */
+
+#define SBIC_ASR_INT 0x80 /* Interrupt pending */
+#define SBIC_ASR_LCI 0x40 /* Last command ignored */
+#define SBIC_ASR_BSY 0x20 /* Busy, only cmd/data/asr readable */
+#define SBIC_ASR_CIP 0x10 /* Busy, cmd unavail also */
+#define SBIC_ASR_xxx 0x0c
+#define SBIC_ASR_PE 0x02 /* Parity error (even) */
+#define SBIC_ASR_DBR 0x01 /* Data Buffer Ready */
+
+/*
+ * My ID register, and/or CDB Size
+ */
+
+#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */
+ /* 11 Mhz is invalid */
+#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */
+#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */
+#define SBIC_ID_EHP 0x10 /* Enable host parity */
+#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */
+#define SBIC_ID_MASK 0x07
+#define SBIC_ID_CBDSIZE_MASK 0x0f /* if unk SCSI cmd group */
+
+/*
+ * Control register
+ */
+
+#define SBIC_CTL_DMA 0x80 /* Single byte dma */
+#define SBIC_CTL_DBA_DMA 0x40 /* direct buffer acces (bus master)*/
+#define SBIC_CTL_BURST_DMA 0x20 /* continuous mode (8237) */
+#define SBIC_CTL_NO_DMA 0x00 /* Programmed I/O */
+#define SBIC_CTL_HHP 0x10 /* Halt on host parity error */
+#define SBIC_CTL_EDI 0x08 /* Ending disconnect interrupt */
+#define SBIC_CTL_IDI 0x04 /* Intermediate disconnect interrupt*/
+#define SBIC_CTL_HA 0x02 /* Halt on ATN */
+#define SBIC_CTL_HSP 0x01 /* Halt on SCSI parity error */
+
+/*
+ * Timeout period register
+ * [val in msecs, input clk in 0.1 Mhz]
+ */
+
+#define SBIC_TIMEOUT(val,clk) ((((val) * (clk)) / 800) + 1)
+
+/*
+ * CDBn registers, note that
+ * cdb11 is used for status byte in target mode (send-status-and-cc)
+ * cdb12 sez if linked command complete, and w/flag if so
+ */
+
+/*
+ * Target LUN register
+ * [holds target status when select-and-xfer]
+ */
+
+#define SBIC_TLUN_VALID 0x80 /* did we receive an Identify msg */
+#define SBIC_TLUN_DOK 0x40 /* Disconnect OK */
+#define SBIC_TLUN_xxx 0x38
+#define SBIC_TLUN_MASK 0x07
+
+/*
+ * Command Phase register
+ */
+
+#define SBIC_CPH_MASK 0x7f /* values/restarts are cmd specific */
+#define SBIC_CPH(p) ((p) & SBIC_CPH_MASK)
+
+/*
+ * FIFO register
+ */
+
+#define SBIC_FIFO_DEEP 12
+
+/*
+ * maximum possible size in TC registers. Since this is 24 bit, it's easy
+ */
+#define SBIC_TC_MAX ((1 << 24) - 1)
+
+/*
+ * Synchronous xfer register
+ */
+
+#define SBIC_SYN_OFF_MASK 0x0f
+#define SBIC_SYN_MAX_OFFSET SBIC_FIFO_DEEP
+#define SBIC_SYN_PER_MASK 0x70
+#define SBIC_SYN_MIN_PERIOD 2 /* upto 8, encoded as 0 */
+
+#define SBIC_SYN(o,p) \
+ (((o) & SBIC_SYN_OFF_MASK) | (((p) << 4) & SBIC_SYN_PER_MASK))
+
+/*
+ * Transfer count register
+ * optimal access macros depend on addressing
+ */
+
+/*
+ * Destination ID (selid) register
+ */
+
+#define SBIC_SID_SCC 0x80 /* Select command chaining (tgt) */
+#define SBIC_SID_DPD 0x40 /* Data phase direction (inittor) */
+#define SBIC_SID_FROM_SCSI 0x40
+#define SBIC_SID_TO_SCSI 0x00
+#define SBIC_SID_xxx 0x38
+#define SBIC_SID_IDMASK 0x07
+
+/*
+ * Source ID (rselid) register
+ */
+
+#define SBIC_RID_ER 0x80 /* Enable reselection */
+#define SBIC_RID_ES 0x40 /* Enable selection */
+#define SBIC_RID_DSP 0x20 /* Disable select parity */
+#define SBIC_RID_SIV 0x08 /* Source ID valid */
+#define SBIC_RID_MASK 0x07
+
+/*
+ * Status register
+ */
+
+#define SBIC_CSR_CAUSE 0xf0
+#define SBIC_CSR_RESET 0x00 /* chip was reset */
+#define SBIC_CSR_CMD_DONE 0x10 /* cmd completed */
+#define SBIC_CSR_CMD_STOPPED 0x20 /* interrupted or abrted*/
+#define SBIC_CSR_CMD_ERR 0x40 /* end with error */
+#define SBIC_CSR_BUS_SERVICE 0x80 /* REQ pending on the bus */
+
+
+#define SBIC_CSR_QUALIFIER 0x0f
+/* Reset State Interrupts */
+#define SBIC_CSR_RESET 0x00 /* reset w/advanced features*/
+#define SBIC_CSR_RESET_AM 0x01 /* reset w/advanced features*/
+/* Successful Completion Interrupts */
+#define SBIC_CSR_TARGET 0x10 /* reselect complete */
+#define SBIC_CSR_INITIATOR 0x11 /* select complete */
+#define SBIC_CSR_WO_ATN 0x13 /* tgt mode completion */
+#define SBIC_CSR_W_ATN 0x14 /* ditto */
+#define SBIC_CSR_XLATED 0x15 /* translate address cmd */
+#define SBIC_CSR_S_XFERRED 0x16 /* initiator mode completion*/
+#define SBIC_CSR_XFERRED 0x18 /* phase in low bits */
+/* Paused or Aborted Interrupts */
+#define SBIC_CSR_MSGIN_W_ACK 0x20 /* (I) msgin, ACK asserted*/
+#define SBIC_CSR_SDP 0x21 /* (I) SDP msg received */
+#define SBIC_CSR_SEL_ABRT 0x22 /* sel/resel aborted */
+#define SBIC_CSR_XFR_PAUSED 0x23 /* (T) no ATN */
+#define SBIC_CSR_XFR_PAUSED_ATN 0x24 /* (T) ATN is asserted */
+#define SBIC_CSR_RSLT_AM 0x27 /* (I) lost selection (AM) */
+#define SBIC_CSR_MIS 0x28 /* (I) xfer aborted, ph mis */
+/* Terminated Interrupts */
+#define SBIC_CSR_CMD_INVALID 0x40
+#define SBIC_CSR_DISC 0x41 /* (I) tgt disconnected */
+#define SBIC_CSR_SEL_TIMEO 0x42
+#define SBIC_CSR_PE 0x43 /* parity error */
+#define SBIC_CSR_PE_ATN 0x44 /* ditto, ATN is asserted */
+#define SBIC_CSR_XLATE_TOOBIG 0x45
+#define SBIC_CSR_RSLT_NOAM 0x46 /* (I) lost sel, no AM mode */
+#define SBIC_CSR_BAD_STATUS 0x47 /* status byte was nok */
+#define SBIC_CSR_MIS_1 0x48 /* ph mis, see low bits */
+/* Service Required Interrupts */
+#define SBIC_CSR_RSLT_NI 0x80 /* reselected, no ify msg */
+#define SBIC_CSR_RSLT_IFY 0x81 /* ditto, AM mode, got ify */
+#define SBIC_CSR_SLT 0x82 /* selected, no ATN */
+#define SBIC_CSR_SLT_ATN 0x83 /* selected with ATN */
+#define SBIC_CSR_ATN 0x84 /* (T) ATN asserted */
+#define SBIC_CSR_DISC_1 0x85 /* (I) bus is free */
+#define SBIC_CSR_UNK_GROUP 0x87 /* strange CDB1 */
+#define SBIC_CSR_MIS_2 0x88 /* (I) ph mis, see low bits */
+
+#define SBIC_PHASE(csr) SCSI_PHASE(csr)
+
+/*
+ * Command register (command codes)
+ */
+
+#define SBIC_CMD_SBT 0x80 /* Single byte xfer qualifier */
+#define SBIC_CMD_MASK 0x7f
+
+ /* Miscellaneous */
+#define SBIC_CMD_RESET 0x00 /* (DTI) lev I */
+#define SBIC_CMD_ABORT 0x01 /* (DTI) lev I */
+#define SBIC_CMD_DISC 0x04 /* ( TI) lev I */
+#define SBIC_CMD_SSCC 0x0d /* ( TI) lev I */
+#define SBIC_CMD_SET_IDI 0x0f /* (DTI) lev I */
+#define SBIC_CMD_XLATE 0x18 /* (DT ) lev II */
+
+ /* Initiator state */
+#define SBIC_CMD_SET_ATN 0x02 /* ( I) lev I */
+#define SBIC_CMD_CLR_ACK 0x03 /* ( I) lev I */
+#define SBIC_CMD_XFER_PAD 0x19 /* ( I) lev II */
+#define SBIC_CMD_XFER_INFO 0x20 /* ( I) lev II */
+
+ /* Target state */
+#define SBIC_CMD_SND_DISC 0x0e /* ( T ) lev II */
+#define SBIC_CMD_RCV_CMD 0x10 /* ( T ) lev II */
+#define SBIC_CMD_RCV_DATA 0x11 /* ( T ) lev II */
+#define SBIC_CMD_RCV_MSG_OUT 0x12 /* ( T ) lev II */
+#define SBIC_CMD_RCV 0x13 /* ( T ) lev II */
+#define SBIC_CMD_SND_STATUS 0x14 /* ( T ) lev II */
+#define SBIC_CMD_SND_DATA 0x15 /* ( T ) lev II */
+#define SBIC_CMD_SND_MSG_IN 0x16 /* ( T ) lev II */
+#define SBIC_CMD_SND 0x17 /* ( T ) lev II */
+
+ /* Disconnected state */
+#define SBIC_CMD_RESELECT 0x05 /* (D ) lev II */
+#define SBIC_CMD_SEL_ATN 0x06 /* (D ) lev II */
+#define SBIC_CMD_SEL 0x07 /* (D ) lev II */
+#define SBIC_CMD_SEL_ATN_XFER 0x08 /* (D I) lev II */
+#define SBIC_CMD_SEL_XFER 0x09 /* (D I) lev II */
+#define SBIC_CMD_RESELECT_RECV 0x0a /* (DT ) lev II */
+#define SBIC_CMD_RESELECT_SEND 0x0b /* (DT ) lev II */
+#define SBIC_CMD_WAIT_SEL_RECV 0x0c /* (DT ) lev II */
+
+/* approximate, but we won't do SBT on selects */
+#define sbic_isa_select(cmd) (((cmd) > 0x5) && ((cmd) < 0xa))
+
+#define PAD(n) char n;
+#define SBIC_MACHINE_DMA_MODE SBIC_CTL_DMA
+
+typedef struct {
+ volatile unsigned char sbic_asr; /* r : Aux Status Register */
+#define sbic_address sbic_asr /* w : desired register no */
+ PAD(pad1);
+ PAD(pad2);
+ PAD(pad3);
+ volatile unsigned char sbic_value; /* rw: register value */
+} sbic_padded_ind_regmap_t;
+typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p;
+
+#define sbic_read_reg(regs,regno,val) do { \
+ (regs)->sbic_address = (regno); \
+ (val) = (regs)->sbic_value; \
+ } while (0)
+
+#define sbic_write_reg(regs,regno,val) do { \
+ (regs)->sbic_address = (regno); \
+ (regs)->sbic_value = (val); \
+ } while (0)
+
+#define SET_SBIC_myid(regs,val) sbic_write_reg(regs,SBIC_myid,val)
+#define GET_SBIC_myid(regs,val) sbic_read_reg(regs,SBIC_myid,val)
+#define SET_SBIC_cdbsize(regs,val) sbic_write_reg(regs,SBIC_cdbsize,val)
+#define GET_SBIC_cdbsize(regs,val) sbic_read_reg(regs,SBIC_cdbsize,val)
+#define SET_SBIC_control(regs,val) sbic_write_reg(regs,SBIC_control,val)
+#define GET_SBIC_control(regs,val) sbic_read_reg(regs,SBIC_control,val)
+#define SET_SBIC_timeo(regs,val) sbic_write_reg(regs,SBIC_timeo,val)
+#define GET_SBIC_timeo(regs,val) sbic_read_reg(regs,SBIC_timeo,val)
+#define SET_SBIC_cdb1(regs,val) sbic_write_reg(regs,SBIC_cdb1,val)
+#define GET_SBIC_cdb1(regs,val) sbic_read_reg(regs,SBIC_cdb1,val)
+#define SET_SBIC_cdb2(regs,val) sbic_write_reg(regs,SBIC_cdb2,val)
+#define GET_SBIC_cdb2(regs,val) sbic_read_reg(regs,SBIC_cdb2,val)
+#define SET_SBIC_cdb3(regs,val) sbic_write_reg(regs,SBIC_cdb3,val)
+#define GET_SBIC_cdb3(regs,val) sbic_read_reg(regs,SBIC_cdb3,val)
+#define SET_SBIC_cdb4(regs,val) sbic_write_reg(regs,SBIC_cdb4,val)
+#define GET_SBIC_cdb4(regs,val) sbic_read_reg(regs,SBIC_cdb4,val)
+#define SET_SBIC_cdb5(regs,val) sbic_write_reg(regs,SBIC_cdb5,val)
+#define GET_SBIC_cdb5(regs,val) sbic_read_reg(regs,SBIC_cdb5,val)
+#define SET_SBIC_cdb6(regs,val) sbic_write_reg(regs,SBIC_cdb6,val)
+#define GET_SBIC_cdb6(regs,val) sbic_read_reg(regs,SBIC_cdb6,val)
+#define SET_SBIC_cdb7(regs,val) sbic_write_reg(regs,SBIC_cdb7,val)
+#define GET_SBIC_cdb7(regs,val) sbic_read_reg(regs,SBIC_cdb7,val)
+#define SET_SBIC_cdb8(regs,val) sbic_write_reg(regs,SBIC_cdb8,val)
+#define GET_SBIC_cdb8(regs,val) sbic_read_reg(regs,SBIC_cdb8,val)
+#define SET_SBIC_cdb9(regs,val) sbic_write_reg(regs,SBIC_cdb9,val)
+#define GET_SBIC_cdb9(regs,val) sbic_read_reg(regs,SBIC_cdb9,val)
+#define SET_SBIC_cdb10(regs,val) sbic_write_reg(regs,SBIC_cdb10,val)
+#define GET_SBIC_cdb10(regs,val) sbic_read_reg(regs,SBIC_cdb10,val)
+#define SET_SBIC_cdb11(regs,val) sbic_write_reg(regs,SBIC_cdb11,val)
+#define GET_SBIC_cdb11(regs,val) sbic_read_reg(regs,SBIC_cdb11,val)
+#define SET_SBIC_cdb12(regs,val) sbic_write_reg(regs,SBIC_cdb12,val)
+#define GET_SBIC_cdb12(regs,val) sbic_read_reg(regs,SBIC_cdb12,val)
+#define SET_SBIC_tlun(regs,val) sbic_write_reg(regs,SBIC_tlun,val)
+#define GET_SBIC_tlun(regs,val) sbic_read_reg(regs,SBIC_tlun,val)
+#define SET_SBIC_cmd_phase(regs,val) sbic_write_reg(regs,SBIC_cmd_phase,val)
+#define GET_SBIC_cmd_phase(regs,val) sbic_read_reg(regs,SBIC_cmd_phase,val)
+#define SET_SBIC_syn(regs,val) sbic_write_reg(regs,SBIC_syn,val)
+#define GET_SBIC_syn(regs,val) sbic_read_reg(regs,SBIC_syn,val)
+#define SET_SBIC_count_hi(regs,val) sbic_write_reg(regs,SBIC_count_hi,val)
+#define GET_SBIC_count_hi(regs,val) sbic_read_reg(regs,SBIC_count_hi,val)
+#define SET_SBIC_count_med(regs,val) sbic_write_reg(regs,SBIC_count_med,val)
+#define GET_SBIC_count_med(regs,val) sbic_read_reg(regs,SBIC_count_med,val)
+#define SET_SBIC_count_lo(regs,val) sbic_write_reg(regs,SBIC_count_lo,val)
+#define GET_SBIC_count_lo(regs,val) sbic_read_reg(regs,SBIC_count_lo,val)
+#define SET_SBIC_selid(regs,val) sbic_write_reg(regs,SBIC_selid,val)
+#define GET_SBIC_selid(regs,val) sbic_read_reg(regs,SBIC_selid,val)
+#define SET_SBIC_rselid(regs,val) sbic_write_reg(regs,SBIC_rselid,val)
+#define GET_SBIC_rselid(regs,val) sbic_read_reg(regs,SBIC_rselid,val)
+#define SET_SBIC_csr(regs,val) sbic_write_reg(regs,SBIC_csr,val)
+#define GET_SBIC_csr(regs,val) sbic_read_reg(regs,SBIC_csr,val)
+#define SET_SBIC_cmd(regs,val) sbic_write_reg(regs,SBIC_cmd,val)
+#define GET_SBIC_cmd(regs,val) sbic_read_reg(regs,SBIC_cmd,val)
+#define SET_SBIC_data(regs,val) sbic_write_reg(regs,SBIC_data,val)
+#define GET_SBIC_data(regs,val) sbic_read_reg(regs,SBIC_data,val)
+
+#define SBIC_TC_PUT(regs,val) do { \
+ sbic_write_reg(regs,SBIC_count_hi,((val)>>16)); \
+ (regs)->sbic_value = (val)>>8; \
+ (regs)->sbic_value = (val); \
+} while (0)
+#define SBIC_TC_GET(regs,val) do { \
+ sbic_read_reg(regs,SBIC_count_hi,(val)); \
+ (val) = ((val)<<8) | (regs)->sbic_value; \
+ (val) = ((val)<<8) | (regs)->sbic_value; \
+} while (0)
+
+#define SBIC_LOAD_COMMAND(regs,cmd,cmdsize) do { \
+ int n=(cmdsize)-1; \
+ char *ptr = (char*)(cmd); \
+ sbic_write_reg(regs,SBIC_cdb1,*ptr++); \
+ while (n-- > 0) (regs)->sbic_value = *ptr++; \
+} while (0)
+
+#define GET_SBIC_asr(regs,val) (val) = (regs)->sbic_asr
+
+#define WAIT_CIP(regs) do { \
+ while ((regs)->sbic_asr & SBIC_ASR_CIP) \
+ ; \
+} while (0)
+
+/* transmit a byte in programmed I/O mode */
+#define SEND_BYTE(regs, ch) do { \
+ WAIT_CIP(regs); \
+ SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
+ SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \
+ SET_SBIC_data(regs, ch); \
+ } while (0)
+
+/* receive a byte in programmed I/O mode */
+#define RECV_BYTE(regs, ch) do { \
+ WAIT_CIP(regs); \
+ SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
+ SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \
+ GET_SBIC_data(regs, ch); \
+ } while (0)
--- /dev/null
+/* $NetBSD: sbicvar.h,v 1.1 1996/03/06 23:44:10 mark Exp $ */
+
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)scsivar.h 7.1 (Berkeley) 5/8/90
+ */
+
+#ifndef _SBICVAR_H_
+#define _SBICVAR_H_
+#include <sys/malloc.h>
+
+/*
+ * The largest single request will be MAXPHYS bytes which will require
+ * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of
+ * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the
+ * buffer is not page aligned (+1).
+ */
+#define DMAMAXIO (MAXPHYS/NBPG+1)
+
+struct dma_chain {
+ int dc_count;
+ char *dc_addr;
+};
+
+/*
+ * ACB. Holds additional information for each SCSI command Comments: We
+ * need a separate scsi command block because we may need to overwrite it
+ * with a request sense command. Basicly, we refrain from fiddling with
+ * the scsi_xfer struct (except do the expected updating of return values).
+ * We'll generally update: xs->{flags,resid,error,sense,status} and
+ * occasionally xs->retries.
+ */
+struct sbic_acb {
+ TAILQ_ENTRY(sbic_acb) chain;
+ struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */
+ int flags; /* Status */
+#define ACB_FREE 0x00
+#define ACB_ACTIVE 0x01
+#define ACB_DONE 0x04
+#define ACB_CHKSENSE 0x08
+#define ACB_BBUF 0x10 /* DMA input needs to be copied from bounce */
+#define ACB_DATAIN 0x20 /* DMA direction flag */
+ struct scsi_generic cmd; /* SCSI command block */
+ int clen;
+ struct dma_chain sc_kv; /* Virtual address of whole DMA */
+ struct dma_chain sc_pa; /* Physical address of DMA segment */
+ u_long sc_tcnt; /* number of bytes for this DMA */
+ u_char *sc_dmausrbuf; /* user buffer kva - for bounce copy */
+ u_long sc_dmausrlen; /* length of bounce copy */
+ u_short sc_dmacmd; /* Internal data for this DMA */
+ char *pa_addr; /* XXXX initial phys addr */
+ u_char *sc_usrbufpa; /* user buffer phys addr */
+};
+
+/*
+ * Some info about each (possible) target on the SCSI bus. This should
+ * probably have been a "per target+lunit" structure, but we'll leave it at
+ * this for now. Is there a way to reliably hook it up to sc->fordriver??
+ */
+struct sbic_tinfo {
+ int cmds; /* #commands processed */
+ int dconns; /* #disconnects */
+ int touts; /* #timeouts */
+ int perrs; /* #parity errors */
+ int senses; /* #request sense commands sent */
+ u_char* bounce; /* Bounce buffer for this device */
+ ushort lubusy; /* What local units/subr. are busy? */
+ u_char flags;
+ u_char period; /* Period suggestion */
+ u_char offset; /* Offset suggestion */
+} tinfo_t;
+
+struct sbic_softc {
+ struct device sc_dev;
+/* struct isr sc_isr;*/
+ struct target_sync {
+ u_char state;
+ u_char period;
+ u_char offset;
+ } sc_sync[8];
+ u_char target; /* Currently active target */
+ u_char lun;
+ struct scsi_link sc_link; /* proto for sub devices */
+ sbic_regmap_p sc_sbicp; /* the SBIC */
+ volatile void *sc_cregs; /* driver specific regs */
+
+ /* Lists of command blocks */
+ TAILQ_HEAD(acb_list, sbic_acb) free_list,
+ ready_list,
+ nexus_list;
+
+ struct sbic_acb *sc_nexus; /* current command */
+ struct sbic_acb sc_acb[8]; /* the real command blocks */
+ struct sbic_tinfo sc_tinfo[8];
+
+ struct scsi_xfer *sc_xs; /* transfer from high level code */
+ u_char sc_flags;
+ u_char sc_scsiaddr;
+ u_char sc_stat[2];
+ u_char sc_msg[7];
+ u_long sc_clkfreq;
+ u_long sc_tcnt; /* number of bytes transfered */
+ u_short sc_dmacmd; /* used by dma drivers */
+ u_short sc_dmatimo; /* dma timeout */
+ u_long sc_dmamask; /* dma valid mem mask */
+ struct dma_chain *sc_cur;
+ struct dma_chain *sc_last;
+ int (*sc_dmago) __P((struct sbic_softc *, char *, int, int));
+ int (*sc_dmanext) __P((struct sbic_softc *));
+ void (*sc_enintr) __P((struct sbic_softc *));
+ void (*sc_dmastop) __P((struct sbic_softc *));
+ u_short gtsc_bankmask; /* GVP specific bank selected */
+};
+
+/* sc_flags */
+#define SBICF_ALIVE 0x01 /* controller initialized */
+#define SBICF_DCFLUSH 0x02 /* need flush for overlap after dma finishes */
+#define SBICF_SELECTED 0x04 /* bus is in selected state. */
+#define SBICF_ICMD 0x08 /* Immediate command in execution */
+#define SBICF_BADDMA 0x10 /* controller can only DMA to ztwobus space */
+#define SBICF_INTR 0x40 /* SBICF interrupt expected */
+#define SBICF_INDMA 0x80 /* not used yet, DMA I/O in progress */
+
+/* sync states */
+#define SYNC_START 0 /* no sync handshake started */
+#define SYNC_SENT 1 /* we sent sync request, no answer yet */
+#define SYNC_DONE 2 /* target accepted our (or inferior) settings,
+ or it rejected the request and we stay async */
+#ifdef DEBUG
+#define DDB_FOLLOW 0x04
+#define DDB_IO 0x08
+#endif
+extern u_char sbic_inhibit_sync[8];
+extern int sbic_no_dma;
+extern int sbic_clock_override;
+
+#define PHASE 0x07 /* mask for psns/pctl phase */
+#define DATA_OUT_PHASE 0x00
+#define DATA_IN_PHASE 0x01
+#define CMD_PHASE 0x02
+#define STATUS_PHASE 0x03
+#define BUS_FREE_PHASE 0x04
+#define ARB_SEL_PHASE 0x05 /* Fuji chip combines arbitration with sel. */
+#define MESG_OUT_PHASE 0x06
+#define MESG_IN_PHASE 0x07
+
+#define MSG_CMD_COMPLETE 0x00
+#define MSG_EXT_MESSAGE 0x01
+#define MSG_SAVE_DATA_PTR 0x02
+#define MSG_RESTORE_PTR 0x03
+#define MSG_DISCONNECT 0x04
+#define MSG_INIT_DETECT_ERROR 0x05
+#define MSG_ABORT 0x06
+#define MSG_REJECT 0x07
+#define MSG_NOOP 0x08
+#define MSG_PARITY_ERROR 0x09
+#define MSG_BUS_DEVICE_RESET 0x0C
+#define MSG_IDENTIFY 0x80
+#define MSG_IDENTIFY_DR 0xc0 /* (disconnect/reconnect allowed) */
+#define MSG_SYNC_REQ 0x01
+
+#define MSG_ISIDENTIFY(x) (x&MSG_IDENTIFY)
+#define IFY_TRN 0x20
+#define IFY_LUNTRN(x) (x&0x07)
+#define IFY_LUN(x) (!(x&0x20))
+
+/* Check if high bit set */
+
+#define STS_CHECKCOND 0x02 /* Check Condition (ie., read sense) */
+#define STS_CONDMET 0x04 /* Condition Met (ie., search worked) */
+#define STS_BUSY 0x08
+#define STS_INTERMED 0x10 /* Intermediate status sent */
+#define STS_EXT 0x80 /* Extended status valid */
+
+
+/* States returned by our state machine */
+
+#define SBIC_STATE_ERROR -1
+#define SBIC_STATE_DONE 0
+#define SBIC_STATE_RUNNING 1
+#define SBIC_STATE_DISCONNECT 2
+
+/*
+ * XXXX
+ */
+struct scsi_fmt_cdb {
+ int len; /* cdb length (in bytes) */
+ u_char cdb[28]; /* cdb to use on next read/write */
+};
+
+struct buf;
+struct scsi_xfer;
+
+void sbic_minphys __P((struct buf *bp));
+int sbic_scsicmd __P((struct scsi_xfer *));
+
+#endif /* _SBICVAR_H_ */
--- /dev/null
+/* $NetBSD: sfas.c,v 1.4 1996/03/18 21:23:20 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Scott Stevens
+ * Copyright (c) 1995 Daniel Widenfalk
+ * Copyright (c) 1994 Christian E. Hopps
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)scsi.c 7.5 (Berkeley) 5/4/91
+ */
+
+/*
+ * Emulex FAS216 scsi adaptor driver
+ */
+
+/*
+ * Modified for NetBSD/arm32 by Scott Stevens
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <machine/pmap.h>
+#include <machine/cpu.h>
+#include <machine/io.h>
+#include <machine/irqhandler.h>
+#include <machine/katelib.h>
+#include <arm32/podulebus/podulebus.h>
+#include <arm32/podulebus/sfasreg.h>
+#include <arm32/podulebus/sfasvar.h>
+
+/* Externs */
+extern pt_entry_t *pmap_pte __P((pmap_t, vm_offset_t));
+
+void sfasinitialize __P((struct sfas_softc *));
+void sfas_minphys __P((struct buf *bp));
+int sfas_scsicmd __P((struct scsi_xfer *xs));
+void sfas_donextcmd __P((struct sfas_softc *dev, struct sfas_pending *pendp));
+void sfas_scsidone __P((struct sfas_softc *dev, struct scsi_xfer *xs,
+ int stat));
+void sfasintr __P((struct sfas_softc *dev));
+void sfasiwait __P((struct sfas_softc *dev));
+void sfasreset __P((struct sfas_softc *dev, int how));
+int sfasselect __P((struct sfas_softc *dev, struct sfas_pending *pendp,
+ unsigned char *cbuf, int clen,
+ unsigned char *buf, int len, int mode));
+void sfasicmd __P((struct sfas_softc *dev, struct sfas_pending *pendp));
+void sfasgo __P((struct sfas_softc *dev, struct sfas_pending *pendp));
+
+/*
+ * Initialize these to make 'em patchable. Defaults to enable sync and discon.
+ */
+u_char sfas_inhibit_sync[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+u_char sfas_inhibit_disc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+#define DEBUG
+#ifdef DEBUG
+#define QPRINTF(a) if (sfas_debug > 1) printf a
+int sfas_debug = 2;
+#else
+#define QPRINTF
+#endif
+
+/*
+ * default minphys routine for sfas based controllers
+ */
+void
+sfas_minphys(bp)
+ struct buf *bp;
+{
+
+ /*
+ * No max transfer at this level.
+ */
+ minphys(bp);
+}
+
+/*
+ * Initialize the nexus structs.
+ */
+void
+sfas_init_nexus(dev, nexus)
+ struct sfas_softc *dev;
+ struct nexus *nexus;
+{
+ bzero(nexus, sizeof(struct nexus));
+
+ nexus->state = SFAS_NS_IDLE;
+ nexus->period = 200;
+ nexus->offset = 0;
+ nexus->syncper = 5;
+ nexus->syncoff = 0;
+ nexus->config3 = dev->sc_config3 & ~SFAS_CFG3_FASTSCSI;
+}
+
+void
+sfasinitialize(dev)
+ struct sfas_softc *dev;
+{
+ u_int *pte;
+ int i;
+
+ dev->sc_led_status = 0;
+
+ TAILQ_INIT(&dev->sc_xs_pending);
+ TAILQ_INIT(&dev->sc_xs_free);
+
+/*
+ * Initialize the sfas_pending structs and link them into the free list. We
+ * have to set vm_link_data.pages to 0 or the vm FIX won't work.
+ */
+ for(i=0; i<MAXPENDING; i++) {
+ TAILQ_INSERT_TAIL(&dev->sc_xs_free, &dev->sc_xs_store[i],
+ link);
+ }
+
+/*
+ * Calculate the correct clock conversion factor 2 <= factor <= 8, i.e. set
+ * the factor to clock_freq / 5 (int).
+ */
+ if (dev->sc_clock_freq <= 10)
+ dev->sc_clock_conv_fact = 2;
+ if (dev->sc_clock_freq <= 40)
+ dev->sc_clock_conv_fact = 2+((dev->sc_clock_freq-10)/5);
+ else
+ panic("sfasinitialize: Clock frequence too high");
+
+/* Setup and save the basic configuration registers */
+ dev->sc_config1 = (dev->sc_host_id & SFAS_CFG1_BUS_ID_MASK);
+ dev->sc_config2 = SFAS_CFG2_FEATURES_ENABLE;
+ dev->sc_config3 = (dev->sc_clock_freq > 25 ? SFAS_CFG3_FASTCLK : 0);
+
+/* Precalculate timeout value and clock period. */
+/* Ekkk ... floating point in the kernel !!!! */
+/* dev->sc_timeout_val = 1+dev->sc_timeout*dev->sc_clock_freq/
+ (7.682*dev->sc_clock_conv_fact);*/
+ dev->sc_timeout_val = 1+dev->sc_timeout*dev->sc_clock_freq/
+ ((7682*dev->sc_clock_conv_fact)/1000);
+ dev->sc_clock_period = 1000/dev->sc_clock_freq;
+
+ sfasreset(dev, 1 | 2); /* Reset Chip and Bus */
+
+ dev->sc_units_disconnected = 0;
+ dev->sc_msg_in_len = 0;
+ dev->sc_msg_out_len = 0;
+
+ dev->sc_flags = 0;
+
+ for(i=0; i<8; i++)
+ sfas_init_nexus(dev, &dev->sc_nexus[i]);
+
+/*
+ * Setup bump buffer.
+ */
+ dev->sc_bump_va = (u_char *)kmem_alloc(kernel_map, dev->sc_bump_sz);
+ dev->sc_bump_pa = pmap_extract(kernel_pmap, (vm_offset_t)dev->sc_bump_va);
+
+/*
+ * Setup pages to noncachable, that way we don't have to flush the cache
+ * every time we need "bumped" transfer.
+ */
+ pte = pmap_pte(kernel_pmap, (vm_offset_t)dev->sc_bump_va);
+ *pte &= ~PT_C;
+ tlbflush();
+
+ printf(" dmabuf V0x%08x P0x%08x", (u_int)dev->sc_bump_va, (u_int)dev->sc_bump_pa);
+}
+
+
+/*
+ * used by specific sfas controller
+ */
+int
+sfas_scsicmd(struct scsi_xfer *xs)
+{
+ struct sfas_softc *dev;
+ struct scsi_link *slp;
+ struct sfas_pending *pendp;
+ int flags, s, target;
+
+ slp = xs->sc_link;
+ dev = slp->adapter_softc;
+ flags = xs->flags;
+ target = slp->target;
+
+ if (flags & SCSI_DATA_UIO)
+ panic("sfas: scsi data uio requested");
+
+ if ((flags & SCSI_POLL) && (dev->sc_flags & SFAS_ACTIVE))
+ panic("sfas_scsicmd: busy");
+
+/* Get hold of a sfas_pending block. */
+ s = splbio();
+ pendp = dev->sc_xs_free.tqh_first;
+ if (pendp == NULL) {
+ splx(s);
+ return(TRY_AGAIN_LATER);
+ }
+ TAILQ_REMOVE(&dev->sc_xs_free, pendp, link);
+ pendp->xs = xs;
+ splx(s);
+
+
+/* If the chip if busy OR the unit is busy, we have to wait for out turn. */
+ if ((dev->sc_flags & SFAS_ACTIVE) ||
+ (dev->sc_nexus[target].flags & SFAS_NF_UNIT_BUSY)) {
+ s = splbio();
+ TAILQ_INSERT_TAIL(&dev->sc_xs_pending, pendp, link);
+ splx(s);
+ } else
+ sfas_donextcmd(dev, pendp);
+
+ return((flags & SCSI_POLL) ? COMPLETE : SUCCESSFULLY_QUEUED);
+}
+
+/*
+ * Actually select the unit, whereby the whole scsi-process is started.
+ */
+void
+sfas_donextcmd(dev, pendp)
+ struct sfas_softc *dev;
+ struct sfas_pending *pendp;
+{
+ int s;
+
+/*
+ * Special case for scsi unit reset. I think this is waterproof. We first
+ * select the unit during splbio. We then cycle through the generated
+ * interrupts until the interrupt routine signals that the unit has
+ * acknowledged the reset. After that we have to wait a reset to select
+ * delay before anything else can happend.
+ */
+ if (pendp->xs->flags & SCSI_RESET) {
+ struct nexus *nexus;
+
+ s = splbio();
+ while(!sfasselect(dev, pendp, 0, 0, 0, 0, SFAS_SELECT_K)) {
+ splx(s);
+ delay(10);
+ s = splbio();
+ }
+
+ nexus = dev->sc_cur_nexus;
+ while(nexus->flags & SFAS_NF_UNIT_BUSY) {
+ sfasiwait(dev);
+ sfasintr(dev);
+ }
+
+ nexus->flags |= SFAS_NF_UNIT_BUSY;
+ splx(s);
+
+ sfasreset(dev, 0);
+
+ s = splbio();
+ nexus->flags &= ~SFAS_NF_UNIT_BUSY;
+ splx(s);
+ }
+
+/*
+ * If we are polling, go to splbio and perform the command, else we poke
+ * the scsi-bus via sfasgo to get the interrupt machine going.
+ */
+ if (pendp->xs->flags & SCSI_POLL) {
+ s = splbio();
+ sfasicmd(dev, pendp);
+ TAILQ_INSERT_TAIL(&dev->sc_xs_free, pendp, link);
+ splx(s);
+ } else {
+ sfasgo(dev, pendp);
+ }
+}
+
+void
+sfas_scsidone(dev, xs, stat)
+ struct sfas_softc *dev;
+ struct scsi_xfer *xs;
+ int stat;
+{
+ struct sfas_pending *pendp;
+ int s;
+
+ xs->status = stat;
+
+ if (stat == 0)
+ xs->resid = 0;
+ else {
+ switch(stat) {
+ case SCSI_CHECK:
+ /* If we get here we have valid sense data. Faults during
+ * sense is handeled elsewhere and will generate a
+ * XS_DRIVER_STUFFUP. */
+ xs->error = XS_SENSE;
+ break;
+ case SCSI_BUSY:
+ xs->error = XS_BUSY;
+ break;
+ case -1:
+ xs->error = XS_DRIVER_STUFFUP;
+ QPRINTF(("sfas_scsicmd() bad %x\n", stat));
+ break;
+ default:
+ xs->error = XS_TIMEOUT;
+ break;
+ }
+ }
+
+ xs->flags |= ITSDONE;
+
+/* Steal the next command from the queue so that one unit can't hog the bus. */
+ s = splbio();
+ pendp = dev->sc_xs_pending.tqh_first;
+ while(pendp) {
+ if (!(dev->sc_nexus[pendp->xs->sc_link->target].flags &
+ SFAS_NF_UNIT_BUSY))
+ break;
+ pendp = pendp->link.tqe_next;
+ }
+
+ if (pendp != NULL) {
+ TAILQ_REMOVE(&dev->sc_xs_pending, pendp, link);
+ }
+
+ splx(s);
+ scsi_done(xs);
+
+ if (pendp)
+ sfas_donextcmd(dev, pendp);
+}
+
+/*
+ * There are two kinds of reset:
+ * 1) CHIP-bus reset. This also implies a SCSI-bus reset.
+ * 2) SCSI-bus reset.
+ * After the appropriate resets have been performed we wait a reset to select
+ * delay time.
+ */
+void
+sfasreset(dev, how)
+ struct sfas_softc *dev;
+ int how;
+{
+ sfas_regmap_p rp;
+ int i, s;
+
+ rp = dev->sc_fas;
+
+ if (how & 1) {
+ for(i=0; i<8; i++)
+ sfas_init_nexus(dev, &dev->sc_nexus[i]);
+
+ *rp->sfas_command = SFAS_CMD_RESET_CHIP;
+ delay(1);
+ *rp->sfas_command = SFAS_CMD_NOP;
+
+ *rp->sfas_config1 = dev->sc_config1;
+ *rp->sfas_config2 = dev->sc_config2;
+ *rp->sfas_config3 = dev->sc_config3;
+ *rp->sfas_timeout = dev->sc_timeout_val;
+ *rp->sfas_clkconv = dev->sc_clock_conv_fact &
+ SFAS_CLOCK_CONVERSION_MASK;
+ }
+
+ if (how & 2) {
+ for(i=0; i<8; i++)
+ sfas_init_nexus(dev, &dev->sc_nexus[i]);
+
+ s = splbio();
+
+ *rp->sfas_command = SFAS_CMD_RESET_SCSI_BUS;
+ delay(100);
+
+/* Skip interrupt generated by RESET_SCSI_BUS */
+ while(*rp->sfas_status & SFAS_STAT_INTERRUPT_PENDING) {
+ dev->sc_status = *rp->sfas_status;
+ dev->sc_interrupt = *rp->sfas_interrupt;
+
+ delay(100);
+ }
+
+ dev->sc_status = *rp->sfas_status;
+ dev->sc_interrupt = *rp->sfas_interrupt;
+
+ splx(s);
+ }
+
+ if (dev->sc_config_flags & SFAS_SLOW_START)
+ delay(4*250000); /* RESET to SELECT DELAY*4 for slow devices */
+ else
+ delay(250000); /* RESET to SELECT DELAY */
+}
+
+/*
+ * Save active data pointers to the nexus block currently active.
+ */
+void
+sfas_save_pointers(dev)
+ struct sfas_softc *dev;
+{
+ struct nexus *nx;
+
+ nx = dev->sc_cur_nexus;
+ if (nx) {
+ nx->cur_link = dev->sc_cur_link;
+ nx->max_link = dev->sc_max_link;
+ nx->buf = dev->sc_buf;
+ nx->len = dev->sc_len;
+ nx->dma_len = dev->sc_dma_len;
+ nx->dma_buf = dev->sc_dma_buf;
+ nx->dma_blk_flg = dev->sc_dma_blk_flg;
+ nx->dma_blk_len = dev->sc_dma_blk_len;
+ nx->dma_blk_ptr = dev->sc_dma_blk_ptr;
+ }
+}
+
+/*
+ * Restore data pointers from the currently active nexus block.
+ */
+void
+sfas_restore_pointers(dev)
+ struct sfas_softc *dev;
+{
+ struct nexus *nx;
+
+ nx = dev->sc_cur_nexus;
+ if (nx) {
+ dev->sc_cur_link = nx->cur_link;
+ dev->sc_max_link = nx->max_link;
+ dev->sc_buf = nx->buf;
+ dev->sc_len = nx->len;
+ dev->sc_dma_len = nx->dma_len;
+ dev->sc_dma_buf = nx->dma_buf;
+ dev->sc_dma_blk_flg = nx->dma_blk_flg;
+ dev->sc_dma_blk_len = nx->dma_blk_len;
+ dev->sc_dma_blk_ptr = nx->dma_blk_ptr;
+ dev->sc_chain = nx->dma;
+ dev->sc_unit = (nx->lun_unit & 0x0F);
+ dev->sc_lun = (nx->lun_unit & 0xF0) >> 4;
+ }
+}
+
+/*
+ * sfasiwait is used during interrupt and polled IO to wait for an event from
+ * the FAS chip. This function MUST NOT BE CALLED without interrupt disabled.
+ */
+void
+sfasiwait(dev)
+ struct sfas_softc *dev;
+{
+ sfas_regmap_p rp;
+
+/*
+ * If SFAS_DONT_WAIT is set, we have already grabbed the interrupt info
+ * elsewhere. So we don't have to wait for it.
+ */
+ if (dev->sc_flags & SFAS_DONT_WAIT) {
+ dev->sc_flags &= ~SFAS_DONT_WAIT;
+ return;
+ }
+
+ rp = dev->sc_fas;
+
+/* Wait for FAS chip to signal an interrupt. */
+ while(!(*rp->sfas_status & SFAS_STAT_INTERRUPT_PENDING))
+ delay(1);
+
+/* Grab interrupt info from chip. */
+ dev->sc_status = *rp->sfas_status;
+ dev->sc_interrupt = *rp->sfas_interrupt;
+ if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
+ dev->sc_resel[0] = *rp->sfas_fifo;
+ dev->sc_resel[1] = *rp->sfas_fifo;
+ }
+}
+
+/*
+ * Transfer info to/from device. sfas_ixfer uses polled IO+sfasiwait so the
+ * rules that apply to sfasiwait also applies here.
+ */
+void
+sfas_ixfer(dev, polling)
+ struct sfas_softc *dev;
+ int polling;
+{
+ sfas_regmap_p rp;
+ u_char *buf;
+ int len, mode, phase;
+
+ rp = dev->sc_fas;
+ buf = dev->sc_buf;
+ len = dev->sc_len;
+
+/*
+ * Decode the scsi phase to determine whether we are reading or writing.
+ * mode == 1 => READ, mode == 0 => WRITE
+ */
+ phase = dev->sc_status & SFAS_STAT_PHASE_MASK;
+ mode = (phase == SFAS_PHASE_DATA_IN);
+
+ while(len && ((dev->sc_status & SFAS_STAT_PHASE_MASK) == phase))
+ if (mode) {
+ *rp->sfas_command = SFAS_CMD_TRANSFER_INFO;
+
+ sfasiwait(dev);
+
+ *buf++ = *rp->sfas_fifo;
+ len--;
+ } else {
+ len--;
+ *rp->sfas_fifo = *buf++;
+ *rp->sfas_command = SFAS_CMD_TRANSFER_INFO;
+
+ sfasiwait(dev);
+ }
+
+/* Update buffer pointers to reflect the sent/recieved data. */
+ dev->sc_buf = buf;
+ dev->sc_len = len;
+
+/*
+ * Since the last sfasiwait will be a phase-change, we can't wait for it
+ * again later, so we have to signal that.
+ * Since this may be called from an interrupt initiated routine then we
+ * must call sfasintr again to avoid losing an interrupt. Phew!
+ */
+ if(polling)
+ dev->sc_flags |= SFAS_DONT_WAIT;
+ else
+ sfasintr(dev);
+}
+
+/*
+ * Build a Synchronous Data Transfer Request message
+ */
+void
+sfas_build_sdtrm(dev, period, offset)
+ struct sfas_softc *dev;
+ int period;
+ int offset;
+{
+ dev->sc_msg_out[0] = 0x01;
+ dev->sc_msg_out[1] = 0x03;
+ dev->sc_msg_out[2] = 0x01;
+ dev->sc_msg_out[3] = period/4;
+ dev->sc_msg_out[4] = offset;
+ dev->sc_msg_out_len= 5;
+}
+
+/*
+ * Arbitate the scsi bus and select the unit
+ */
+int
+sfas_select_unit(dev, target)
+ struct sfas_softc *dev;
+ short target;
+{
+ sfas_regmap_p rp;
+ struct nexus *nexus;
+ int s, retcode, i;
+ u_char cmd;
+
+ s = splbio(); /* Do this at splbio so that we won't be disturbed. */
+
+ retcode = 0;
+
+ nexus = &dev->sc_nexus[target];
+
+/*
+ * Check if the chip is busy. If not the we mark it as so and hope that nobody
+ * reselects us until we have grabbed the bus.
+ */
+ if (!(dev->sc_flags & SFAS_ACTIVE) && !dev->sc_sel_nexus) {
+ dev->sc_flags |= SFAS_ACTIVE;
+
+ rp = dev->sc_fas;
+
+ *rp->sfas_syncper = nexus->syncper;
+ *rp->sfas_syncoff = nexus->syncoff;
+ *rp->sfas_config3 = nexus->config3;
+
+ *rp->sfas_config1 = dev->sc_config1;
+ *rp->sfas_timeout = dev->sc_timeout_val;
+ *rp->sfas_dest_id = target;
+
+/* If nobody has stolen the bus, we can send a select command to the chip. */
+ if (!(*rp->sfas_status & SFAS_STAT_INTERRUPT_PENDING)) {
+ *rp->sfas_fifo = nexus->ID;
+ if ((nexus->flags & (SFAS_NF_DO_SDTR | SFAS_NF_RESET))
+ || (dev->sc_msg_out_len != 0))
+ cmd = SFAS_CMD_SEL_ATN_STOP;
+ else {
+ for(i=0; i<nexus->clen; i++)
+ *rp->sfas_fifo = nexus->cbuf[i];
+
+ cmd = SFAS_CMD_SEL_ATN;
+ }
+
+ dev->sc_sel_nexus = nexus;
+
+ *rp->sfas_command = cmd;
+ retcode = 1;
+ }
+ }
+
+ splx(s);
+ return(retcode);
+}
+
+/*
+ * Grab the nexus if available else return 0.
+ */
+struct nexus *
+sfas_arbitate_target(dev, target)
+ struct sfas_softc *dev;
+ int target;
+{
+ struct nexus *nexus;
+ int s;
+
+/*
+ * This is realy simple. Raise interrupt level to splbio. Grab the nexus and
+ * leave.
+ */
+ nexus = &dev->sc_nexus[target];
+
+ s = splbio();
+
+ if (nexus->flags & SFAS_NF_UNIT_BUSY)
+ nexus = 0;
+ else
+ nexus->flags |= SFAS_NF_UNIT_BUSY;
+
+ splx(s);
+ return(nexus);
+}
+
+/*
+ * Setup a nexus for use. Initializes command, buffer pointers and dma chain.
+ */
+void
+sfas_setup_nexus(dev, nexus, pendp, cbuf, clen, buf, len, mode)
+ struct sfas_softc *dev;
+ struct nexus *nexus;
+ struct sfas_pending *pendp;
+ unsigned char *cbuf;
+ int clen;
+ unsigned char *buf;
+ int len;
+ int mode;
+{
+ char sync, target, lun;
+
+ target = pendp->xs->sc_link->target;
+ lun = pendp->xs->sc_link->lun;
+
+/*
+ * Adopt mode to reflect the config flags.
+ * If we can't use DMA we can't use synch transfer. Also check the
+ * sfas_inhibit_xxx[target] flags.
+ */
+ if ((dev->sc_config_flags & (SFAS_NO_SYNCH | SFAS_NO_DMA)) ||
+ sfas_inhibit_sync[(int)target])
+ mode &= ~SFAS_SELECT_S;
+
+ if ((dev->sc_config_flags & SFAS_NO_RESELECT) ||
+ sfas_inhibit_disc[(int)target])
+ mode &= ~SFAS_SELECT_R;
+
+ nexus->xs = pendp->xs;
+
+/* Setup the nexus struct. */
+ nexus->ID = ((mode & SFAS_SELECT_R) ? 0xC0 : 0x80) | lun;
+ nexus->clen = clen;
+ bcopy(cbuf, nexus->cbuf, nexus->clen);
+ nexus->cbuf[1] |= lun << 5; /* Fix the lun bits */
+ nexus->cur_link = 0;
+ nexus->dma_len = 0;
+ nexus->dma_buf = 0;
+ nexus->dma_blk_len = 0;
+ nexus->dma_blk_ptr = 0;
+ nexus->len = len;
+ nexus->buf = buf;
+ nexus->lun_unit = (lun << 4) | target;
+ nexus->state = SFAS_NS_SELECTED;
+
+/* We must keep these flags. All else must be zero. */
+ nexus->flags &= SFAS_NF_UNIT_BUSY | SFAS_NF_REQUEST_SENSE
+ | SFAS_NF_SYNC_TESTED | SFAS_NF_SELECT_ME;
+
+/*
+ * If we are requesting sense, reflect that in the flags so that we can handle
+ * error in sense data correctly
+ */
+ if (nexus->flags & SFAS_NF_REQUEST_SENSE) {
+ nexus->flags &= ~SFAS_NF_REQUEST_SENSE;
+ nexus->flags |= SFAS_NF_SENSING;
+ }
+
+ if (mode & SFAS_SELECT_I)
+ nexus->flags |= SFAS_NF_IMMEDIATE;
+ if (mode & SFAS_SELECT_K)
+ nexus->flags |= SFAS_NF_RESET;
+
+ sync = ((mode & SFAS_SELECT_S) ? 1 : 0);
+
+/* We can't use sync during polled IO. */
+ if (sync && (mode & SFAS_SELECT_I))
+ sync = 0;
+
+ if (!sync &&
+ ((nexus->flags & SFAS_NF_SYNC_TESTED) && (nexus->offset != 0))) {
+ /*
+ * If the scsi unit is set to synch transfer and we don't want
+ * that, we have to renegotiate.
+ */
+
+ nexus->flags |= SFAS_NF_DO_SDTR;
+ nexus->period = 200;
+ nexus->offset = 0;
+ } else if (sync && !(nexus->flags & SFAS_NF_SYNC_TESTED)) {
+ /*
+ * If the scsi unit is not set to synch transfer and we want
+ * that, we have to negotiate. This should realy base the
+ * period on the clock frequence rather than just check if
+ * >25Mhz
+ */
+
+ nexus->flags |= SFAS_NF_DO_SDTR;
+ nexus->period = ((dev->sc_clock_freq>25) ? 100 : 200);
+ nexus->offset = 8;
+
+ /* If the user has a long cable, we want to limit the period */
+ if ((nexus->period == 100) &&
+ (dev->sc_config_flags & SFAS_SLOW_CABLE))
+ nexus->period = 200;
+ }
+
+/*
+ * Fake a dma-block for polled IO. This way we can use the same code to handle
+ * reselection. Much nicer this way.
+ */
+ if ((mode & SFAS_SELECT_I) || (dev->sc_config_flags & SFAS_NO_DMA)) {
+ nexus->dma[0].ptr = (vm_offset_t)buf;
+ nexus->dma[0].len = len;
+ nexus->dma[0].flg = SFAS_CHAIN_PRG;
+ nexus->max_link = 1;
+ } else {
+ nexus->max_link = dev->sc_build_dma_chain(dev, nexus->dma,
+ buf, len);
+ }
+
+/* Flush the caches. (If needed) */
+/* Do I need to ? */
+/*
+ if ((mmutype == MMU_68040) && len && !(mode & SFAS_SELECT_I))
+ dma_cachectl(buf, len);
+*/
+}
+
+int
+sfasselect(dev, pendp, cbuf, clen, buf, len, mode)
+ struct sfas_softc *dev;
+ struct sfas_pending *pendp;
+ unsigned char *cbuf;
+ int clen;
+ unsigned char *buf;
+ int len;
+ int mode;
+{
+ struct nexus *nexus;
+
+/* Get the nexus struct. */
+ nexus = sfas_arbitate_target(dev, pendp->xs->sc_link->target);
+ if (nexus == NULL)
+ return(0);
+
+/* Setup the nexus struct. */
+ sfas_setup_nexus(dev, nexus, pendp, cbuf, clen, buf, len, mode);
+
+/* Post it to the interrupt machine. */
+ sfas_select_unit(dev, pendp->xs->sc_link->target);
+
+ return(1);
+}
+
+void
+sfas_request_sense(dev, nexus)
+ struct sfas_softc *dev;
+ struct nexus *nexus;
+{
+ struct scsi_xfer *xs;
+ struct sfas_pending pend;
+ struct scsi_sense rqs;
+ int mode;
+
+ xs = nexus->xs;
+
+/* Fake a sfas_pending structure. */
+ pend.xs = xs;
+
+ rqs.opcode = REQUEST_SENSE;
+ rqs.byte2 = xs->sc_link->lun << 5;
+#ifdef not_yet
+ rqs.length=xs->req_sense_length?xs->req_sense_length:sizeof(xs->sense);
+#else
+ rqs.length=sizeof(xs->sense);
+#endif
+
+ rqs.unused[0] = rqs.unused[1] = rqs.control = 0;
+
+/*
+ * If we are requesting sense during polled IO, we have to sense with polled
+ * IO too.
+ */
+ mode = SFAS_SELECT_RS;
+ if (nexus->flags & SFAS_NF_IMMEDIATE)
+ mode = SFAS_SELECT_I;
+
+/* Setup the nexus struct for sensing. */
+ sfas_setup_nexus(dev, nexus, &pend, (char *)&rqs, sizeof(rqs),
+ (char *)&xs->sense, rqs.length, mode);
+
+/* Post it to the interrupt machine. */
+ sfas_select_unit(dev, xs->sc_link->target);
+}
+
+void
+sfasgo(dev, pendp)
+ struct sfas_softc *dev;
+ struct sfas_pending *pendp;
+{
+ int s;
+ char *buf;
+
+ buf = pendp->xs->data;
+
+ if (sfasselect(dev, pendp, (char *)pendp->xs->cmd, pendp->xs->cmdlen,
+ buf, pendp->xs->datalen, SFAS_SELECT_RS)) {
+ /*
+ * We got the command going so the sfas_pending struct is now
+ * free to reuse.
+ */
+
+ s = splbio();
+ TAILQ_INSERT_TAIL(&dev->sc_xs_free, pendp, link);
+ splx(s);
+ } else {
+ /*
+ * We couldn't make the command fly so we have to wait. The
+ * struct MUST be inserted at the head to keep the order of
+ * the commands.
+ */
+
+ s = splbio();
+ TAILQ_INSERT_HEAD(&dev->sc_xs_pending, pendp, link);
+ splx(s);
+ }
+
+ return;
+}
+
+/*
+ * Part one of the interrupt machine. Error checks and reselection test.
+ * We don't know if we have an active nexus here!
+ */
+int
+sfas_pretests(dev, rp)
+ struct sfas_softc *dev;
+ sfas_regmap_p rp;
+{
+ struct nexus *nexus;
+ int i, s;
+
+ if (dev->sc_interrupt & SFAS_INT_SCSI_RESET_DETECTED) {
+ /*
+ * Cleanup and notify user. Lets hope that this is all we
+ * have to do
+ */
+
+ for(i=0; i<8; i++) {
+ if (dev->sc_nexus[i].xs)
+ sfas_scsidone(dev, dev->sc_nexus[i].xs, -2);
+
+ sfas_init_nexus(dev, &dev->sc_nexus[i]);
+ }
+ printf("sfasintr: SCSI-RESET detected!");
+ return(-1);
+ }
+
+ if (dev->sc_interrupt & SFAS_INT_ILLEGAL_COMMAND) {
+ /* Something went terrible wrong! Dump some data and panic! */
+
+ printf("FIFO:");
+ while(*rp->sfas_fifo_flags & SFAS_FIFO_COUNT_MASK)
+ printf(" %x", *rp->sfas_fifo);
+ printf("\n");
+
+ printf("CMD: %x\n", *rp->sfas_command);
+ panic("sfasintr: ILLEGAL COMMAND!");
+ }
+
+ if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
+ /* We were reselected. Set the chip as busy */
+
+ s = splbio();
+ dev->sc_flags |= SFAS_ACTIVE;
+ if (dev->sc_sel_nexus) {
+ dev->sc_sel_nexus->flags |= SFAS_NF_SELECT_ME;
+ dev->sc_sel_nexus = 0;
+ }
+ splx(s);
+
+ if (dev->sc_units_disconnected) {
+ /* Find out who reselected us. */
+
+ dev->sc_resel[0] &= ~(1<<dev->sc_host_id);
+
+ for(i=0; i<8; i++)
+ if (dev->sc_resel[0] & (1<<i))
+ break;
+
+ if (i == 8)
+ panic("Illegal reselection!");
+
+ if (dev->sc_nexus[i].state == SFAS_NS_DISCONNECTED) {
+ /*
+ * This unit had disconnected, so we reconnect
+ * it.
+ */
+
+ dev->sc_cur_nexus = &dev->sc_nexus[i];
+ nexus = dev->sc_cur_nexus;
+
+ *rp->sfas_syncper = nexus->syncper;
+ *rp->sfas_syncoff = nexus->syncoff;
+ *rp->sfas_config3 = nexus->config3;
+
+ *rp->sfas_dest_id = i & 7;
+
+ dev->sc_units_disconnected--;
+ dev->sc_msg_in_len= 0;
+
+ /* Restore active pointers. */
+ sfas_restore_pointers(dev);
+
+ nexus->state = SFAS_NS_RESELECTED;
+
+ *rp->sfas_command = SFAS_CMD_MESSAGE_ACCEPTED;
+
+ return(1);
+ }
+ }
+
+ /* Somehow we got an illegal reselection. Dump and panic. */
+ printf("sfasintr: resel[0] %x resel[1] %x disconnected %d\n",
+ dev->sc_resel[0], dev->sc_resel[1],
+ dev->sc_units_disconnected);
+ panic("sfasintr: Unexpected reselection!");
+ }
+
+ return(0);
+}
+
+/*
+ * Part two of the interrupt machine. Handle disconnection and post command
+ * processing. We know that we have an active nexus here.
+ */
+int
+sfas_midaction(dev, rp, nexus)
+ struct sfas_softc *dev;
+ sfas_regmap_p rp;
+ struct nexus *nexus;
+{
+ int i, left, len, s;
+ u_char status, msg;
+
+ if (dev->sc_interrupt & SFAS_INT_DISCONNECT) {
+ s = splbio();
+ dev->sc_cur_nexus = 0;
+
+ /* Mark chip as busy and clean up the chip FIFO. */
+ dev->sc_flags &= ~SFAS_ACTIVE;
+ *rp->sfas_command = SFAS_CMD_FLUSH_FIFO;
+
+ /* Let the nexus state reflect what we have to do. */
+ switch(nexus->state) {
+ case SFAS_NS_SELECTED:
+ dev->sc_sel_nexus = 0;
+ nexus->flags &= ~SFAS_NF_SELECT_ME;
+
+ /*
+ * We were trying to select the unit. Probably no unit
+ * at this ID.
+ */
+ nexus->xs->resid = dev->sc_len;
+
+ nexus->status = -2;
+ nexus->flags &= ~SFAS_NF_UNIT_BUSY;
+ nexus->state = SFAS_NS_FINISHED;
+ break;
+
+ case SFAS_NS_SENSE:
+ /*
+ * Oops! We have to request sense data from this unit.
+ * Do so.
+ */
+ dev->sc_led(dev, 0);
+ nexus->flags |= SFAS_NF_REQUEST_SENSE;
+ sfas_request_sense(dev, nexus);
+ break;
+
+ case SFAS_NS_DONE:
+ /* All done. */
+ nexus->xs->resid = dev->sc_len;
+
+ nexus->flags &= ~SFAS_NF_UNIT_BUSY;
+ nexus->state = SFAS_NS_FINISHED;
+ dev->sc_led(dev, 0);
+ break;
+
+ case SFAS_NS_DISCONNECTING:
+ /*
+ * We have recieved a DISCONNECT message, so we are
+ * doing a normal disconnection.
+ */
+ nexus->state = SFAS_NS_DISCONNECTED;
+
+ dev->sc_units_disconnected++;
+ break;
+
+ case SFAS_NS_RESET:
+ /*
+ * We were reseting this SCSI-unit. Clean up the
+ * nexus struct.
+ */
+ dev->sc_led(dev, 0);
+ sfas_init_nexus(dev, nexus);
+ break;
+
+ default:
+ /*
+ * Unexpected disconnection! Cleanup and exit. This
+ * shouldn't cause any problems.
+ */
+ printf("sfasintr: Unexpected disconnection\n");
+ printf("sfasintr: u %x s %d p %d f %x c %x\n",
+ nexus->lun_unit, nexus->state,
+ dev->sc_status & SFAS_STAT_PHASE_MASK,
+ nexus->flags, nexus->cbuf[0]);
+
+ nexus->xs->resid = dev->sc_len;
+
+ nexus->flags &= ~SFAS_NF_UNIT_BUSY;
+ nexus->state = SFAS_NS_FINISHED;
+ nexus->status = -3;
+
+ dev->sc_led(dev, 0);
+ break;
+ }
+
+ /*
+ * If we have disconnected units, we MUST enable reselection
+ * within 250ms.
+ */
+ if (dev->sc_units_disconnected &&
+ !(dev->sc_flags & SFAS_ACTIVE))
+ *rp->sfas_command = SFAS_CMD_ENABLE_RESEL;
+
+ splx(s);
+
+ /* Select the first pre-initialized nexus we find. */
+ for(i=0; i<8; i++)
+ if (dev->sc_nexus[i].flags & SFAS_NF_SELECT_ME)
+ if (sfas_select_unit(dev, i) == 2)
+ break;
+
+ /* Does any unit need sense data? */
+ for(i=0; i<8; i++)
+ if (dev->sc_nexus[i].flags & SFAS_NF_REQUEST_SENSE) {
+ sfas_request_sense(dev, &dev->sc_nexus[i]);
+ break;
+ }
+
+ /* We are done with this nexus! */
+ if (nexus->state == SFAS_NS_FINISHED)
+ sfas_scsidone(dev, nexus->xs, nexus->status);
+
+ return(1);
+ }
+
+ switch(nexus->state) {
+ case SFAS_NS_SELECTED:
+ dev->sc_cur_nexus = nexus;
+ dev->sc_sel_nexus = 0;
+
+ nexus->flags &= ~SFAS_NF_SELECT_ME;
+
+ /*
+ * We have selected a unit. Setup chip, restore pointers and
+ * light the led.
+ */
+ *rp->sfas_syncper = nexus->syncper;
+ *rp->sfas_syncoff = nexus->syncoff;
+ *rp->sfas_config3 = nexus->config3;
+
+ sfas_restore_pointers(dev);
+
+ if (!(nexus->flags & SFAS_NF_SENSING))
+ nexus->status = 0xFF;
+ dev->sc_msg_in[0] = 0xFF;
+ dev->sc_msg_in_len= 0;
+
+ dev->sc_led(dev, 1);
+
+ break;
+
+ case SFAS_NS_DATA_IN:
+ case SFAS_NS_DATA_OUT:
+ /* We have transfered data. */
+ if (dev->sc_dma_len)
+ if (dev->sc_cur_link < dev->sc_max_link) {
+ /*
+ * Clean up dma and at the same time get how
+ * many bytes that were NOT transfered.
+ */
+ left = dev->sc_setup_dma(dev, 0, 0, SFAS_DMA_CLEAR);
+ len = dev->sc_dma_len;
+
+ if (nexus->state == SFAS_NS_DATA_IN) {
+ /*
+ * If we were bumping we may have had an odd length
+ * which means that there may be bytes left in the
+ * fifo. We also need to move the data from the
+ * bump buffer to the actual memory.
+ */
+ if (dev->sc_dma_buf == dev->sc_bump_pa)
+ {
+ while((*rp->sfas_fifo_flags&SFAS_FIFO_COUNT_MASK)
+ && left)
+ dev->sc_bump_va[len-(left--)] = *rp->sfas_fifo;
+
+ bcopy(dev->sc_bump_va, dev->sc_buf, len-left);
+ }
+ } else {
+ /* Count any unsent bytes and flush them. */
+ left+= *rp->sfas_fifo_flags & SFAS_FIFO_COUNT_MASK;
+ *rp->sfas_command = SFAS_CMD_FLUSH_FIFO;
+ }
+
+ /*
+ * Update pointers/length to reflect the transfered
+ * data.
+ */
+ dev->sc_len -= len-left;
+ dev->sc_buf += len-left;
+
+ dev->sc_dma_buf += len-left;
+ dev->sc_dma_len = left;
+
+ dev->sc_dma_blk_ptr += len-left;
+ dev->sc_dma_blk_len -= len-left;
+
+ /*
+ * If it was the end of a dma block, we select the
+ * next to begin with.
+ */
+ if (!dev->sc_dma_blk_len)
+ dev->sc_cur_link++;
+ }
+ break;
+
+ case SFAS_NS_STATUS:
+ /*
+ * If we were not sensing, grab the status byte. If we were
+ * sensing and we got a bad status, let the user know.
+ */
+
+ status = *rp->sfas_fifo;
+ msg = *rp->sfas_fifo;
+
+ if (!(nexus->flags & SFAS_NF_SENSING))
+ nexus->status = status;
+ else if (status != 0)
+ nexus->status = -1;
+
+ /*
+ * Preload the command complete message. Handeled in
+ * sfas_postaction.
+ */
+ dev->sc_msg_in[0] = msg;
+ dev->sc_msg_in_len = 1;
+ nexus->flags |= SFAS_NF_HAS_MSG;
+ break;
+
+ default:
+ break;
+ }
+
+ return(0);
+}
+
+/*
+ * Part three of the interrupt machine. Handle phase changes (and repeated
+ * phase passes). We know that we have an active nexus here.
+ */
+int
+sfas_postaction(dev, rp, nexus)
+ struct sfas_softc *dev;
+ sfas_regmap_p rp;
+ struct nexus *nexus;
+{
+ int i, len;
+ u_char cmd;
+ short offset, period;
+
+ cmd = 0;
+
+ switch(dev->sc_status & SFAS_STAT_PHASE_MASK) {
+ case SFAS_PHASE_DATA_OUT:
+ case SFAS_PHASE_DATA_IN:
+ if ((dev->sc_status & SFAS_STAT_PHASE_MASK) ==
+ SFAS_PHASE_DATA_OUT)
+ nexus->state = SFAS_NS_DATA_OUT;
+ else
+ nexus->state = SFAS_NS_DATA_IN;
+
+ /* Make DMA ready to accept new data. Load active pointers
+ * from the DMA block. */
+ dev->sc_setup_dma(dev, 0, 0, SFAS_DMA_CLEAR);
+ if (dev->sc_cur_link < dev->sc_max_link) {
+ if (!dev->sc_dma_blk_len) {
+ dev->sc_dma_blk_ptr = dev->sc_chain[dev->sc_cur_link].ptr;
+ dev->sc_dma_blk_len = dev->sc_chain[dev->sc_cur_link].len;
+ dev->sc_dma_blk_flg = dev->sc_chain[dev->sc_cur_link].flg;
+ }
+
+ /* We should use polled IO here. */
+ if (dev->sc_dma_blk_flg == SFAS_CHAIN_PRG) {
+ sfas_ixfer(dev, nexus->xs->flags & SCSI_POLL);
+ dev->sc_cur_link++;
+ dev->sc_dma_len = 0;
+ break;
+ }
+ else if (dev->sc_dma_blk_flg == SFAS_CHAIN_BUMP)
+ len = dev->sc_dma_blk_len;
+ else
+ len = dev->sc_need_bump(dev, dev->sc_dma_blk_ptr,
+ dev->sc_dma_blk_len);
+
+ /*
+ * If len != 0 we must bump the data, else we just DMA it
+ * straight into memory.
+ */
+ if (len) {
+ dev->sc_dma_buf = dev->sc_bump_pa;
+ dev->sc_dma_len = len;
+
+ if (nexus->state == SFAS_NS_DATA_OUT)
+ bcopy(dev->sc_buf, dev->sc_bump_va, dev->sc_dma_len);
+ } else {
+ dev->sc_dma_buf = dev->sc_dma_blk_ptr;
+ dev->sc_dma_len = dev->sc_dma_blk_len;
+ }
+
+ /* Load DMA with adress and length of transfer. */
+ dev->sc_setup_dma(dev, dev->sc_dma_buf, dev->sc_dma_len,
+ ((nexus->state == SFAS_NS_DATA_OUT) ?
+ SFAS_DMA_WRITE : SFAS_DMA_READ));
+
+ printf("Using DMA !!!!\n");
+ cmd = SFAS_CMD_TRANSFER_INFO | SFAS_CMD_DMA;
+ } else {
+ /*
+ * Hmmm, the unit wants more info than we have or has
+ * more than we want. Let the chip handle that.
+ */
+
+ *rp->sfas_tc_low = 0; /* was 256 but this does not make sense */
+ *rp->sfas_tc_mid = 1;
+ *rp->sfas_tc_high = 0;
+ cmd = SFAS_CMD_TRANSFER_PAD;
+ }
+ break;
+
+ case SFAS_PHASE_COMMAND:
+ /* The scsi unit wants the command, send it. */
+ nexus->state = SFAS_NS_SVC;
+
+ *rp->sfas_command = SFAS_CMD_FLUSH_FIFO;
+ for(i=0; i<5; i++);
+
+ for(i=0; i<nexus->clen; i++)
+ *rp->sfas_fifo = nexus->cbuf[i];
+ cmd = SFAS_CMD_TRANSFER_INFO;
+ break;
+
+ case SFAS_PHASE_STATUS:
+ /*
+ * We've got status phase. Request status and command
+ * complete message.
+ */
+ nexus->state = SFAS_NS_STATUS;
+ cmd = SFAS_CMD_COMMAND_COMPLETE;
+ break;
+
+ case SFAS_PHASE_MESSAGE_OUT:
+ /*
+ * Either the scsi unit wants us to send a message or we have
+ * asked for it by seting the ATN bit.
+ */
+ nexus->state = SFAS_NS_MSG_OUT;
+
+ *rp->sfas_command = SFAS_CMD_FLUSH_FIFO;
+
+ if (nexus->flags & SFAS_NF_DO_SDTR) {
+ /* Send a Synchronous Data Transfer Request. */
+
+ sfas_build_sdtrm(dev, nexus->period, nexus->offset);
+ nexus->flags |= SFAS_NF_SDTR_SENT;
+ nexus->flags &= ~SFAS_NF_DO_SDTR;
+ } else if (nexus->flags & SFAS_NF_RESET) {
+ /* Send a reset scsi unit message. */
+
+ dev->sc_msg_out[0] = 0x0C;
+ dev->sc_msg_out_len = 1;
+ nexus->state = SFAS_NS_RESET;
+ nexus->flags &= ~SFAS_NF_RESET;
+ } else if (dev->sc_msg_out_len == 0) {
+ /* Don't know what to send so we send a NOP message. */
+
+ dev->sc_msg_out[0] = 0x08;
+ dev->sc_msg_out_len = 1;
+ }
+
+ cmd = SFAS_CMD_TRANSFER_INFO;
+
+ for(i=0; i<dev->sc_msg_out_len; i++)
+ *rp->sfas_fifo = dev->sc_msg_out[i];
+ dev->sc_msg_out_len = 0;
+
+ break;
+
+ case SFAS_PHASE_MESSAGE_IN:
+ /* Receive a message from the scsi unit. */
+ nexus->state = SFAS_NS_MSG_IN;
+
+ while(!(nexus->flags & SFAS_NF_HAS_MSG)) {
+ *rp->sfas_command = SFAS_CMD_TRANSFER_INFO;
+ sfasiwait(dev);
+
+ dev->sc_msg_in[dev->sc_msg_in_len++] = *rp->sfas_fifo;
+
+ /* Check if we got all the bytes in the message. */
+ if (dev->sc_msg_in[0] >= 0x80) ;
+ else if (dev->sc_msg_in[0] >= 0x30) ;
+ else if (((dev->sc_msg_in[0] >= 0x20) &&
+ (dev->sc_msg_in_len == 2)) ||
+ ((dev->sc_msg_in[0] != 0x01) &&
+ (dev->sc_msg_in_len == 1))) {
+ nexus->flags |= SFAS_NF_HAS_MSG;
+ break;
+ } else {
+ if (dev->sc_msg_in_len >= 2)
+ if ((dev->sc_msg_in[1]+2) == dev->sc_msg_in_len) {
+ nexus->flags |= SFAS_NF_HAS_MSG;
+ break;
+ }
+ }
+
+ *rp->sfas_command = SFAS_CMD_MESSAGE_ACCEPTED;
+ sfasiwait(dev);
+
+ if ((dev->sc_status & SFAS_STAT_PHASE_MASK) !=
+ SFAS_PHASE_MESSAGE_IN)
+ break;
+ }
+
+ cmd = SFAS_CMD_MESSAGE_ACCEPTED;
+ if (nexus->flags & SFAS_NF_HAS_MSG) {
+ /* We have a message. Decode it. */
+
+ switch(dev->sc_msg_in[0]) {
+ case 0x00: /* COMMAND COMPLETE */
+ if ((nexus->status == SCSI_CHECK) &&
+ !(nexus->flags & SFAS_NF_SENSING))
+ nexus->state = SFAS_NS_SENSE;
+ else
+ nexus->state = SFAS_NS_DONE;
+ break;
+ case 0x04: /* DISCONNECT */
+ nexus->state = SFAS_NS_DISCONNECTING;
+ break;
+ case 0x02: /* SAVE DATA POINTER */
+ sfas_save_pointers(dev);
+ break;
+ case 0x03: /* RESTORE DATA POINTERS */
+ sfas_restore_pointers(dev);
+ break;
+ case 0x07: /* MESSAGE REJECT */
+ /*
+ * If we had sent a SDTR and we got a message
+ * reject, the scsi docs say that we must go
+ * to async transfer.
+ */
+ if (nexus->flags & SFAS_NF_SDTR_SENT) {
+ nexus->flags &= ~SFAS_NF_SDTR_SENT;
+
+ nexus->config3 &= ~SFAS_CFG3_FASTSCSI;
+ nexus->syncper = 5;
+ nexus->syncoff = 0;
+
+ *rp->sfas_syncper = nexus->syncper;
+ *rp->sfas_syncoff = nexus->syncoff;
+ *rp->sfas_config3 = nexus->config3;
+ } else
+ /*
+ * Something was rejected but we don't know
+ * what! PANIC!
+ */
+ panic("sfasintr: Unknown message rejected!");
+ break;
+ case 0x08: /* MO OPERATION */
+ break;
+ case 0x01: /* EXTENDED MESSAGE */
+ switch(dev->sc_msg_in[2]) {
+ case 0x01:/* SYNC. DATA TRANSFER REQUEST */
+ /* Decode the SDTR message. */
+ period = 4*dev->sc_msg_in[3];
+ offset = dev->sc_msg_in[4];
+
+ /*
+ * Make sure that the specs are within
+ * chip limits. Note that if we
+ * initiated the negotiation the specs
+ * WILL be withing chip limits. If it
+ * was the scsi unit that initiated
+ * the negotiation, the specs may be
+ * to high.
+ */
+ if (offset > 16)
+ offset = 16;
+ if ((period < 200) &&
+ (dev->sc_clock_freq <= 25))
+ period = 200;
+
+ if (offset == 0)
+ period = 5*dev->sc_clock_period;
+
+ nexus->syncper = period/
+ dev->sc_clock_period;
+ nexus->syncoff = offset;
+
+ if (period < 200)
+ nexus->config3 |= SFAS_CFG3_FASTSCSI;
+ else
+ nexus->config3 &=~SFAS_CFG3_FASTSCSI;
+
+ nexus->flags |= SFAS_NF_SYNC_TESTED;
+
+ *rp->sfas_syncper = nexus->syncper;
+ *rp->sfas_syncoff = nexus->syncoff;
+ *rp->sfas_config3 = nexus->config3;
+
+ /*
+ * Hmmm, it seems that the scsi unit
+ * initiated sync negotiation, so lets
+ * reply acording to scsi-2 standard.
+ */
+ if (!(nexus->flags& SFAS_NF_SDTR_SENT))
+ {
+ if ((dev->sc_config_flags &
+ SFAS_NO_SYNCH) ||
+ (dev->sc_config_flags &
+ SFAS_NO_DMA) ||
+ sfas_inhibit_sync[
+ nexus->lun_unit & 7]) {
+ period = 200;
+ offset = 0;
+ }
+
+ nexus->offset = offset;
+ nexus->period = period;
+ nexus->flags |= SFAS_NF_DO_SDTR;
+ *rp->sfas_command = SFAS_CMD_SET_ATN;
+ }
+
+ nexus->flags &= ~SFAS_NF_SDTR_SENT;
+ break;
+
+ case 0x00: /* MODIFY DATA POINTERS */
+ case 0x02: /* EXTENDED IDENTIFY (SCSI-1) */
+ case 0x03: /* WIDE DATA TRANSFER REQUEST */
+ default:
+ /* Reject any unhandeled messages. */
+
+ dev->sc_msg_out[0] = 0x07;
+ dev->sc_msg_out_len = 1;
+ *rp->sfas_command = SFAS_CMD_SET_ATN;
+ cmd = SFAS_CMD_MESSAGE_ACCEPTED;
+ break;
+ }
+ break;
+
+ default:
+ /* Reject any unhandeled messages. */
+
+ dev->sc_msg_out[0] = 0x07;
+ dev->sc_msg_out_len = 1;
+ *rp->sfas_command = SFAS_CMD_SET_ATN;
+ cmd = SFAS_CMD_MESSAGE_ACCEPTED;
+ break;
+ }
+ nexus->flags &= ~SFAS_NF_HAS_MSG;
+ dev->sc_msg_in_len = 0;
+ }
+ break;
+ default:
+ printf("SFASINTR: UNKNOWN PHASE! phase: %d\n",
+ dev->sc_status & SFAS_STAT_PHASE_MASK);
+ dev->sc_led(dev, 0);
+ sfas_scsidone(dev, nexus->xs, -4);
+
+ return(-1);
+ }
+
+ if (cmd)
+ *rp->sfas_command = cmd;
+
+ return(0);
+}
+
+/*
+ * Stub for interrupt machine.
+ */
+void
+sfasintr(dev)
+ struct sfas_softc *dev;
+{
+ sfas_regmap_p rp;
+ struct nexus *nexus;
+
+ rp = dev->sc_fas;
+
+ if (!sfas_pretests(dev, rp)) {
+
+ nexus = dev->sc_cur_nexus;
+ if (nexus == NULL)
+ nexus = dev->sc_sel_nexus;
+
+ if (nexus)
+ if (!sfas_midaction(dev, rp, nexus))
+ sfas_postaction(dev, rp, nexus);
+ }
+}
+
+/*
+ * sfasicmd is used to perform IO when we can't use interrupts. sfasicmd
+ * emulates the normal environment by waiting for the chip and calling
+ * sfasintr.
+ */
+void
+sfasicmd(dev, pendp)
+ struct sfas_softc *dev;
+ struct sfas_pending *pendp;
+{
+ sfas_regmap_p rp;
+ struct nexus *nexus;
+
+ nexus = &dev->sc_nexus[pendp->xs->sc_link->target];
+ rp = dev->sc_fas;
+
+ if (!sfasselect(dev, pendp, (char *)pendp->xs->cmd, pendp->xs->cmdlen,
+ (char *)pendp->xs->data, pendp->xs->datalen,
+ SFAS_SELECT_I))
+ panic("sfasicmd: Couldn't select unit");
+
+ while(nexus->state != SFAS_NS_FINISHED) {
+ sfasiwait(dev);
+ sfasintr(dev);
+ }
+
+ nexus->flags &= ~SFAS_NF_SYNC_TESTED;
+}
--- /dev/null
+/* $NetBSD: sfasreg.h,v 1.1 1996/01/31 23:26:45 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Daniel Widenfalk
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Daniel Widenfalk
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SFASREG_H_
+#define _SFASREG_H_
+
+/*
+ * Emulex FAS216 SCSI interface hardware description.
+ */
+
+typedef volatile unsigned char vu_char;
+
+typedef struct {
+ vu_char *sfas_tc_low; /* rw: Transfer count low */
+ vu_char *sfas_tc_mid; /* rw: Transfer count mid */
+ vu_char *sfas_fifo; /* rw: Data FIFO */
+ vu_char *sfas_command; /* rw: Chip command reg */
+ vu_char *sfas_dest_id; /* w: (Re)select bus ID */
+#define sfas_status sfas_dest_id /* r: Status */
+ vu_char *sfas_timeout; /* w: (Re)select timeout */
+#define sfas_interrupt sfas_timeout /* r: Interrupt */
+ vu_char *sfas_syncper; /* w: Synch. transfer period */
+#define sfas_seqstep sfas_syncper /* r: Sequence step */
+ vu_char *sfas_syncoff; /* w: Synch. transfer offset */
+#define sfas_fifo_flags sfas_syncoff /* r: FIFO flags */
+ vu_char *sfas_config1; /* rw: Config register #1 */
+ vu_char *sfas_clkconv; /* w: Clock conv. factor */
+ vu_char *sfas_test; /* w: Test register */
+ vu_char *sfas_config2; /* rw: Config register #2 */
+ vu_char *sfas_config3; /* rw: Config register #3 */
+ vu_char *sfas_tc_high; /* rw: Transfer count high */
+ vu_char *sfas_fifo_bot; /* w: FIFO bottom register */
+} sfas_regmap_t;
+typedef sfas_regmap_t *sfas_regmap_p;
+
+/* Commands for the FAS216 */
+#define SFAS_CMD_DMA 0x80
+
+#define SFAS_CMD_SEL_NO_ATN 0x41
+#define SFAS_CMD_SEL_ATN 0x42
+#define SFAS_CMD_SEL_ATN3 0x46
+#define SFAS_CMD_SEL_ATN_STOP 0x43
+
+#define SFAS_CMD_ENABLE_RESEL 0x44
+#define SFAS_CMD_DISABLE_RESEL 0x45
+
+#define SFAS_CMD_TRANSFER_INFO 0x10
+#define SFAS_CMD_TRANSFER_PAD 0x98
+
+#define SFAS_CMD_COMMAND_COMPLETE 0x11
+#define SFAS_CMD_MESSAGE_ACCEPTED 0x12
+
+#define SFAS_CMD_SET_ATN 0x1A
+#define SFAS_CMD_RESET_ATN 0x1B
+
+#define SFAS_CMD_NOP 0x00
+#define SFAS_CMD_FLUSH_FIFO 0x01
+#define SFAS_CMD_RESET_CHIP 0x02
+#define SFAS_CMD_RESET_SCSI_BUS 0x03
+
+#define SFAS_STAT_PHASE_MASK 0x07
+#define SFAS_STAT_PHASE_TRANS_CPLT 0x08
+#define SFAS_STAT_TRANSFER_COUNT_ZERO 0x10
+#define SFAS_STAT_PARITY_ERROR 0x20
+#define SFAS_STAT_GROSS_ERROR 0x40
+#define SFAS_STAT_INTERRUPT_PENDING 0x80
+
+#define SFAS_PHASE_DATA_OUT 0
+#define SFAS_PHASE_DATA_IN 1
+#define SFAS_PHASE_COMMAND 2
+#define SFAS_PHASE_STATUS 3
+#define SFAS_PHASE_MESSAGE_OUT 6
+#define SFAS_PHASE_MESSAGE_IN 7
+
+#define SFAS_DEST_ID_MASK 0x07
+
+#define SFAS_INT_SELECTED 0x01
+#define SFAS_INT_SELECTED_WITH_ATN 0x02
+#define SFAS_INT_RESELECTED 0x04
+#define SFAS_INT_FUNCTION_COMPLETE 0x08
+#define SFAS_INT_BUS_SERVICE 0x10
+#define SFAS_INT_DISCONNECT 0x20
+#define SFAS_INT_ILLEGAL_COMMAND 0x40
+#define SFAS_INT_SCSI_RESET_DETECTED 0x80
+
+#define SFAS_SYNCHRON_PERIOD_MASK 0x1F
+
+#define SFAS_FIFO_COUNT_MASK 0x1F
+#define SFAS_FIFO_SEQUENCE_STEP_MASK 0xE0
+#define SFAS_FIFO_SEQUENCE_SHIFT 5
+
+#define SFAS_SYNCHRON_OFFSET_MASK 0x0F
+#define SFAS_SYNC_ASSERT_MASK 0x30
+#define SFAS_SYNC_ASSERT_SHIFT 4
+#define SFAS_SYNC_DEASSERT_MASK 0x30
+#define SFAS_SYNC_DEASSERT_SHIFT 6
+
+#define SFAS_CFG1_BUS_ID_MASK 0x07
+#define SFAS_CFG1_CHIP_TEST_MODE 0x08
+#define SFAS_CFG1_SCSI_PARITY_ENABLE 0x10
+#define SFAS_CFG1_PARITY_TEST_MODE 0x20
+#define SFAS_CFG1_SCSI_RES_INT_DIS 0x40
+#define SFAS_CFG1_SLOW_CABLE_MODE 0x80
+
+#define SFAS_CLOCK_CONVERSION_MASK 0x07
+
+#define SFAS_TEST_TARGET_TEST_MODE 0x01
+#define SFAS_TEST_INITIATOR_TEST_MODE 0x02
+#define SFAS_TEST_TRISTATE_TEST_MODE 0x04
+
+#define SFAS_CFG2_DMA_PARITY_ENABLE 0x01
+#define SFAS_CFG2_REG_PARITY_ENABLE 0x02
+#define SFAS_CFG2_TARG_BAD_PARITY_ABORT 0x04
+#define SFAS_CFG2_SCSI_2_MODE 0x08
+#define SFAS_CFG2_TRISTATE_DMA_REQ 0x10
+#define SFAS_CFG2_BYTE_CONTROL_MODE 0x20
+#define SFAS_CFG2_FEATURES_ENABLE 0x40
+#define SFAS_CFG2_RESERVE_FIFO_BYTE 0x80
+
+#define SFAS_CFG3_THRESHOLD_8_MODE 0x01
+#define SFAS_CFG3_ALTERNATE_DMA_MODE 0x02
+#define SFAS_CFG3_SAVE_RESIDUAL_BYTE 0x04
+#define SFAS_CFG3_FASTCLK 0x08
+#define SFAS_CFG3_FASTSCSI 0x10
+#define SFAS_CFG3_CDB10 0x20
+#define SFAS_CFG3_QENB 0x40
+#define SFAS_CFG3_IDRESCHK 0x80
+
+#endif
--- /dev/null
+/* $NetBSD: sfasvar.h,v 1.1 1996/01/31 23:26:49 mark Exp $ */
+
+/*
+ * Copyright (c) 1995 Daniel Widenfalk
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Daniel Widenfalk
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SFASVAR_H_
+#define _SFASVAR_H_
+
+#ifndef _SFASREG_H_
+#include <arm32/podulebus/sfasreg.h>
+#endif
+
+/*
+ * MAXCHAIN is the anticipated maximum number of chain blocks needed. This
+ * assumes that we are NEVER requested to transfer more than MAXPHYS bytes.
+ */
+#define MAXCHAIN (MAXPHYS/NBPG+2)
+
+/*
+ * Maximum number of requests standing by. Could be anything, but I think 9
+ * looks nice :-) NOTE: This does NOT include requests already started!
+ */
+#define MAXPENDING 9 /* 7 IDs + 2 extra */
+
+/*
+ * DMA chain block. If flg == SFAS_CHAIN_PRG or flg == SFAS_CHAIN_BUMP then
+ * ptr is a VIRTUAL adress. If flg == SFAS_CHAIN_DMA then ptr is a PHYSICAL
+ * adress.
+ */
+struct sfas_dma_chain {
+ vm_offset_t ptr;
+ u_short len;
+ short flg;
+};
+#define SFAS_CHAIN_DMA 0x00
+#define SFAS_CHAIN_BUMP 0x01
+#define SFAS_CHAIN_PRG 0x02
+
+
+/*
+ * This struct contains the necessary info for a pending request. Pointer to
+ * a scsi_xfer struct.
+ */
+struct sfas_pending {
+ TAILQ_ENTRY(sfas_pending) link;
+ struct scsi_xfer *xs;
+};
+
+/*
+ * nexus contains all active data for one SCSI unit. Parts of the info in this
+ * struct survives between scsi commands.
+ */
+struct nexus {
+ struct scsi_xfer *xs; /* Pointer to request */
+
+ u_char ID; /* ID message to be sent */
+ u_char clen; /* scsi command length + */
+ u_char cbuf[14]; /* the actual command bytes */
+
+ struct sfas_dma_chain dma[MAXCHAIN]; /* DMA chain blocks */
+ short max_link; /* Maximum used of above */
+ short cur_link; /* Currently handled block */
+
+ u_char *buf; /* Virtual adress of data */
+ int len; /* Bytes left to transfer */
+
+ vm_offset_t dma_buf; /* Current DMA adress */
+ int dma_len; /* Current DMA length */
+
+ vm_offset_t dma_blk_ptr; /* Current chain adress */
+ int dma_blk_len; /* Current chain length */
+ u_char dma_blk_flg; /* Current chain flags */
+
+ u_char state; /* Nexus state, see below */
+ u_short flags; /* Nexus flags, see below */
+
+ short period; /* Sync period to request */
+ u_char offset; /* Sync offset to request */
+
+ u_char syncper; /* FAS216 variable storage */
+ u_char syncoff; /* FAS216 variable storage */
+ u_char config3; /* FAS216 variable storage */
+
+ u_char lun_unit; /* (Lun<<4) | Unit of nexus */
+ u_char status; /* Status byte from unit*/
+
+};
+
+/* SCSI nexus_states */
+#define SFAS_NS_IDLE 0 /* Nexus idle */
+#define SFAS_NS_SELECTED 1 /* Last command was a SELECT command */
+#define SFAS_NS_DATA_IN 2 /* Last command was a TRANSFER_INFO */
+ /* command during a data in phase */
+#define SFAS_NS_DATA_OUT 3 /* Last command was a TRANSFER_INFO */
+ /* command during a data out phase */
+#define SFAS_NS_STATUS 4 /* We have send a COMMAND_COMPLETE */
+ /* command and are awaiting status */
+#define SFAS_NS_MSG_IN 5 /* Last phase was MESSAGE IN */
+#define SFAS_NS_MSG_OUT 6 /* Last phase was MESSAGE OUT */
+#define SFAS_NS_SVC 7 /* We have sent the command */
+#define SFAS_NS_DISCONNECTING 8 /* We have recieved a disconnect msg */
+#define SFAS_NS_DISCONNECTED 9 /* We are disconnected */
+#define SFAS_NS_RESELECTED 10 /* We was reselected */
+#define SFAS_NS_DONE 11 /* Done. Prephsase to FINISHED */
+#define SFAS_NS_FINISHED 12 /* Realy done. Call scsi_done */
+#define SFAS_NS_SENSE 13 /* We are requesting sense */
+#define SFAS_NS_RESET 14 /* We are reseting this unit */
+
+/* SCSI nexus flags */
+#define SFAS_NF_UNIT_BUSY 0x0001 /* Unit is not available */
+
+#define SFAS_NF_SELECT_ME 0x0002 /* Nexus is set up, waiting for bus */
+
+#define SFAS_NF_REQUEST_SENSE 0x0004 /* We should request sense */
+#define SFAS_NF_SENSING 0x0008 /* We are sensing */
+
+#define SFAS_NF_HAS_MSG 0x0010 /* We have recieved a complete msg */
+
+#define SFAS_NF_DO_SDTR 0x0020 /* We should send a SDTR */
+#define SFAS_NF_SDTR_SENT 0x0040 /* We have sent a SDTR */
+#define SFAS_NF_SYNC_TESTED 0x0080 /* We have negotiated sync */
+
+#define SFAS_NF_RESET 0x0100 /* Reset this nexus */
+#define SFAS_NF_IMMEDIATE 0x0200 /* We are operating from sfasicmd */
+
+#define SFAS_NF_DEBUG 0x8000 /* As it says: DEBUG */
+
+struct sfas_softc {
+ struct device sc_dev; /* System required struct */
+ struct scsi_link sc_link; /* For sub devices */
+ irqhandler_t sc_ih; /* Interrupt chain struct */
+
+ TAILQ_HEAD(,sfas_pending) sc_xs_pending;
+ TAILQ_HEAD(,sfas_pending) sc_xs_free;
+ struct sfas_pending sc_xs_store[MAXPENDING];
+
+ sfas_regmap_p sc_fas; /* FAS216 Address */
+ void *sc_spec; /* Board-specific data */
+
+ u_char *sc_bump_va; /* Bumpbuf virtual adr */
+ vm_offset_t sc_bump_pa; /* Bumpbuf physical adr */
+ int sc_bump_sz; /* Bumpbuf size */
+
+/* Configuration registers, must be set BEFORE sfasinitialize */
+ u_char sc_clock_freq;
+ u_short sc_timeout;
+ u_char sc_host_id;
+ u_char sc_config_flags;
+
+/* Generic DMA functions */
+ int (*sc_setup_dma)();
+ int (*sc_build_dma_chain)();
+ int (*sc_need_bump)();
+
+/* Generic Led data */
+ int sc_led_status;
+ void (*sc_led)();
+
+/* Nexus list */
+ struct nexus sc_nexus[8];
+ struct nexus *sc_cur_nexus;
+ struct nexus *sc_sel_nexus;
+
+/* Current transfer data */
+ u_char *sc_buf; /* va */
+ int sc_len;
+
+ vm_offset_t sc_dma_buf; /* pa */
+ int sc_dma_len;
+ vm_offset_t sc_dma_blk_ptr;
+ int sc_dma_blk_len;
+ short sc_dma_blk_flg;
+
+ struct sfas_dma_chain *sc_chain; /* Current DMA chain */
+ short sc_max_link;
+ short sc_cur_link;
+
+/* Interrupt registers */
+ u_char sc_status;
+ u_char sc_interrupt;
+ u_char sc_resel[2];
+
+ u_char sc_units_disconnected;
+
+/* Storage for FAS216 config registers (current values) */
+ u_char sc_config1;
+ u_char sc_config2;
+ u_char sc_config3;
+ u_char sc_clock_conv_fact;
+ u_char sc_timeout_val;
+ u_char sc_clock_period;
+
+ u_char sc_msg_in[7];
+ u_char sc_msg_in_len;
+
+ u_char sc_msg_out[7];
+ u_char sc_msg_out_len;
+
+ u_char sc_unit;
+ u_char sc_lun;
+ u_char sc_flags;
+};
+
+#define SFAS_DMA_READ 0
+#define SFAS_DMA_WRITE 1
+#define SFAS_DMA_CLEAR 2
+
+/* sc_flags */
+#define SFAS_ACTIVE 0x01
+#define SFAS_DONT_WAIT 0x02
+
+/* SCSI Selection modes */
+#define SFAS_SELECT 0x00 /* Normal selection: No sync, no resel */
+#define SFAS_SELECT_R 0x01 /* Reselection allowed */
+#define SFAS_SELECT_S 0x02 /* Synchronous transfer allowed */
+#define SFAS_SELECT_I 0x04 /* Selection for sfasicmd */
+#define SFAS_SELECT_K 0x08 /* Send a BUS DEVICE RESET message (Kill) */
+
+/* Nice abbreviations of the above */
+#define SFAS_SELECT_RS (SFAS_SELECT_R|SFAS_SELECT_S)
+#define SFAS_SELECT_RI (SFAS_SELECT_R|SFAS_SELECT_I)
+#define SFAS_SELECT_SI (SFAS_SELECT_S|SFAS_SELECT_I)
+#define SFAS_SELECT_RSI (SFAS_SELECT_R|SFAS_SELECT_S|SFAS_SELECT_I)
+
+/* sc_config_flags */
+#define SFAS_NO_SYNCH 0x01 /* Disable synchronous transfer */
+#define SFAS_NO_DMA 0x02 /* Do not use DMA! EVER! */
+#define SFAS_NO_RESELECT 0x04 /* Do not allow relesection */
+#define SFAS_SLOW_CABLE 0x08 /* Cable is "unsafe" for fast scsi-2 */
+#define SFAS_SLOW_START 0x10 /* There are slow starters on the bus */
+
+void sfasinitialize __P((struct sfas_softc *sc));
+void sfas_minphys __P((struct buf *bp));
+int sfas_scsicmd __P((struct scsi_xfer *));
+
+#endif /* _SFASVAR_H_ */