summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/arc/Makefile28
-rw-r--r--sys/arch/arc/TODO27
-rw-r--r--sys/arch/arc/arc/arctype.h46
-rw-r--r--sys/arch/arc/arc/autoconf.c230
-rw-r--r--sys/arch/arc/arc/clock.c314
-rw-r--r--sys/arch/arc/arc/clock_mc.c216
-rw-r--r--sys/arch/arc/arc/clockvar.h79
-rw-r--r--sys/arch/arc/arc/conf.c330
-rw-r--r--sys/arch/arc/arc/cpu.c188
-rw-r--r--sys/arch/arc/arc/cpu_exec.c104
-rw-r--r--sys/arch/arc/arc/disksubr.c323
-rw-r--r--sys/arch/arc/arc/fp.S3611
-rw-r--r--sys/arch/arc/arc/genassym.c74
-rw-r--r--sys/arch/arc/arc/locore.S2880
-rw-r--r--sys/arch/arc/arc/machdep.c1165
-rw-r--r--sys/arch/arc/arc/mainbus.c173
-rw-r--r--sys/arch/arc/arc/mem.c173
-rw-r--r--sys/arch/arc/arc/minidebug.c1111
-rw-r--r--sys/arch/arc/arc/pmap.c1633
-rw-r--r--sys/arch/arc/arc/process_machdep.c114
-rw-r--r--sys/arch/arc/arc/swapgeneric.c195
-rw-r--r--sys/arch/arc/arc/sys_machdep.c130
-rw-r--r--sys/arch/arc/arc/trap.c1561
-rw-r--r--sys/arch/arc/arc/vm_machdep.c487
-rw-r--r--sys/arch/arc/compile/.cvsignore1
-rw-r--r--sys/arch/arc/compile/.keep_me1
-rw-r--r--sys/arch/arc/conf/GENERIC97
-rw-r--r--sys/arch/arc/conf/Makefile.arc183
-rw-r--r--sys/arch/arc/conf/PICA108
-rw-r--r--sys/arch/arc/conf/files.arc124
-rw-r--r--sys/arch/arc/dev/ace.c1783
-rw-r--r--sys/arch/arc/dev/asc.c2074
-rw-r--r--sys/arch/arc/dev/ascreg.h322
-rw-r--r--sys/arch/arc/dev/dma.c395
-rw-r--r--sys/arch/arc/dev/dma.h151
-rw-r--r--sys/arch/arc/dev/fd.c1139
-rw-r--r--sys/arch/arc/dev/fdreg.h67
-rw-r--r--sys/arch/arc/dev/if_sn.c1300
-rw-r--r--sys/arch/arc/dev/if_sn.h347
-rw-r--r--sys/arch/arc/dev/lpt.c676
-rw-r--r--sys/arch/arc/dev/pccons.c2094
-rw-r--r--sys/arch/arc/dev/scsi.h559
-rw-r--r--sys/arch/arc/include/ansi.h75
-rw-r--r--sys/arch/arc/include/asm.h160
-rw-r--r--sys/arch/arc/include/autoconf.h79
-rw-r--r--sys/arch/arc/include/bus.h132
-rw-r--r--sys/arch/arc/include/cdefs.h39
-rw-r--r--sys/arch/arc/include/cpu.h417
-rw-r--r--sys/arch/arc/include/disklabel.h81
-rw-r--r--sys/arch/arc/include/display.h48
-rw-r--r--sys/arch/arc/include/ecoff.h90
-rw-r--r--sys/arch/arc/include/elf.h138
-rw-r--r--sys/arch/arc/include/endian.h95
-rw-r--r--sys/arch/arc/include/exec.h57
-rw-r--r--sys/arch/arc/include/float.h81
-rw-r--r--sys/arch/arc/include/ieeefp.h25
-rw-r--r--sys/arch/arc/include/intr.h164
-rw-r--r--sys/arch/arc/include/kbdreg.h53
-rw-r--r--sys/arch/arc/include/kcore.h45
-rw-r--r--sys/arch/arc/include/kdbparam.h75
-rw-r--r--sys/arch/arc/include/limits.h101
-rw-r--r--sys/arch/arc/include/mips_opcode.h260
-rw-r--r--sys/arch/arc/include/mouse.h50
-rw-r--r--sys/arch/arc/include/param.h166
-rw-r--r--sys/arch/arc/include/pcb.h61
-rw-r--r--sys/arch/arc/include/pccons.h45
-rw-r--r--sys/arch/arc/include/pio.h46
-rw-r--r--sys/arch/arc/include/pmap.h109
-rw-r--r--sys/arch/arc/include/proc.h54
-rw-r--r--sys/arch/arc/include/profile.h79
-rw-r--r--sys/arch/arc/include/psl.h69
-rw-r--r--sys/arch/arc/include/pte.h134
-rw-r--r--sys/arch/arc/include/ptrace.h45
-rw-r--r--sys/arch/arc/include/reg.h62
-rw-r--r--sys/arch/arc/include/regdef.h74
-rw-r--r--sys/arch/arc/include/regnum.h136
-rw-r--r--sys/arch/arc/include/reloc.h75
-rw-r--r--sys/arch/arc/include/setjmp.h8
-rw-r--r--sys/arch/arc/include/signal.h68
-rw-r--r--sys/arch/arc/include/stdarg.h65
-rw-r--r--sys/arch/arc/include/trap.h68
-rw-r--r--sys/arch/arc/include/types.h82
-rw-r--r--sys/arch/arc/include/varargs.h69
-rw-r--r--sys/arch/arc/include/vmparam.h238
-rw-r--r--sys/arch/arc/isa/isa_machdep.h72
-rw-r--r--sys/arch/arc/isa/isabus.c490
-rw-r--r--sys/arch/arc/isa/isadma.c317
-rw-r--r--sys/arch/arc/isa/isadmareg.h22
-rw-r--r--sys/arch/arc/isa/spkrreg.h11
-rw-r--r--sys/arch/arc/isa/timerreg.h100
-rw-r--r--sys/arch/arc/pica/pica.h168
-rw-r--r--sys/arch/arc/pica/picabus.c323
-rw-r--r--sys/arch/arc/stand/Makefile96
-rw-r--r--sys/arch/arc/stand/boot.c114
-rw-r--r--sys/arch/arc/stand/conf.c70
-rw-r--r--sys/arch/arc/stand/filesystem.c44
-rw-r--r--sys/arch/arc/stand/libsa/Makefile14
-rw-r--r--sys/arch/arc/stand/libsa/devopen.c128
-rw-r--r--sys/arch/arc/stand/libsa/getenv.c45
-rw-r--r--sys/arch/arc/stand/libsa/getputchar.c69
-rw-r--r--sys/arch/arc/stand/rz.c174
-rw-r--r--sys/arch/arc/stand/start.S129
102 files changed, 33017 insertions, 0 deletions
diff --git a/sys/arch/arc/Makefile b/sys/arch/arc/Makefile
new file mode 100644
index 00000000000..d358d6b5abf
--- /dev/null
+++ b/sys/arch/arc/Makefile
@@ -0,0 +1,28 @@
+# from: @(#)Makefile 8.1 (Berkeley) 6/16/93
+# $Id: Makefile,v 1.1 1996/06/24 09:07:17 pefo Exp $
+
+# Makefile for pica links, tags file
+
+.include "../../kern/Make.tags.inc"
+
+all:
+ @echo "make links or tags only"
+
+DIRS= conf dev dist include pica
+
+links::
+ -for i in ${DIRS}; do \
+ (cd $$i && { rm -f tags; ln -s ${SYSTAGS} tags; }) done
+
+PICA= /sys/pica/dev/*.[ch] /sys/pica/include/*.[ch] \
+ /sys/pica/pica/*.[ch] /sys/pica/ultrix/*.[ch]
+APICA= /sys/pica/pica/*.s
+
+tags::
+ -ctags -wdtif ${COMM} ${PICA}
+ egrep "^LEAF(.*)|^[AN]LEAF(.*)|^NON_LEAF(.*)" ${APICA} | \
+ sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+ >> tags
+ sort -o tags tags
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/arc/TODO b/sys/arch/arc/TODO
new file mode 100644
index 00000000000..ce4530ec694
--- /dev/null
+++ b/sys/arch/arc/TODO
@@ -0,0 +1,27 @@
+To do list (not in any particular order).
+
+ o Improve pmap_zero_page and pmap_copy_page. Speed and flushing.
+
+ o Move the RO and WIRED attribute from the pte to the pv table.
+ This saves four instructions in the tlb miss handler.
+InWork: Have a test version. The system hangs after a while. Not solved yet.
+ Also, is it worth the effort to remove 4 instr. in TLB-miss handler?
+
+ o Boot. Standalone boot program instead of booting the kernel directly?
+
+ o Create boot package for distribution.
+
+ o sigsetjmp/siglongjmp missing....
+
+ o Add more videomodes to pccons driver. 50kHz and 64kHz monitors?
+InWork: This seems to be hard. Need more info on the chip.
+
+ o Find out why bitmap load to S3-928 flashes screen.
+Know why (enable linear mode). Need S3 info.
+
+ o Would be nice to have Motif...
+
+ o Can we have 32 double registers?
+
+
+Lots of other things.....
diff --git a/sys/arch/arc/arc/arctype.h b/sys/arch/arc/arc/arctype.h
new file mode 100644
index 00000000000..d309d3e5d48
--- /dev/null
+++ b/sys/arch/arc/arc/arctype.h
@@ -0,0 +1,46 @@
+/* $OpenBSD: arctype.h,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University,
+ * Ralph Campbell and Rick Macklem.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)arctype.h 8.1 (Berkeley) 6/10/93
+ * $Id: arctype.h,v 1.1 1996/06/24 09:07:21 pefo Exp $
+ */
+
+/*
+ * Mother board type byte of "systype" environment variable.
+ */
+#define ACER_PICA_61 0x1 /* Acer Labs Pica 61 */
+#define DESKSTATION 0x2 /* Deskstation xxx */
diff --git a/sys/arch/arc/arc/autoconf.c b/sys/arch/arc/arc/autoconf.c
new file mode 100644
index 00000000000..2a90388362a
--- /dev/null
+++ b/sys/arch/arc/arc/autoconf.c
@@ -0,0 +1,230 @@
+/* $OpenBSD: autoconf.c,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: autoconf.c 1.31 91/01/21
+ *
+ * from: @(#)autoconf.c 8.1 (Berkeley) 6/10/93
+ * $Id: autoconf.c,v 1.1 1996/06/24 09:07:20 pefo Exp $
+ */
+
+/*
+ * Setup the system to run on the current machine.
+ *
+ * Configure() is called at boot time. Available
+ * devices are determined (from possibilities mentioned in ioconf.c),
+ * and the drivers are initialized.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/disklabel.h>
+#include <sys/conf.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+
+/*
+ * The following several variables are related to
+ * the configuration process, and are used in initializing
+ * the machine.
+ */
+int cold = 1; /* if 1, still working on cold-start */
+int cpuspeed = 150; /* approx # instr per usec. */
+
+/*
+ * Configure all devices found that we know about.
+ * This is done at boot time.
+ */
+configure()
+{
+ (void)splhigh(); /* To be really shure.. */
+ if(config_rootfound("mainbus", "mainbus") == 0)
+ panic("no mainbus found");
+ (void)spl0();
+
+#ifdef GENERIC
+ if ((boothowto & RB_ASKNAME) == 0)
+ setroot();
+ setconf();
+#else
+ setroot();
+#endif
+ swapconf();
+ cold = 0;
+}
+
+/*
+ * Configure swap space and related parameters.
+ */
+swapconf()
+{
+ register struct swdevt *swp;
+ register int nblks;
+
+ for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
+ if (bdevsw[major(swp->sw_dev)].d_psize) {
+ nblks =
+ (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
+ if (nblks != -1 &&
+ (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
+ swp->sw_nblks = nblks;
+ swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
+ }
+ }
+ dumpconf();
+}
+
+#define DOSWAP /* Change swdevt and dumpdev too */
+u_long bootdev; /* should be dev_t, but not until 32 bits */
+
+static char devname[][2] = {
+ 's','d', /* 0 = sd */
+ 'x','x', /* 1 = unused */
+ 'x','x', /* 2 = unused */
+ 'x','x', /* 3 = unused */
+ 'x','x', /* 4 = unused */
+ 'x','x', /* 5 = unused */
+ 'x','x', /* 6 = unused */
+ 'f','d', /* 7 = floppy */
+};
+
+#define PARTITIONMASK 0x7
+#define PARTITIONSHIFT 3
+
+/*
+ * Attempt to find the device from which we were booted.
+ * If we can do so, and not instructed not to do so,
+ * change rootdev to correspond to the load device.
+ */
+setroot()
+{
+ int majdev, mindev, unit, part, controller;
+ dev_t temp, orootdev;
+ struct swdevt *swp;
+
+ if (boothowto & RB_DFLTROOT ||
+ (bootdev & B_MAGICMASK) != B_DEVMAGIC)
+ return;
+ majdev = B_TYPE(bootdev);
+ if (majdev >= sizeof(devname) / sizeof(devname[0]))
+ return;
+ controller = B_CONTROLLER(bootdev);
+ part = B_PARTITION(bootdev);
+ unit = B_UNIT(bootdev);
+
+ mindev = (unit << PARTITIONSHIFT) + part;
+ orootdev = rootdev;
+ rootdev = makedev(majdev, mindev);
+ /*
+ * If the original rootdev is the same as the one
+ * just calculated, don't need to adjust the swap configuration.
+ */
+ if (rootdev == orootdev)
+ return;
+
+ printf("changing root device to %c%c%d%c\n",
+ devname[majdev][0], devname[majdev][1],
+ unit, part + 'a');
+
+#ifdef DOSWAP
+ for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
+ if (majdev == major(swp->sw_dev) &&
+ (mindev / MAXPARTITIONS) == (minor(swp->sw_dev) / MAXPARTITIONS)) {
+ temp = swdevt[0].sw_dev;
+ swdevt[0].sw_dev = swp->sw_dev;
+ swp->sw_dev = temp;
+ break;
+ }
+ }
+ if (swp->sw_dev == NODEV)
+ return;
+
+ /*
+ * If dumpdev was the same as the old primary swap
+ * device, move it to the new primary swap device.
+ */
+ if (temp == dumpdev)
+ dumpdev = swdevt[0].sw_dev;
+#endif
+}
+
+/*
+ * Look at the string 'cp' and decode the boot device.
+ * Boot names look like: scsi()disk(n)rdisk()partition(1)\bsd
+ */
+void
+makebootdev(cp)
+ char *cp;
+{
+ int majdev, unit, part, ctrl;
+ char dv[8];
+
+ bootdev = B_DEVMAGIC;
+
+ dv[0] = *cp;
+ ctrl = getpno(&cp);
+ if(*cp++ == ')') {
+ dv[1] = *cp;
+ unit = getpno(&cp);
+
+ for (majdev = 0; majdev < sizeof(devname)/sizeof(devname[0]); majdev++)
+ if (dv[0] == devname[majdev][0] &&
+ dv[1] == devname[majdev][1] && cp[0] == ')')
+ bootdev = MAKEBOOTDEV(majdev, 0, ctrl, unit,0);
+ }
+}
+getpno(cp)
+ char **cp;
+{
+ int val = 0;
+ char *cx = *cp;
+
+ while(*cx && *cx != '(')
+ cx++;
+ if(*cx == '(') {
+ cx++;
+ while(*cx && *cx != ')') {
+ val = val * 10 + *cx - '0';
+ cx++;
+ }
+ }
+ *cp = cx;
+ return val;
+}
diff --git a/sys/arch/arc/arc/clock.c b/sys/arch/arc/arc/clock.c
new file mode 100644
index 00000000000..b247f2ff5d5
--- /dev/null
+++ b/sys/arch/arc/arc/clock.c
@@ -0,0 +1,314 @@
+/* $OpenBSD: clock.c,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: clock.c 1.18 91/01/21
+ *
+ * from: @(#)clock.c 8.1 (Berkeley) 6/10/93
+ * $Id: clock.c,v 1.1 1996/06/24 09:07:20 pefo Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+#include <arc/arc/clockvar.h>
+#include <arc/arc/arctype.h>
+
+
+extern int cputype; /* What kind of cpu we are running on */
+
+/* Definition of the driver for autoconfig. */
+static int clockmatch __P((struct device *, void *, void *));
+static void clockattach __P((struct device *, struct device *, void *));
+
+struct cfattach clock_ca = {
+ sizeof(struct clock_softc), clockmatch, clockattach
+};
+struct cfdriver clock_cd = {
+ NULL, "clock", DV_DULL, NULL, 0
+};
+
+void mcclock_attach __P((struct device *, struct device *, void *));
+
+#define SECMIN ((unsigned)60) /* seconds per minute */
+#define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */
+#define SECDAY ((unsigned)(24*SECHOUR)) /* seconds per day */
+#define SECYR ((unsigned)(365*SECDAY)) /* seconds per common year */
+
+#define LEAPYEAR(year) (((year) % 4) == 0)
+
+static int
+clockmatch(parent, cfdata, aux)
+ struct device *parent;
+ void *cfdata;
+ void *aux;
+{
+ struct cfdata *cf = cfdata;
+ struct confargs *ca = aux;
+
+ /* See how many clocks this system has */
+ switch (cputype) {
+
+ case ACER_PICA_61:
+ /* make sure that we're looking for this type of device. */
+ if (!BUS_MATCHNAME(ca, "dallas_rtc"))
+ return (0);
+
+ if (cf->cf_unit >= 1)
+ return (0);
+
+ break;
+
+ default:
+ panic("unknown CPU");
+ }
+
+ return (1);
+}
+
+static void
+clockattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+
+ switch (cputype) {
+
+ case ACER_PICA_61:
+ mcclock_attach(parent, self, aux);
+ break;
+
+ default:
+ panic("clockattach: it didn't get here. really.");
+ }
+
+
+ /*
+ * establish the clock interrupt; it's a special case
+ */
+ BUS_INTR_ESTABLISH((struct confargs *)aux, (intr_handler_t)hardclock, self);
+
+ printf("\n");
+}
+
+/*
+ * Wait "n" microseconds. This doesn't belong here. XXX.
+ */
+void
+delay(n)
+ int n;
+{
+ DELAY(n);
+}
+
+/*
+ * Machine-dependent clock routines.
+ *
+ * Startrtclock restarts the real-time clock, which provides
+ * hardclock interrupts to kern_clock.c.
+ *
+ * Inittodr initializes the time of day hardware which provides
+ * date functions. Its primary function is to use some file
+ * system information in case the hardare clock lost state.
+ *
+ * Resettodr restores the time of day hardware after a time change.
+ */
+
+
+/*
+ * Start the real-time and statistics clocks. Leave stathz 0 since there
+ * are no other timers available.
+ */
+void
+cpu_initclocks()
+{
+ extern int tickadj;
+ struct clock_softc *csc = (struct clock_softc *)clock_cd.cd_devs[0];
+
+ hz = 100; /* 100 Hz */
+ tick = 1000000 / hz; /* number of micro-seconds between interrupts */
+
+ /*
+ * Start the clock.
+ */
+ (*csc->sc_init)(csc);
+}
+
+/*
+ * We assume newhz is either stathz or profhz, and that neither will
+ * change after being set up above. Could recalculate intervals here
+ * but that would be a drag.
+ */
+void
+setstatclockrate(newhz)
+ int newhz;
+{
+}
+
+/*
+ * This code is defunct after 2099.
+ * Will Unix still be here then??
+ */
+static short dayyr[12] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+/*
+ * Initialze the time of day register, based on the time base which is, e.g.
+ * from a filesystem. Base provides the time to within six months,
+ * and the time of year clock (if any) provides the rest.
+ */
+void
+inittodr(base)
+ time_t base;
+{
+ struct tod_time c;
+ struct clock_softc *csc = (struct clock_softc *)clock_cd.cd_devs[0];
+ register int days, yr;
+ long deltat;
+ int badbase, s;
+
+ if (base < 5*SECYR) {
+ printf("WARNING: preposterous time in file system");
+ /* read the system clock anyway */
+ base = 6*SECYR + 186*SECDAY + SECDAY/2;
+ badbase = 1;
+ } else
+ badbase = 0;
+
+ /* Read RTC chip registers */
+ (*csc->sc_get)(csc, base, &c);
+
+ csc->sc_initted = 1;
+
+ /* simple sanity checks */
+ c.year = c.year+80; /* must be multiple of 4 because chip knows leap */
+ if (c.year < 70 || c.mon < 1 || c.mon > 12 || c.day < 1 ||
+ c.day > 31 || c.hour > 23 || c.min > 59 || c.sec > 59) {
+ /*
+ * Believe the time in the file system for lack of
+ * anything better, resetting the TODR.
+ */
+ time.tv_sec = base;
+ if (!badbase) {
+ printf("WARNING: preposterous clock chip time\n");
+ resettodr();
+ }
+ goto bad;
+ }
+ days = 0;
+ for (yr = 70; yr < c.year; yr++)
+ days += LEAPYEAR(yr) ? 366 : 365;
+ days += dayyr[c.mon - 1] + c.day - 1;
+ if (LEAPYEAR(yr) && c.mon > 2)
+ days++;
+ /* now have days since Jan 1, 1970; the rest is easy... */
+ time.tv_sec = days * SECDAY + c.hour * 3600 + c.min * 60 + c.sec;
+
+ if (!badbase) {
+ /*
+ * See if we gained/lost two or more days;
+ * if so, assume something is amiss.
+ */
+ deltat = time.tv_sec - base;
+ if (deltat < 0)
+ deltat = -deltat;
+ if (deltat < 2 * SECDAY)
+ return;
+ printf("WARNING: clock %s %d days",
+ time.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
+ }
+bad:
+ printf(" -- CHECK AND RESET THE DATE!\n");
+}
+
+/*
+ * Reset the TODR based on the time value; used when the TODR
+ * has a preposterous value and also when the time is reset
+ * by the stime system call. Also called when the TODR goes past
+ * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
+ * to wrap the TODR around.
+ */
+void
+resettodr()
+{
+ struct tod_time c;
+ struct clock_softc *csc = (struct clock_softc *)clock_cd.cd_devs[0];
+ register int t, t2;
+ int s;
+
+ if(!csc->sc_initted)
+ return;
+
+ /* compute the day of week. 1 is Sunday*/
+ t2 = time.tv_sec / SECDAY;
+ c.dow = (t2 + 5) % 7; /* 1/1/1970 was thursday */
+
+ /* compute the year */
+ t2 = time.tv_sec / SECDAY;
+ c.year = 69;
+ while (t2 >= 0) { /* whittle off years */
+ t = t2;
+ c.year++;
+ t2 -= LEAPYEAR(c.year) ? 366 : 365;
+ }
+
+ /* t = month + day; separate */
+ t2 = LEAPYEAR(c.year);
+ for (c.mon = 1; c.mon < 12; c.mon++)
+ if (t < dayyr[c.mon] + (t2 && c.mon > 1))
+ break;
+
+ c.day = t - dayyr[c.mon - 1] + 1;
+ if (t2 && c.mon > 2)
+ c.day--;
+
+ /* the rest is easy */
+ t = time.tv_sec % SECDAY;
+ c.hour = t / 3600;
+ t %= 3600;
+ c.min = t / 60;
+ c.sec = t % 60;
+ c.year = c.year-80; /* must be multiple of 4 because chip knows leap */
+
+ (*csc->sc_set)(csc, &c);
+}
diff --git a/sys/arch/arc/arc/clock_mc.c b/sys/arch/arc/arc/clock_mc.c
new file mode 100644
index 00000000000..88261cac0ed
--- /dev/null
+++ b/sys/arch/arc/arc/clock_mc.c
@@ -0,0 +1,216 @@
+/* $OpenBSD: clock_mc.c,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+/* $NetBSD: clock_mc.c,v 1.2 1995/06/28 04:30:30 cgd Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: clock.c 1.18 91/01/21
+ *
+ * @(#)clock.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/pio.h>
+
+#include <arc/arc/clockvar.h>
+#include <arc/arc/arctype.h>
+#include <arc/pica/pica.h>
+#include <dev/ic/mc146818reg.h>
+
+extern u_int cputype;
+extern int cpu_int_mask;
+
+void mcclock_attach __P((struct device *parent,
+ struct device *self, void *aux));
+static void mcclock_init __P((struct clock_softc *csc));
+static void mcclock_get __P((struct clock_softc *csc, time_t base,
+ struct tod_time *ct));
+static void mcclock_set __P((struct clock_softc *csc,
+ struct tod_time *ct));
+
+struct mcclockdata {
+ void (*mc_write) __P((struct clock_softc *csc, u_int reg,
+ u_int datum));
+ u_int (*mc_read) __P((struct clock_softc *csc, u_int reg));
+ void *mc_addr;
+};
+
+#define mc146818_write(sc, reg, datum) \
+ (*((struct mcclockdata *)sc->sc_data)->mc_write)(sc, reg, datum)
+#define mc146818_read(sc, reg) \
+ (*((struct mcclockdata *)sc->sc_data)->mc_read)(sc, reg)
+
+#if defined(ACER_PICA_61)
+static void mc_write_arc __P((struct clock_softc *csc, u_int reg,
+ u_int datum));
+static u_int mc_read_arc __P((struct clock_softc *csc, u_int reg));
+static struct mcclockdata mcclockdata_arc = { mc_write_arc, mc_read_arc };
+#endif
+
+void
+mcclock_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct clock_softc *csc = (struct clock_softc *)self;
+
+ register volatile struct chiptime *c;
+ struct confargs *ca = aux;
+
+ printf(": mc146818 or compatible");
+
+ csc->sc_init = mcclock_init;
+ csc->sc_get = mcclock_get;
+ csc->sc_set = mcclock_set;
+
+ switch (cputype) {
+
+ case ACER_PICA_61:
+ /*
+ * XXX should really allocate a new one and copy, or
+ * something. unlikely we'll have more than one...
+ */
+ csc->sc_data = &mcclockdata_arc;
+ mcclockdata_arc.mc_addr = BUS_CVTADDR(ca);
+ break;
+
+ default:
+ printf("\n");
+ panic("don't know how to set up for other system types.");
+ }
+
+ /* Turn interrupts off, just in case. */
+ mc146818_write(csc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
+}
+
+static void
+mcclock_init(csc)
+ struct clock_softc *csc;
+{
+/* XXX Does not really belong here but for the moment we don't care */
+ out32(PICA_SYS_IT_VALUE, 9); /* 10ms - 1 */
+ /* Enable periodic clock interrupt */
+ out32(PICA_SYS_EXT_IMASK, cpu_int_mask);
+}
+
+/*
+ * Get the time of day, based on the clock's value and/or the base value.
+ */
+static void
+mcclock_get(csc, base, ct)
+ struct clock_softc *csc;
+ time_t base;
+ struct tod_time *ct;
+{
+ mc_todregs regs;
+ int s;
+
+ s = splclock();
+ MC146818_GETTOD(csc, &regs)
+ splx(s);
+
+ ct->sec = regs[MC_SEC];
+ ct->min = regs[MC_MIN];
+ ct->hour = regs[MC_HOUR];
+ ct->dow = regs[MC_DOW];
+ ct->day = regs[MC_DOM];
+ ct->mon = regs[MC_MONTH];
+ ct->year = regs[MC_YEAR];
+}
+
+/*
+ * Reset the TODR based on the time value.
+ */
+static void
+mcclock_set(csc, ct)
+ struct clock_softc *csc;
+ struct tod_time *ct;
+{
+ mc_todregs regs;
+ int s;
+
+ s = splclock();
+ MC146818_GETTOD(csc, &regs);
+ splx(s);
+
+ regs[MC_SEC] = ct->sec;
+ regs[MC_MIN] = ct->min;
+ regs[MC_HOUR] = ct->hour;
+ regs[MC_DOW] = ct->dow;
+ regs[MC_DOM] = ct->day;
+ regs[MC_MONTH] = ct->mon;
+ regs[MC_YEAR] = ct->year;
+
+ s = splclock();
+ MC146818_PUTTOD(csc, &regs);
+ splx(s);
+}
+
+
+#if defined(ACER_PICA_61)
+
+static void
+mc_write_arc(csc, reg, datum)
+ struct clock_softc *csc;
+ u_int reg, datum;
+{
+ int i,as;
+
+ as = in32(PICA_SYS_ISA_AS) & 0x80;
+ out32(PICA_SYS_ISA_AS, as | reg);
+ outb(PICA_SYS_CLOCK, datum);
+}
+
+static u_int
+mc_read_arc(csc, reg)
+ struct clock_softc *csc;
+ u_int reg;
+{
+ int i,as;
+
+ as = in32(PICA_SYS_ISA_AS) & 0x80;
+ out32(PICA_SYS_ISA_AS, as | reg);
+ i = inb(PICA_SYS_CLOCK);
+ return(i);
+}
+#endif /*ACER_PICA_61*/
diff --git a/sys/arch/arc/arc/clockvar.h b/sys/arch/arc/arc/clockvar.h
new file mode 100644
index 00000000000..9f4f677e9f1
--- /dev/null
+++ b/sys/arch/arc/arc/clockvar.h
@@ -0,0 +1,79 @@
+/* $OpenBSD: clockvar.h,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+/* $NetBSD: clockvar.h,v 1.1 1995/06/28 02:44:59 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ * Adopted for r4400: Per Fogelstrom
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Definitions for "cpu-independent" clock handling for the mips arc arch.
+ */
+
+/*
+ * clocktime structure:
+ *
+ * structure passed to TOY clocks when setting them. broken out this
+ * way, so that the time_t -> field conversion can be shared.
+ */
+struct tod_time {
+ int year; /* year - 1900 */
+ int mon; /* month (1 - 12) */
+ int day; /* day (1 - 31) */
+ int hour; /* hour (0 - 23) */
+ int min; /* minute (0 - 59) */
+ int sec; /* second (0 - 59) */
+ int dow; /* day of week (0 - 6; 0 = Sunday) */
+};
+
+/*
+ * clockdesc structure:
+ *
+ * provides clock-specific functions to do necessary operations.
+ */
+struct clock_softc {
+ struct device sc_dev;
+
+ /*
+ * The functions that all types of clock provide.
+ */
+ void (*sc_attach) __P((struct device *parent, struct device *self,
+ void *aux));
+ void (*sc_init) __P((struct clock_softc *csc));
+ void (*sc_get) __P((struct clock_softc *csc, time_t base,
+ struct tod_time *ct));
+ void (*sc_set) __P((struct clock_softc *csc, struct tod_time *ct));
+
+ /*
+ * Private storage for particular clock types.
+ */
+ void *sc_data;
+
+ /*
+ * Has the time been initialized?
+ */
+ int sc_initted;
+};
diff --git a/sys/arch/arc/arc/conf.c b/sys/arch/arc/arc/conf.c
new file mode 100644
index 00000000000..7bfd2009c58
--- /dev/null
+++ b/sys/arch/arc/arc/conf.c
@@ -0,0 +1,330 @@
+/* $OpenBSD: conf.c,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)conf.c 8.2 (Berkeley) 11/14/93
+ * $Id: conf.c,v 1.1 1996/06/24 09:07:20 pefo Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+
+int ttselect __P((dev_t, int, struct proc *));
+
+/*
+ * Block devices.
+ */
+
+#include "vnd.h"
+bdev_decl(vnd);
+bdev_decl(sw);
+#include "sd.h"
+bdev_decl(sd);
+#include "cd.h"
+bdev_decl(cd);
+#include "fdc.h"
+bdev_decl(fd);
+
+struct bdevsw bdevsw[] =
+{
+ bdev_disk_init(NSD,sd), /* 0: SCSI disk */
+ bdev_swap_init(1,sw), /* 1: should be here swap pseudo-dev */
+ bdev_disk_init(NVND,vnd), /* 2: vnode disk driver */
+ bdev_disk_init(NCD,cd), /* 3: SCSI CD-ROM */
+ bdev_notdef(), /* 4: */
+ bdev_notdef(), /* 5: */
+ bdev_notdef(), /* 6: */
+ bdev_disk_init(NFDC,fd), /* 7: Floppy disk driver */
+ bdev_notdef(), /* 8: */
+ bdev_notdef(), /* 9: */
+ bdev_notdef(), /* 10: */
+ bdev_notdef(), /* 11: */
+ bdev_notdef(), /* 12: */
+ bdev_notdef(), /* 13: */
+ bdev_notdef(), /* 14: */
+ bdev_notdef(), /* 15: */
+};
+
+int nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
+
+/*
+ * Character devices.
+ */
+
+/* open, close, read, write, ioctl, tty, mmap */
+#define cdev_pc_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \
+ dev_init(c,n,tty), ttselect, dev_init(c,n,mmap), D_TTY }
+
+/* open, close, write, ioctl */
+#define cdev_lpt_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+ 0, seltrue, (dev_type_mmap((*))) enodev }
+
+/* open, close, write, ioctl */
+#define cdev_spkr_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+ 0, seltrue, (dev_type_mmap((*))) enodev }
+
+cdev_decl(cn);
+cdev_decl(sw);
+cdev_decl(ctty);
+#define mmread mmrw
+#define mmwrite mmrw
+dev_type_read(mmrw);
+cdev_decl(mm);
+#include "pty.h"
+#define ptstty ptytty
+#define ptsioctl ptyioctl
+cdev_decl(pts);
+#define ptctty ptytty
+#define ptcioctl ptyioctl
+cdev_decl(ptc);
+cdev_decl(log);
+cdev_decl(fd);
+#include "st.h"
+cdev_decl(st);
+#include "fdc.h"
+bdev_decl(fd);
+cdev_decl(vnd);
+#include "bpfilter.h"
+cdev_decl(bpf);
+#include "ace.h"
+cdev_decl(ace);
+#include "lpt.h"
+cdev_decl(lpt);
+cdev_decl(sd);
+#include "pc.h"
+cdev_decl(pc);
+cdev_decl(pms);
+cdev_decl(cd);
+
+/* open, close, read, ioctl */
+cdev_decl(ipl);
+#ifdef IPFILTER
+#define NIPF 1
+#else
+#define NIPF 0
+#endif
+
+struct cdevsw cdevsw[] =
+{
+ cdev_cn_init(1,cn), /* 0: virtual console */
+ cdev_swap_init(1,sw), /* 1: /dev/drum (swap pseudo-device) */
+ cdev_ctty_init(1,ctty), /* 2: controlling terminal */
+ cdev_mm_init(1,mm), /* 3: /dev/{null,mem,kmem,...} */
+ cdev_tty_init(NPTY,pts), /* 4: pseudo-tty slave */
+ cdev_ptc_init(NPTY,ptc), /* 5: pseudo-tty master */
+ cdev_log_init(1,log), /* 6: /dev/klog */
+ cdev_fd_init(1,filedesc), /* 7: file descriptor pseudo-dev */
+ cdev_disk_init(NCD,cd), /* 8: SCSI CD */
+ cdev_disk_init(NSD,sd), /* 9: SCSI disk */
+ cdev_tape_init(NST,st), /* 10: SCSI tape */
+ cdev_disk_init(NVND,vnd), /* 11: vnode disk */
+ cdev_bpftun_init(NBPFILTER,bpf),/* 12: berkeley packet filter */
+ cdev_disk_init(NFDC,fd), /* 13: Floppy disk */
+ cdev_pc_init(NPC,pc), /* 14: builtin pc style console dev */
+ cdev_mouse_init(1,pms), /* 15: builtin PS2 style mouse */
+ cdev_lpt_init(NLPT,lpt), /* 16: lpt paralell printer interface */
+ cdev_tty_init(NCOM,ace), /* 17: ace 16C450 serial interface */
+ cdev_notdef(), /* 18: */
+ cdev_notdef(), /* 19: */
+ cdev_tty_init(NPTY,pts), /* 20: pseudo-tty slave */
+ cdev_ptc_init(NPTY,ptc), /* 21: pseudo-tty master */
+ cdev_notdef(), /* 22: */
+ cdev_notdef(), /* 23: */
+ cdev_notdef(), /* 24: */
+ cdev_notdef(), /* 25: */
+ cdev_notdef(), /* 26: */
+ cdev_notdef(), /* 27: */
+ cdev_notdef(), /* 28: */
+ cdev_notdef(), /* 29: */
+ cdev_notdef(), /* 30: */
+ cdev_gen_ipf(NIPF,ipl), /* 31: IP filter log */
+};
+
+int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
+
+int mem_no = 2; /* major device number of memory special file */
+
+/*
+ * Swapdev is a fake device implemented
+ * in sw.c used only internally to get to swstrategy.
+ * It cannot be provided to the users, because the
+ * swstrategy routine munches the b_dev and b_blkno entries
+ * before calling the appropriate driver. This would horribly
+ * confuse, e.g. the hashing routines. Instead, /dev/drum is
+ * provided as a character (raw) device.
+ */
+dev_t swapdev = makedev(1, 0);
+
+/*
+ * Routine that identifies /dev/mem and /dev/kmem.
+ *
+ * A minimal stub routine can always return 0.
+ */
+iskmemdev(dev)
+ dev_t dev;
+{
+
+#ifdef COMPAT_BSD44
+ if (major(dev) == 2 && (minor(dev) == 0 || minor(dev) == 1))
+#else
+ if (major(dev) == 3 && (minor(dev) == 0 || minor(dev) == 1))
+#endif
+ return (1);
+ return (0);
+}
+
+/*
+ * Returns true if def is /dev/zero
+ */
+iszerodev(dev)
+ dev_t dev;
+{
+#ifdef COMPAT_BSD44
+ return (major(dev) == 2 && minor(dev) == 12);
+#else
+ return (major(dev) == 3 && minor(dev) == 12);
+#endif
+}
+
+
+#define MAXDEV 57
+static int chrtoblktbl[MAXDEV] = {
+ /* VCHR */ /* VBLK */
+ /* 0 */ NODEV,
+ /* 1 */ NODEV,
+ /* 2 */ NODEV,
+ /* 3 */ NODEV,
+ /* 4 */ NODEV,
+ /* 5 */ NODEV,
+ /* 6 */ NODEV,
+ /* 7 */ NODEV,
+ /* 8 */ NODEV,
+ /* 9 */ 0,
+ /* 10 */ NODEV,
+ /* 11 */ 2,
+ /* 12 */ NODEV,
+ /* 13 */ 7,
+ /* 14 */ NODEV,
+ /* 15 */ NODEV,
+ /* 16 */ NODEV,
+ /* 17 */ NODEV,
+ /* 18 */ NODEV,
+ /* 19 */ NODEV,
+ /* 20 */ NODEV,
+ /* 21 */ NODEV,
+ /* 22 */ NODEV,
+ /* 23 */ NODEV,
+ /* 24 */ NODEV,
+ /* 25 */ NODEV,
+ /* 26 */ NODEV,
+ /* 27 */ NODEV,
+ /* 28 */ NODEV,
+ /* 29 */ NODEV,
+ /* 30 */ NODEV,
+ /* 31 */ NODEV,
+ /* 32 */ NODEV,
+ /* 33 */ NODEV,
+ /* 34 */ NODEV,
+ /* 35 */ NODEV,
+ /* 36 */ NODEV,
+ /* 37 */ NODEV,
+ /* 38 */ NODEV,
+ /* 39 */ NODEV,
+ /* 40 */ NODEV,
+ /* 41 */ NODEV,
+ /* 42 */ NODEV,
+ /* 43 */ NODEV,
+ /* 44 */ NODEV,
+ /* 45 */ NODEV,
+ /* 46 */ NODEV,
+ /* 47 */ NODEV,
+ /* 48 */ NODEV,
+ /* 49 */ NODEV,
+ /* 50 */ NODEV,
+ /* 51 */ NODEV,
+ /* 52 */ NODEV,
+ /* 53 */ NODEV,
+ /* 54 */ NODEV,
+ /* 55 */ NODEV,
+ /* 56 */ NODEV,
+};
+/*
+ * Routine to convert from character to block device number.
+ *
+ * A minimal stub routine can always return NODEV.
+ */
+chrtoblk(dev)
+ dev_t dev;
+{
+ int blkmaj;
+
+ if (major(dev) >= MAXDEV || (blkmaj = chrtoblktbl[major(dev)]) == NODEV)
+ return (NODEV);
+ return (makedev(blkmaj, minor(dev)));
+}
+
+/*
+ * This entire table could be autoconfig()ed but that would mean that
+ * the kernel's idea of the console would be out of sync with that of
+ * the standalone boot. I think it best that they both use the same
+ * known algorithm unless we see a pressing need otherwise.
+ */
+#include <dev/cons.h>
+
+cons_decl(pc);
+cons_decl(ace);
+
+struct consdev constab[] = {
+#if NPC + NVT > 0
+ cons_init(pc),
+#endif
+#if NCOM > 0
+ cons_init(ace),
+#endif
+ { 0 },
+};
diff --git a/sys/arch/arc/arc/cpu.c b/sys/arch/arc/arc/cpu.c
new file mode 100644
index 00000000000..5917761ebf6
--- /dev/null
+++ b/sys/arch/arc/arc/cpu.c
@@ -0,0 +1,188 @@
+/* $OpenBSD: cpu.c,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Per Fogelstrom
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+
+
+/* Definition of the driver for autoconfig. */
+static int cpumatch(struct device *, void *, void *);
+static void cpuattach(struct device *, struct device *, void *);
+
+struct cfattach cpu_ca = {
+ sizeof(struct device), cpumatch, cpuattach
+};
+struct cfdriver cpu_cd = {
+ NULL, "cpu", DV_DULL, NULL, 0
+};
+
+static int cpuprint __P((void *, char *pnp));
+
+static int
+cpumatch(parent, cfdata, aux)
+ struct device *parent;
+ void *cfdata;
+ void *aux;
+{
+ struct cfdata *cf = cfdata;
+ struct confargs *ca = aux;
+
+ /* make sure that we're looking for a CPU. */
+ if (strcmp(ca->ca_name, cpu_cd.cd_name) != 0)
+ return (0);
+
+ return (1);
+}
+
+static void
+cpuattach(parent, dev, aux)
+ struct device *parent;
+ struct device *dev;
+ void *aux;
+{
+ struct pcs *p;
+ int needcomma, needrev, i;
+
+ printf(": ");
+
+ switch(cpu_id.cpu.cp_imp) {
+
+ case MIPS_R2000:
+ printf("MIPS R2000 CPU");
+ break;
+ case MIPS_R3000:
+ printf("MIPS R3000 CPU");
+ break;
+ case MIPS_R6000:
+ printf("MIPS R6000 CPU");
+ break;
+ case MIPS_R4000:
+ if(machPrimaryInstCacheSize == 16384)
+ printf("MIPS R4400 CPU");
+ else
+ printf("MIPS R4000 CPU");
+ break;
+ case MIPS_R3LSI:
+ printf("LSI Logic R3000 derivate");
+ break;
+ case MIPS_R6000A:
+ printf("MIPS R6000A CPU");
+ break;
+ case MIPS_R3IDT:
+ printf("IDT R3000 derivate");
+ break;
+ case MIPS_R10000:
+ printf("MIPS R10000/T5 CPU");
+ break;
+ case MIPS_R4200:
+ printf("MIPS R4200 CPU (ICE)");
+ break;
+ case MIPS_R8000:
+ printf("MIPS R8000 Blackbird/TFP CPU");
+ break;
+ case MIPS_R4600:
+ printf("QED R4600 Orion CPU");
+ break;
+ case MIPS_R3SONY:
+ printf("Sony R3000 based CPU");
+ break;
+ case MIPS_R3TOSH:
+ printf("Toshiba R3000 based CPU");
+ break;
+ case MIPS_R3NKK:
+ printf("NKK R3000 based CPU");
+ break;
+ case MIPS_UNKC1:
+ case MIPS_UNKC2:
+ default:
+ printf("Unknown CPU type (0x%x)",cpu_id.cpu.cp_imp);
+ break;
+ }
+ printf(" Rev. %d.%d with ", cpu_id.cpu.cp_majrev, cpu_id.cpu.cp_minrev);
+
+
+ switch(fpu_id.cpu.cp_imp) {
+
+ case MIPS_SOFT:
+ printf("Software emulation float");
+ break;
+ case MIPS_R2360:
+ printf("MIPS R2360 FPC");
+ break;
+ case MIPS_R2010:
+ printf("MIPS R2010 FPC");
+ break;
+ case MIPS_R3010:
+ printf("MIPS R3010 FPC");
+ break;
+ case MIPS_R6010:
+ printf("MIPS R6010 FPC");
+ break;
+ case MIPS_R4010:
+ printf("MIPS R4010 FPC");
+ break;
+ case MIPS_R31LSI:
+ printf("FPC");
+ break;
+ case MIPS_R10010:
+ printf("MIPS R10000/T5 FPU");
+ break;
+ case MIPS_R4210:
+ printf("MIPS R4200 FPC (ICE)");
+ case MIPS_R8000:
+ printf("MIPS R8000 Blackbird/TFP");
+ break;
+ case MIPS_R4600:
+ printf("QED R4600 Orion FPC");
+ break;
+ case MIPS_R3SONY:
+ printf("Sony R3000 based FPC");
+ break;
+ case MIPS_R3TOSH:
+ printf("Toshiba R3000 based FPC");
+ break;
+ case MIPS_R3NKK:
+ printf("NKK R3000 based FPC");
+ break;
+ case MIPS_UNKF1:
+ default:
+ printf("Unknown FPU type (0x%x)", fpu_id.cpu.cp_imp);
+ break;
+ }
+ printf(" Rev. %d.%d", fpu_id.cpu.cp_majrev, fpu_id.cpu.cp_minrev);
+ printf("\n");
+
+ printf(" Primary cache size: %dkb Instruction, %dkb Data.\n",
+ machPrimaryInstCacheSize / 1024,
+ machPrimaryDataCacheSize / 1024);
+}
+
diff --git a/sys/arch/arc/arc/cpu_exec.c b/sys/arch/arc/arc/cpu_exec.c
new file mode 100644
index 00000000000..4e3e657011a
--- /dev/null
+++ b/sys/arch/arc/arc/cpu_exec.c
@@ -0,0 +1,104 @@
+/* $NetBSD: cpu_exec.c,v 1.4 1995/04/25 19:16:46 mellon Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by Ralph
+ * Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)machdep.c 8.3 (Berkeley) 1/12/94
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/exec.h>
+#include <sys/resourcevar.h>
+#include <vm/vm.h>
+
+#include <sys/exec_ecoff.h>
+#include <machine/reg.h>
+
+/*
+ * cpu_exec_aout_makecmds():
+ * cpu-dependent a.out format hook for execve().
+ *
+ * Determine of the given exec package refers to something which we
+ * understand and, if so, set up the vmcmds for it.
+ *
+ */
+int
+cpu_exec_aout_makecmds(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+{
+ return ENOEXEC;
+}
+
+#ifdef COMPAT_ULTRIX
+extern struct emul emul_ultrix;
+
+void
+cpu_exec_ecoff_setregs(p, pack, stack, retval)
+ struct proc *p;
+ struct exec_package *pack;
+ u_long stack;
+ register_t *retval;
+{
+ struct ecoff_aouthdr *eap;
+
+ setregs(p, pack, stack, retval);
+ eap = (struct ecoff_aouthdr *)
+ ((caddr_t)pack->ep_hdr + sizeof(struct ecoff_filehdr));
+ p->p_md.md_regs[GP] = eap->ea_gp_value;
+}
+
+/*
+ * cpu_exec_ecoff_hook():
+ * cpu-dependent ECOFF format hook for execve().
+ *
+ * Do any machine-dependent diddling of the exec package when doing ECOFF.
+ *
+ */
+int
+cpu_exec_ecoff_hook(p, epp, eap)
+ struct proc *p;
+ struct exec_package *epp;
+ struct ecoff_aouthdr *eap;
+{
+
+ epp->ep_emul = &emul_ultrix;
+ return 0;
+}
+#endif
diff --git a/sys/arch/arc/arc/disksubr.c b/sys/arch/arc/arc/disksubr.c
new file mode 100644
index 00000000000..4f84136f3a8
--- /dev/null
+++ b/sys/arch/arc/arc/disksubr.c
@@ -0,0 +1,323 @@
+/* $OpenBSD: disksubr.c,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+/* $NetBSD: disksubr.c,v 1.3 1995/04/22 12:43:22 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Authors: Keith Bostic, Chris G. Demetriou, Per Fogelstrom (R4000)
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/ioccom.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+
+extern struct device *bootdv;
+
+/* was this the boot device ? */
+void
+dk_establish(dk, dev)
+ struct disk *dk;
+ struct device *dev;
+{
+}
+
+/*
+ * Attempt to read a disk label from a device
+ * using the indicated stategy routine.
+ * The label must be partly set up before this:
+ * secpercyl and anything required in the strategy routine
+ * (e.g., sector size) must be filled in before calling us.
+ * Returns null on success and an error string on failure.
+ */
+char *
+readdisklabel(dev, strat, lp, clp)
+ dev_t dev;
+ void (*strat)();
+ struct disklabel *lp;
+ struct cpu_disklabel *clp;
+{
+ struct buf *bp;
+ struct disklabel *dlp;
+ struct dos_partition *dp = clp->dosparts;
+ char *msg = NULL;
+ int dospartoff = 0;
+ int i;
+
+ /* minimal requirements for archtypal disk label */
+ if (lp->d_secperunit == 0)
+ lp->d_secperunit = 0x1fffffff;
+ lp->d_npartitions = RAW_PART + 1;
+ for(i = 0; i < RAW_PART; i++) {
+ lp->d_partitions[i].p_size = 0;
+ lp->d_partitions[i].p_offset = 0;
+ }
+ if (lp->d_partitions[RAW_PART].p_size == 0)
+ lp->d_partitions[RAW_PART].p_size = 0x1fffffff;
+ lp->d_partitions[RAW_PART].p_offset = 0;
+
+ /* obtain buffer to probe drive with */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* do dos partitions in the process of getting disklabel? */
+ if (dp) {
+ /* read master boot record */
+ bp->b_blkno = DOSBBSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_resid = 0;
+ (*strat)(bp);
+
+ /* if successful, wander through dos partition table */
+ if (biowait(bp)) {
+ msg = "dos partition I/O error";
+ goto done;
+ } else if (*(unsigned int *)(bp->b_data) == 0x8ec033fa) {
+ /* XXX how do we check veracity/bounds of this? */
+ bcopy(bp->b_data + DOSPARTOFF, dp, NDOSPART * sizeof(*dp));
+ for (i = 0; i < NDOSPART; i++, dp++) {
+ /* is this ours? */
+ if (dp->dp_size && dp->dp_typ == DOSPTYP_386BSD
+ && dospartoff == 0) {
+ dospartoff = dp->dp_start;
+
+ /* set part a to show NetBSD part */
+ lp->d_partitions[0].p_size = dp->dp_size;
+ lp->d_partitions[0].p_offset = dp->dp_start;
+ lp->d_ntracks = dp->dp_ehd + 1;
+ lp->d_nsectors = DPSECT(dp->dp_esect);
+ lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+ }
+ }
+ }
+
+ }
+ /* next, dig out disk label */
+ bp->b_blkno = dospartoff + LABELSECTOR;
+ bp->b_resid = 0;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+
+ /* if successful, locate disk label within block and validate */
+ if (biowait(bp)) {
+ msg = "disk label read error";
+ goto done;
+ }
+
+ dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
+ if (dlp->d_magic == DISKMAGIC) {
+ if (dkcksum(dlp)) {
+ msg = "NetBSD disk label corrupted";
+ goto done;
+ }
+ *lp = *dlp;
+ goto done;
+ }
+ msg = "no disk label";
+done:
+ bp->b_flags = B_INVAL | B_AGE | B_READ;
+ brelse(bp);
+ return (msg);
+}
+
+/*
+ * Check new disk label for sensibility before setting it.
+ */
+int
+setdisklabel(olp, nlp, openmask, clp)
+ register struct disklabel *olp, *nlp;
+ u_long openmask;
+ struct cpu_disklabel *clp;
+{
+ register i;
+ register struct partition *opp, *npp;
+
+ /* sanity clause */
+ if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
+ (nlp->d_secsize % DEV_BSIZE) != 0)
+ return(EINVAL);
+
+#ifdef notdef
+ /* XXX WHY WAS THIS HERE?! */
+ /* special case to allow disklabel to be invalidated */
+ if (nlp->d_magic == 0xffffffff) {
+ *olp = *nlp;
+ return (0);
+ }
+#endif
+
+ if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
+ dkcksum(nlp) != 0)
+ return (EINVAL);
+
+ while ((i = ffs((long)openmask)) != 0) {
+ i--;
+ openmask &= ~(1 << i);
+ if (nlp->d_npartitions <= i)
+ return (EBUSY);
+ opp = &olp->d_partitions[i];
+ npp = &nlp->d_partitions[i];
+ if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
+ return (EBUSY);
+ /*
+ * Copy internally-set partition information
+ * if new label doesn't include it. XXX
+ */
+ if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
+ npp->p_fstype = opp->p_fstype;
+ npp->p_fsize = opp->p_fsize;
+ npp->p_frag = opp->p_frag;
+ npp->p_cpg = opp->p_cpg;
+ }
+ }
+ nlp->d_checksum = 0;
+ nlp->d_checksum = dkcksum(nlp);
+ *olp = *nlp;
+ return (0);
+}
+
+/*
+ * Write disk label back to device after modification.
+ * this means write out the Rigid disk blocks to represent the
+ * label. Hope the user was carefull.
+ */
+int
+writedisklabel(dev, strat, lp, clp)
+ dev_t dev;
+ void (*strat)();
+ register struct disklabel *lp;
+ struct cpu_disklabel *clp;
+{
+ struct buf *bp;
+ struct disklabel *dlp;
+ struct dos_partition *dp = clp->dosparts;
+ int error = 0, i;
+ int dospartoff = 0;
+
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* do dos partitions in the process of getting disklabel? */
+ if (dp) {
+ /* read master boot record */
+ bp->b_blkno = DOSBBSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_resid = 0;
+ (*strat)(bp);
+
+ if (((error = biowait(bp)) == 0)
+ && *(unsigned int *)(bp->b_data) == 0x8ec033fa) {
+ /* XXX how do we check veracity/bounds of this? */
+ bcopy(bp->b_data + DOSPARTOFF, dp, NDOSPART * sizeof(*dp));
+ for (i = 0; i < NDOSPART; i++, dp++) {
+ /* is this ours? */
+ if (dp->dp_size && dp->dp_typ == DOSPTYP_386BSD
+ && dospartoff == 0) {
+ dospartoff = dp->dp_start;
+ }
+ }
+ }
+
+ }
+ bp->b_blkno = dospartoff + LABELSECTOR;
+ bp->b_resid = 0;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_READ; /* get current label */
+ (*strat)(bp);
+ if (error = biowait(bp))
+ goto done;
+
+ dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
+ *dlp = *lp; /* struct assignment */
+
+ bp->b_flags = B_WRITE;
+ (*strat)(bp);
+ error = biowait(bp);
+
+done:
+ brelse(bp);
+ return (error);
+}
+
+
+/*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition. Adjust transfer
+ * if needed, and signal errors or early completion.
+ */
+int
+bounds_check_with_label(bp, lp, wlabel)
+ struct buf *bp;
+ struct disklabel *lp;
+ int wlabel;
+{
+#define dkpart(dev) (minor(dev) & 7)
+
+ struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
+ int labelsect = lp->d_partitions[RAW_PART].p_offset;
+ int maxsz = p->p_size;
+ int sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
+
+ /* overwriting disk label ? */
+ /* XXX should also protect bootstrap in first 8K */
+ if (bp->b_blkno + p->p_offset == LABELSECTOR + labelsect &&
+ (bp->b_flags & B_READ) == 0 && wlabel == 0) {
+ bp->b_error = EROFS;
+ goto bad;
+ }
+
+ /* beyond partition? */
+ if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
+ /* if exactly at end of disk, return an EOF */
+ if (bp->b_blkno == maxsz) {
+ bp->b_resid = bp->b_bcount;
+ return(0);
+ }
+ /* or truncate if part of it fits */
+ sz = maxsz - bp->b_blkno;
+ if (sz <= 0) {
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ bp->b_bcount = sz << DEV_BSHIFT;
+ }
+
+ /* calculate cylinder for disksort to order transfers with */
+ bp->b_resid = (bp->b_blkno + p->p_offset) / lp->d_secpercyl;
+ return(1);
+bad:
+ bp->b_flags |= B_ERROR;
+ return(-1);
+}
diff --git a/sys/arch/arc/arc/fp.S b/sys/arch/arc/arc/fp.S
new file mode 100644
index 00000000000..af2470947a1
--- /dev/null
+++ b/sys/arch/arc/arc/fp.S
@@ -0,0 +1,3611 @@
+/* $OpenBSD: fp.S,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)fp.s 8.1 (Berkeley) 6/10/93
+ * $Id: fp.S,v 1.1 1996/06/24 09:07:20 pefo Exp $
+ */
+
+/*
+ * Standard header stuff.
+ */
+
+#include <machine/regdef.h>
+#include <machine/asm.h>
+#include <machine/cpu.h>
+
+#include "assym.h"
+
+#define SEXP_INF 0xff
+#define DEXP_INF 0x7ff
+#define SEXP_BIAS 127
+#define DEXP_BIAS 1023
+#define SEXP_MIN -126
+#define DEXP_MIN -1022
+#define SEXP_MAX 127
+#define DEXP_MAX 1023
+#define WEXP_MAX 30 /* maximum unbiased exponent for int */
+#define WEXP_MIN -1 /* minimum unbiased exponent for int */
+#define SFRAC_BITS 23
+#define DFRAC_BITS 52
+#define SIMPL_ONE 0x00800000
+#define DIMPL_ONE 0x00100000
+#define SLEAD_ZEROS 31 - 23
+#define DLEAD_ZEROS 31 - 20
+#define STICKYBIT 1
+#define GUARDBIT 0x80000000
+#define SSIGNAL_NAN 0x00400000
+#define DSIGNAL_NAN 0x00080000
+#define SQUIET_NAN 0x003fffff
+#define DQUIET_NAN0 0x0007ffff
+#define DQUIET_NAN1 0xffffffff
+#define INT_MIN 0x80000000
+#define INT_MAX 0x7fffffff
+
+#define COND_UNORDERED 0x1
+#define COND_EQUAL 0x2
+#define COND_LESS 0x4
+#define COND_SIGNAL 0x8
+
+/*----------------------------------------------------------------------------
+ *
+ * MachEmulateFP --
+ *
+ * Emulate unimplemented floating point operations.
+ * This routine should only be called by MachFPInterrupt().
+ *
+ * MachEmulateFP(instr)
+ * unsigned instr;
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Floating point registers are modified according to instruction.
+ *
+ *----------------------------------------------------------------------------
+ */
+NON_LEAF(MachEmulateFP, STAND_FRAME_SIZE, ra)
+ subu sp, sp, STAND_FRAME_SIZE
+ sw ra, STAND_RA_OFFSET(sp)
+/*
+ * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
+ */
+ srl v0, a0, 21 - 2 # get FMT field
+ and v0, v0, 0xF << 2 # mask FMT field
+ and v1, a0, 0x3F # mask FUNC field
+ sll v1, v1, 5 # align for table lookup
+ bgt v0, 4 << 2, ill # illegal format
+
+ or v1, v1, v0
+ cfc1 a1, FPC_CSR # get exception register
+ lw a3, func_fmt_tbl(v1) # switch on FUNC & FMT
+ and a1, a1, ~FPC_EXCEPTION_UNIMPL # clear exception
+ ctc1 a1, FPC_CSR
+ j a3
+
+ .rdata
+func_fmt_tbl:
+ .word add_s # 0
+ .word add_d # 0
+ .word ill # 0
+ .word ill # 0
+ .word ill # 0
+ .word ill # 0
+ .word ill # 0
+ .word ill # 0
+ .word sub_s # 1
+ .word sub_d # 1
+ .word ill # 1
+ .word ill # 1
+ .word ill # 1
+ .word ill # 1
+ .word ill # 1
+ .word ill # 1
+ .word mul_s # 2
+ .word mul_d # 2
+ .word ill # 2
+ .word ill # 2
+ .word ill # 2
+ .word ill # 2
+ .word ill # 2
+ .word ill # 2
+ .word div_s # 3
+ .word div_d # 3
+ .word ill # 3
+ .word ill # 3
+ .word ill # 3
+ .word ill # 3
+ .word ill # 3
+ .word ill # 3
+ .word ill # 4
+ .word ill # 4
+ .word ill # 4
+ .word ill # 4
+ .word ill # 4
+ .word ill # 4
+ .word ill # 4
+ .word ill # 4
+ .word abs_s # 5
+ .word abs_d # 5
+ .word ill # 5
+ .word ill # 5
+ .word ill # 5
+ .word ill # 5
+ .word ill # 5
+ .word ill # 5
+ .word mov_s # 6
+ .word mov_d # 6
+ .word ill # 6
+ .word ill # 6
+ .word ill # 6
+ .word ill # 6
+ .word ill # 6
+ .word ill # 6
+ .word neg_s # 7
+ .word neg_d # 7
+ .word ill # 7
+ .word ill # 7
+ .word ill # 7
+ .word ill # 7
+ .word ill # 7
+ .word ill # 7
+ .word ill # 8
+ .word ill # 8
+ .word ill # 8
+ .word ill # 8
+ .word ill # 8
+ .word ill # 8
+ .word ill # 8
+ .word ill # 8
+ .word ill # 9
+ .word ill # 9
+ .word ill # 9
+ .word ill # 9
+ .word ill # 9
+ .word ill # 9
+ .word ill # 9
+ .word ill # 9
+ .word ill # 10
+ .word ill # 10
+ .word ill # 10
+ .word ill # 10
+ .word ill # 10
+ .word ill # 10
+ .word ill # 10
+ .word ill # 10
+ .word ill # 11
+ .word ill # 11
+ .word ill # 11
+ .word ill # 11
+ .word ill # 11
+ .word ill # 11
+ .word ill # 11
+ .word ill # 11
+ .word ill # 12
+ .word ill # 12
+ .word ill # 12
+ .word ill # 12
+ .word ill # 12
+ .word ill # 12
+ .word ill # 12
+ .word ill # 12
+ .word ill # 13
+ .word ill # 13
+ .word ill # 13
+ .word ill # 13
+ .word ill # 13
+ .word ill # 13
+ .word ill # 13
+ .word ill # 13
+ .word ill # 14
+ .word ill # 14
+ .word ill # 14
+ .word ill # 14
+ .word ill # 14
+ .word ill # 14
+ .word ill # 14
+ .word ill # 14
+ .word ill # 15
+ .word ill # 15
+ .word ill # 15
+ .word ill # 15
+ .word ill # 15
+ .word ill # 15
+ .word ill # 15
+ .word ill # 15
+ .word ill # 16
+ .word ill # 16
+ .word ill # 16
+ .word ill # 16
+ .word ill # 16
+ .word ill # 16
+ .word ill # 16
+ .word ill # 16
+ .word ill # 17
+ .word ill # 17
+ .word ill # 17
+ .word ill # 17
+ .word ill # 17
+ .word ill # 17
+ .word ill # 17
+ .word ill # 17
+ .word ill # 18
+ .word ill # 18
+ .word ill # 18
+ .word ill # 18
+ .word ill # 18
+ .word ill # 18
+ .word ill # 18
+ .word ill # 18
+ .word ill # 19
+ .word ill # 19
+ .word ill # 19
+ .word ill # 19
+ .word ill # 19
+ .word ill # 19
+ .word ill # 19
+ .word ill # 19
+ .word ill # 20
+ .word ill # 20
+ .word ill # 20
+ .word ill # 20
+ .word ill # 20
+ .word ill # 20
+ .word ill # 20
+ .word ill # 20
+ .word ill # 21
+ .word ill # 21
+ .word ill # 21
+ .word ill # 21
+ .word ill # 21
+ .word ill # 21
+ .word ill # 21
+ .word ill # 21
+ .word ill # 22
+ .word ill # 22
+ .word ill # 22
+ .word ill # 22
+ .word ill # 22
+ .word ill # 22
+ .word ill # 22
+ .word ill # 22
+ .word ill # 23
+ .word ill # 23
+ .word ill # 23
+ .word ill # 23
+ .word ill # 23
+ .word ill # 23
+ .word ill # 23
+ .word ill # 23
+ .word ill # 24
+ .word ill # 24
+ .word ill # 24
+ .word ill # 24
+ .word ill # 24
+ .word ill # 24
+ .word ill # 24
+ .word ill # 24
+ .word ill # 25
+ .word ill # 25
+ .word ill # 25
+ .word ill # 25
+ .word ill # 25
+ .word ill # 25
+ .word ill # 25
+ .word ill # 25
+ .word ill # 26
+ .word ill # 26
+ .word ill # 26
+ .word ill # 26
+ .word ill # 26
+ .word ill # 26
+ .word ill # 26
+ .word ill # 26
+ .word ill # 27
+ .word ill # 27
+ .word ill # 27
+ .word ill # 27
+ .word ill # 27
+ .word ill # 27
+ .word ill # 27
+ .word ill # 27
+ .word ill # 28
+ .word ill # 28
+ .word ill # 28
+ .word ill # 28
+ .word ill # 28
+ .word ill # 28
+ .word ill # 28
+ .word ill # 28
+ .word ill # 29
+ .word ill # 29
+ .word ill # 29
+ .word ill # 29
+ .word ill # 29
+ .word ill # 29
+ .word ill # 29
+ .word ill # 29
+ .word ill # 30
+ .word ill # 30
+ .word ill # 30
+ .word ill # 30
+ .word ill # 30
+ .word ill # 30
+ .word ill # 30
+ .word ill # 30
+ .word ill # 31
+ .word ill # 31
+ .word ill # 31
+ .word ill # 31
+ .word ill # 31
+ .word ill # 31
+ .word ill # 31
+ .word ill # 31
+ .word ill # 32
+ .word cvt_s_d # 32
+ .word ill # 32
+ .word ill # 32
+ .word cvt_s_w # 32
+ .word ill # 32
+ .word ill # 32
+ .word ill # 32
+ .word cvt_d_s # 33
+ .word ill # 33
+ .word ill # 33
+ .word ill # 33
+ .word cvt_d_w # 33
+ .word ill # 33
+ .word ill # 33
+ .word ill # 33
+ .word ill # 34
+ .word ill # 34
+ .word ill # 34
+ .word ill # 34
+ .word ill # 34
+ .word ill # 34
+ .word ill # 34
+ .word ill # 34
+ .word ill # 35
+ .word ill # 35
+ .word ill # 35
+ .word ill # 35
+ .word ill # 35
+ .word ill # 35
+ .word ill # 35
+ .word ill # 35
+ .word cvt_w_s # 36
+ .word cvt_w_d # 36
+ .word ill # 36
+ .word ill # 36
+ .word ill # 36
+ .word ill # 36
+ .word ill # 36
+ .word ill # 36
+ .word ill # 37
+ .word ill # 37
+ .word ill # 37
+ .word ill # 37
+ .word ill # 37
+ .word ill # 37
+ .word ill # 37
+ .word ill # 37
+ .word ill # 38
+ .word ill # 38
+ .word ill # 38
+ .word ill # 38
+ .word ill # 38
+ .word ill # 38
+ .word ill # 38
+ .word ill # 38
+ .word ill # 39
+ .word ill # 39
+ .word ill # 39
+ .word ill # 39
+ .word ill # 39
+ .word ill # 39
+ .word ill # 39
+ .word ill # 39
+ .word ill # 40
+ .word ill # 40
+ .word ill # 40
+ .word ill # 40
+ .word ill # 40
+ .word ill # 40
+ .word ill # 40
+ .word ill # 40
+ .word ill # 41
+ .word ill # 41
+ .word ill # 41
+ .word ill # 41
+ .word ill # 41
+ .word ill # 41
+ .word ill # 41
+ .word ill # 41
+ .word ill # 42
+ .word ill # 42
+ .word ill # 42
+ .word ill # 42
+ .word ill # 42
+ .word ill # 42
+ .word ill # 42
+ .word ill # 42
+ .word ill # 43
+ .word ill # 43
+ .word ill # 43
+ .word ill # 43
+ .word ill # 43
+ .word ill # 43
+ .word ill # 43
+ .word ill # 43
+ .word ill # 44
+ .word ill # 44
+ .word ill # 44
+ .word ill # 44
+ .word ill # 44
+ .word ill # 44
+ .word ill # 44
+ .word ill # 44
+ .word ill # 45
+ .word ill # 45
+ .word ill # 45
+ .word ill # 45
+ .word ill # 45
+ .word ill # 45
+ .word ill # 45
+ .word ill # 45
+ .word ill # 46
+ .word ill # 46
+ .word ill # 46
+ .word ill # 46
+ .word ill # 46
+ .word ill # 46
+ .word ill # 46
+ .word ill # 46
+ .word ill # 47
+ .word ill # 47
+ .word ill # 47
+ .word ill # 47
+ .word ill # 47
+ .word ill # 47
+ .word ill # 47
+ .word ill # 47
+ .word cmp_s # 48
+ .word cmp_d # 48
+ .word ill # 48
+ .word ill # 48
+ .word ill # 48
+ .word ill # 48
+ .word ill # 48
+ .word ill # 48
+ .word cmp_s # 49
+ .word cmp_d # 49
+ .word ill # 49
+ .word ill # 49
+ .word ill # 49
+ .word ill # 49
+ .word ill # 49
+ .word ill # 49
+ .word cmp_s # 50
+ .word cmp_d # 50
+ .word ill # 50
+ .word ill # 50
+ .word ill # 50
+ .word ill # 50
+ .word ill # 50
+ .word ill # 50
+ .word cmp_s # 51
+ .word cmp_d # 51
+ .word ill # 51
+ .word ill # 51
+ .word ill # 51
+ .word ill # 51
+ .word ill # 51
+ .word ill # 51
+ .word cmp_s # 52
+ .word cmp_d # 52
+ .word ill # 52
+ .word ill # 52
+ .word ill # 52
+ .word ill # 52
+ .word ill # 52
+ .word ill # 52
+ .word cmp_s # 53
+ .word cmp_d # 53
+ .word ill # 53
+ .word ill # 53
+ .word ill # 53
+ .word ill # 53
+ .word ill # 53
+ .word ill # 53
+ .word cmp_s # 54
+ .word cmp_d # 54
+ .word ill # 54
+ .word ill # 54
+ .word ill # 54
+ .word ill # 54
+ .word ill # 54
+ .word ill # 54
+ .word cmp_s # 55
+ .word cmp_d # 55
+ .word ill # 55
+ .word ill # 55
+ .word ill # 55
+ .word ill # 55
+ .word ill # 55
+ .word ill # 55
+ .word cmp_s # 56
+ .word cmp_d # 56
+ .word ill # 56
+ .word ill # 56
+ .word ill # 56
+ .word ill # 56
+ .word ill # 56
+ .word ill # 56
+ .word cmp_s # 57
+ .word cmp_d # 57
+ .word ill # 57
+ .word ill # 57
+ .word ill # 57
+ .word ill # 57
+ .word ill # 57
+ .word ill # 57
+ .word cmp_s # 58
+ .word cmp_d # 58
+ .word ill # 58
+ .word ill # 58
+ .word ill # 58
+ .word ill # 58
+ .word ill # 58
+ .word ill # 58
+ .word cmp_s # 59
+ .word cmp_d # 59
+ .word ill # 59
+ .word ill # 59
+ .word ill # 59
+ .word ill # 59
+ .word ill # 59
+ .word ill # 59
+ .word cmp_s # 60
+ .word cmp_d # 60
+ .word ill # 60
+ .word ill # 60
+ .word ill # 60
+ .word ill # 60
+ .word ill # 60
+ .word ill # 60
+ .word cmp_s # 61
+ .word cmp_d # 61
+ .word ill # 61
+ .word ill # 61
+ .word ill # 61
+ .word ill # 61
+ .word ill # 61
+ .word ill # 61
+ .word cmp_s # 62
+ .word cmp_d # 62
+ .word ill # 62
+ .word ill # 62
+ .word ill # 62
+ .word ill # 62
+ .word ill # 62
+ .word ill # 62
+ .word cmp_s # 63
+ .word cmp_d # 63
+ .word ill # 63
+ .word ill # 63
+ .word ill # 63
+ .word ill # 63
+ .word ill # 63
+ .word ill # 63
+ .text
+
+/*
+ * Single precision subtract.
+ */
+sub_s:
+ jal get_ft_fs_s
+ xor t4, t4, 1 # negate FT sign bit
+ b add_sub_s
+/*
+ * Single precision add.
+ */
+add_s:
+ jal get_ft_fs_s
+add_sub_s:
+ bne t1, SEXP_INF, 1f # is FS an infinity?
+ bne t5, SEXP_INF, result_fs_s # if FT is not inf, result=FS
+ bne t2, zero, result_fs_s # if FS is NAN, result is FS
+ bne t6, zero, result_ft_s # if FT is NAN, result is FT
+ bne t0, t4, invalid_s # both infinities same sign?
+ b result_fs_s # result is in FS
+1:
+ beq t5, SEXP_INF, result_ft_s # if FT is inf, result=FT
+ bne t1, zero, 4f # is FS a denormalized num?
+ beq t2, zero, 3f # is FS zero?
+ bne t5, zero, 2f # is FT a denormalized num?
+ beq t6, zero, result_fs_s # FT is zero, result=FS
+ jal renorm_fs_s
+ jal renorm_ft_s
+ b 5f
+2:
+ jal renorm_fs_s
+ subu t5, t5, SEXP_BIAS # unbias FT exponent
+ or t6, t6, SIMPL_ONE # set implied one bit
+ b 5f
+3:
+ bne t5, zero, result_ft_s # if FT != 0, result=FT
+ bne t6, zero, result_ft_s
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ bne v0, FPC_ROUND_RM, 1f # round to -infinity?
+ or t0, t0, t4 # compute result sign
+ b result_fs_s
+1:
+ and t0, t0, t4 # compute result sign
+ b result_fs_s
+4:
+ bne t5, zero, 2f # is FT a denormalized num?
+ beq t6, zero, result_fs_s # FT is zero, result=FS
+ subu t1, t1, SEXP_BIAS # unbias FS exponent
+ or t2, t2, SIMPL_ONE # set implied one bit
+ jal renorm_ft_s
+ b 5f
+2:
+ subu t1, t1, SEXP_BIAS # unbias FS exponent
+ or t2, t2, SIMPL_ONE # set implied one bit
+ subu t5, t5, SEXP_BIAS # unbias FT exponent
+ or t6, t6, SIMPL_ONE # set implied one bit
+/*
+ * Perform the addition.
+ */
+5:
+ move t8, zero # no shifted bits (sticky reg)
+ beq t1, t5, 4f # no shift needed
+ subu v0, t1, t5 # v0 = difference of exponents
+ move v1, v0 # v1 = abs(difference)
+ bge v0, zero, 1f
+ negu v1
+1:
+ ble v1, SFRAC_BITS+2, 2f # is difference too great?
+ li t8, STICKYBIT # set the sticky bit
+ bge v0, zero, 1f # check which exp is larger
+ move t1, t5 # result exp is FTs
+ move t2, zero # FSs fraction shifted is zero
+ b 4f
+1:
+ move t6, zero # FTs fraction shifted is zero
+ b 4f
+2:
+ li t9, 32 # compute 32 - abs(exp diff)
+ subu t9, t9, v1
+ bgt v0, zero, 3f # if FS > FT, shift FTs frac
+ move t1, t5 # FT > FS, result exp is FTs
+ sll t8, t2, t9 # save bits shifted out
+ srl t2, t2, v1 # shift FSs fraction
+ b 4f
+3:
+ sll t8, t6, t9 # save bits shifted out
+ srl t6, t6, v1 # shift FTs fraction
+4:
+ bne t0, t4, 1f # if signs differ, subtract
+ addu t2, t2, t6 # add fractions
+ b norm_s
+1:
+ blt t2, t6, 3f # subtract larger from smaller
+ bne t2, t6, 2f # if same, result=0
+ move t1, zero # result=0
+ move t2, zero
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ bne v0, FPC_ROUND_RM, 1f # round to -infinity?
+ or t0, t0, t4 # compute result sign
+ b result_fs_s
+1:
+ and t0, t0, t4 # compute result sign
+ b result_fs_s
+2:
+ sltu t9, zero, t8 # compute t2:zero - t6:t8
+ subu t8, zero, t8
+ subu t2, t2, t6 # subtract fractions
+ subu t2, t2, t9 # subtract barrow
+ b norm_s
+3:
+ move t0, t4 # sign of result = FTs
+ sltu t9, zero, t8 # compute t6:zero - t2:t8
+ subu t8, zero, t8
+ subu t2, t6, t2 # subtract fractions
+ subu t2, t2, t9 # subtract barrow
+ b norm_s
+
+/*
+ * Double precision subtract.
+ */
+sub_d:
+ jal get_ft_fs_d
+ xor t4, t4, 1 # negate sign bit
+ b add_sub_d
+/*
+ * Double precision add.
+ */
+add_d:
+ jal get_ft_fs_d
+add_sub_d:
+ bne t1, DEXP_INF, 1f # is FS an infinity?
+ bne t5, DEXP_INF, result_fs_d # if FT is not inf, result=FS
+ bne t2, zero, result_fs_d # if FS is NAN, result is FS
+ bne t3, zero, result_fs_d
+ bne t6, zero, result_ft_d # if FT is NAN, result is FT
+ bne t7, zero, result_ft_d
+ bne t0, t4, invalid_d # both infinities same sign?
+ b result_fs_d # result is in FS
+1:
+ beq t5, DEXP_INF, result_ft_d # if FT is inf, result=FT
+ bne t1, zero, 4f # is FS a denormalized num?
+ bne t2, zero, 1f # is FS zero?
+ beq t3, zero, 3f
+1:
+ bne t5, zero, 2f # is FT a denormalized num?
+ bne t6, zero, 1f
+ beq t7, zero, result_fs_d # FT is zero, result=FS
+1:
+ jal renorm_fs_d
+ jal renorm_ft_d
+ b 5f
+2:
+ jal renorm_fs_d
+ subu t5, t5, DEXP_BIAS # unbias FT exponent
+ or t6, t6, DIMPL_ONE # set implied one bit
+ b 5f
+3:
+ bne t5, zero, result_ft_d # if FT != 0, result=FT
+ bne t6, zero, result_ft_d
+ bne t7, zero, result_ft_d
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ bne v0, FPC_ROUND_RM, 1f # round to -infinity?
+ or t0, t0, t4 # compute result sign
+ b result_fs_d
+1:
+ and t0, t0, t4 # compute result sign
+ b result_fs_d
+4:
+ bne t5, zero, 2f # is FT a denormalized num?
+ bne t6, zero, 1f
+ beq t7, zero, result_fs_d # FT is zero, result=FS
+1:
+ subu t1, t1, DEXP_BIAS # unbias FS exponent
+ or t2, t2, DIMPL_ONE # set implied one bit
+ jal renorm_ft_d
+ b 5f
+2:
+ subu t1, t1, DEXP_BIAS # unbias FS exponent
+ or t2, t2, DIMPL_ONE # set implied one bit
+ subu t5, t5, DEXP_BIAS # unbias FT exponent
+ or t6, t6, DIMPL_ONE # set implied one bit
+/*
+ * Perform the addition.
+ */
+5:
+ move t8, zero # no shifted bits (sticky reg)
+ beq t1, t5, 4f # no shift needed
+ subu v0, t1, t5 # v0 = difference of exponents
+ move v1, v0 # v1 = abs(difference)
+ bge v0, zero, 1f
+ negu v1
+1:
+ ble v1, DFRAC_BITS+2, 2f # is difference too great?
+ li t8, STICKYBIT # set the sticky bit
+ bge v0, zero, 1f # check which exp is larger
+ move t1, t5 # result exp is FTs
+ move t2, zero # FSs fraction shifted is zero
+ move t3, zero
+ b 4f
+1:
+ move t6, zero # FTs fraction shifted is zero
+ move t7, zero
+ b 4f
+2:
+ li t9, 32
+ bge v0, zero, 3f # if FS > FT, shift FTs frac
+ move t1, t5 # FT > FS, result exp is FTs
+ blt v1, t9, 1f # shift right by < 32?
+ subu v1, v1, t9
+ subu t9, t9, v1
+ sll t8, t2, t9 # save bits shifted out
+ sltu t9, zero, t3 # dont lose any one bits
+ or t8, t8, t9 # save sticky bit
+ srl t3, t2, v1 # shift FSs fraction
+ move t2, zero
+ b 4f
+1:
+ subu t9, t9, v1
+ sll t8, t3, t9 # save bits shifted out
+ srl t3, t3, v1 # shift FSs fraction
+ sll t9, t2, t9 # save bits shifted out of t2
+ or t3, t3, t9 # and put into t3
+ srl t2, t2, v1
+ b 4f
+3:
+ blt v1, t9, 1f # shift right by < 32?
+ subu v1, v1, t9
+ subu t9, t9, v1
+ sll t8, t6, t9 # save bits shifted out
+ srl t7, t6, v1 # shift FTs fraction
+ move t6, zero
+ b 4f
+1:
+ subu t9, t9, v1
+ sll t8, t7, t9 # save bits shifted out
+ srl t7, t7, v1 # shift FTs fraction
+ sll t9, t6, t9 # save bits shifted out of t2
+ or t7, t7, t9 # and put into t3
+ srl t6, t6, v1
+4:
+ bne t0, t4, 1f # if signs differ, subtract
+ addu t3, t3, t7 # add fractions
+ sltu t9, t3, t7 # compute carry
+ addu t2, t2, t6 # add fractions
+ addu t2, t2, t9 # add carry
+ b norm_d
+1:
+ blt t2, t6, 3f # subtract larger from smaller
+ bne t2, t6, 2f
+ bltu t3, t7, 3f
+ bne t3, t7, 2f # if same, result=0
+ move t1, zero # result=0
+ move t2, zero
+ move t3, zero
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ bne v0, FPC_ROUND_RM, 1f # round to -infinity?
+ or t0, t0, t4 # compute result sign
+ b result_fs_d
+1:
+ and t0, t0, t4 # compute result sign
+ b result_fs_d
+2:
+ beq t8, zero, 1f # compute t2:t3:zero - t6:t7:t8
+ subu t8, zero, t8
+ sltu v0, t3, 1 # compute barrow out
+ subu t3, t3, 1 # subtract barrow
+ subu t2, t2, v0
+1:
+ sltu v0, t3, t7
+ subu t3, t3, t7 # subtract fractions
+ subu t2, t2, t6 # subtract fractions
+ subu t2, t2, v0 # subtract barrow
+ b norm_d
+3:
+ move t0, t4 # sign of result = FTs
+ beq t8, zero, 1f # compute t6:t7:zero - t2:t3:t8
+ subu t8, zero, t8
+ sltu v0, t7, 1 # compute barrow out
+ subu t7, t7, 1 # subtract barrow
+ subu t6, t6, v0
+1:
+ sltu v0, t7, t3
+ subu t3, t7, t3 # subtract fractions
+ subu t2, t6, t2 # subtract fractions
+ subu t2, t2, v0 # subtract barrow
+ b norm_d
+
+/*
+ * Single precision multiply.
+ */
+mul_s:
+ jal get_ft_fs_s
+ xor t0, t0, t4 # compute sign of result
+ move t4, t0
+ bne t1, SEXP_INF, 2f # is FS an infinity?
+ bne t2, zero, result_fs_s # if FS is a NAN, result=FS
+ bne t5, SEXP_INF, 1f # FS is inf, is FT an infinity?
+ bne t6, zero, result_ft_s # if FT is a NAN, result=FT
+ b result_fs_s # result is infinity
+1:
+ bne t5, zero, result_fs_s # inf * zero? if no, result=FS
+ bne t6, zero, result_fs_s
+ b invalid_s # infinity * zero is invalid
+2:
+ bne t5, SEXP_INF, 1f # FS != inf, is FT an infinity?
+ bne t1, zero, result_ft_s # zero * inf? if no, result=FT
+ bne t2, zero, result_ft_s
+ bne t6, zero, result_ft_s # if FT is a NAN, result=FT
+ b invalid_s # zero * infinity is invalid
+1:
+ bne t1, zero, 1f # is FS zero?
+ beq t2, zero, result_fs_s # result is zero
+ jal renorm_fs_s
+ b 2f
+1:
+ subu t1, t1, SEXP_BIAS # unbias FS exponent
+ or t2, t2, SIMPL_ONE # set implied one bit
+2:
+ bne t5, zero, 1f # is FT zero?
+ beq t6, zero, result_ft_s # result is zero
+ jal renorm_ft_s
+ b 2f
+1:
+ subu t5, t5, SEXP_BIAS # unbias FT exponent
+ or t6, t6, SIMPL_ONE # set implied one bit
+2:
+ addu t1, t1, t5 # compute result exponent
+ addu t1, t1, 9 # account for binary point
+ multu t2, t6 # multiply fractions
+ mflo t8
+ mfhi t2
+ b norm_s
+
+/*
+ * Double precision multiply.
+ */
+mul_d:
+ jal get_ft_fs_d
+ xor t0, t0, t4 # compute sign of result
+ move t4, t0
+ bne t1, DEXP_INF, 2f # is FS an infinity?
+ bne t2, zero, result_fs_d # if FS is a NAN, result=FS
+ bne t3, zero, result_fs_d
+ bne t5, DEXP_INF, 1f # FS is inf, is FT an infinity?
+ bne t6, zero, result_ft_d # if FT is a NAN, result=FT
+ bne t7, zero, result_ft_d
+ b result_fs_d # result is infinity
+1:
+ bne t5, zero, result_fs_d # inf * zero? if no, result=FS
+ bne t6, zero, result_fs_d
+ bne t7, zero, result_fs_d
+ b invalid_d # infinity * zero is invalid
+2:
+ bne t5, DEXP_INF, 1f # FS != inf, is FT an infinity?
+ bne t1, zero, result_ft_d # zero * inf? if no, result=FT
+ bne t2, zero, result_ft_d # if FS is a NAN, result=FS
+ bne t3, zero, result_ft_d
+ bne t6, zero, result_ft_d # if FT is a NAN, result=FT
+ bne t7, zero, result_ft_d
+ b invalid_d # zero * infinity is invalid
+1:
+ bne t1, zero, 2f # is FS zero?
+ bne t2, zero, 1f
+ beq t3, zero, result_fs_d # result is zero
+1:
+ jal renorm_fs_d
+ b 3f
+2:
+ subu t1, t1, DEXP_BIAS # unbias FS exponent
+ or t2, t2, DIMPL_ONE # set implied one bit
+3:
+ bne t5, zero, 2f # is FT zero?
+ bne t6, zero, 1f
+ beq t7, zero, result_ft_d # result is zero
+1:
+ jal renorm_ft_d
+ b 3f
+2:
+ subu t5, t5, DEXP_BIAS # unbias FT exponent
+ or t6, t6, DIMPL_ONE # set implied one bit
+3:
+ addu t1, t1, t5 # compute result exponent
+ addu t1, t1, 12 # ???
+ multu t3, t7 # multiply fractions (low * low)
+ move t4, t2 # free up t2,t3 for result
+ move t5, t3
+ mflo a3 # save low order bits
+ mfhi t8
+ not v0, t8
+ multu t4, t7 # multiply FS(high) * FT(low)
+ mflo v1
+ mfhi t3 # init low result
+ sltu v0, v0, v1 # compute carry
+ addu t8, v1
+ multu t5, t6 # multiply FS(low) * FT(high)
+ addu t3, t3, v0 # add carry
+ not v0, t8
+ mflo v1
+ mfhi t2
+ sltu v0, v0, v1
+ addu t8, v1
+ multu t4, t6 # multiply FS(high) * FT(high)
+ addu t3, v0
+ not v1, t3
+ sltu v1, v1, t2
+ addu t3, t2
+ not v0, t3
+ mfhi t2
+ addu t2, v1
+ mflo v1
+ sltu v0, v0, v1
+ addu t2, v0
+ addu t3, v1
+ sltu a3, zero, a3 # reduce t8,a3 to just t8
+ or t8, a3
+ b norm_d
+
+/*
+ * Single precision divide.
+ */
+div_s:
+ jal get_ft_fs_s
+ xor t0, t0, t4 # compute sign of result
+ move t4, t0
+ bne t1, SEXP_INF, 1f # is FS an infinity?
+ bne t2, zero, result_fs_s # if FS is NAN, result is FS
+ bne t5, SEXP_INF, result_fs_s # is FT an infinity?
+ bne t6, zero, result_ft_s # if FT is NAN, result is FT
+ b invalid_s # infinity/infinity is invalid
+1:
+ bne t5, SEXP_INF, 1f # is FT an infinity?
+ bne t6, zero, result_ft_s # if FT is NAN, result is FT
+ move t1, zero # x / infinity is zero
+ move t2, zero
+ b result_fs_s
+1:
+ bne t1, zero, 2f # is FS zero?
+ bne t2, zero, 1f
+ bne t5, zero, result_fs_s # FS=zero, is FT zero?
+ beq t6, zero, invalid_s # 0 / 0
+ b result_fs_s # result = zero
+1:
+ jal renorm_fs_s
+ b 3f
+2:
+ subu t1, t1, SEXP_BIAS # unbias FS exponent
+ or t2, t2, SIMPL_ONE # set implied one bit
+3:
+ bne t5, zero, 2f # is FT zero?
+ bne t6, zero, 1f
+ or a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0
+ and v0, a1, FPC_ENABLE_DIV0 # trap enabled?
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # save exceptions
+ li t1, SEXP_INF # result is infinity
+ move t2, zero
+ b result_fs_s
+1:
+ jal renorm_ft_s
+ b 3f
+2:
+ subu t5, t5, SEXP_BIAS # unbias FT exponent
+ or t6, t6, SIMPL_ONE # set implied one bit
+3:
+ subu t1, t1, t5 # compute exponent
+ subu t1, t1, 3 # compensate for result position
+ li v0, SFRAC_BITS+3 # number of bits to divide
+ move t8, t2 # init dividend
+ move t2, zero # init result
+1:
+ bltu t8, t6, 3f # is dividend >= divisor?
+2:
+ subu t8, t8, t6 # subtract divisor from dividend
+ or t2, t2, 1 # remember that we did
+ bne t8, zero, 3f # if not done, continue
+ sll t2, t2, v0 # shift result to final position
+ b norm_s
+3:
+ sll t8, t8, 1 # shift dividend
+ sll t2, t2, 1 # shift result
+ subu v0, v0, 1 # are we done?
+ bne v0, zero, 1b # no, continue
+ b norm_s
+
+/*
+ * Double precision divide.
+ */
+div_d:
+ jal get_ft_fs_d
+ xor t0, t0, t4 # compute sign of result
+ move t4, t0
+ bne t1, DEXP_INF, 1f # is FS an infinity?
+ bne t2, zero, result_fs_d # if FS is NAN, result is FS
+ bne t3, zero, result_fs_d
+ bne t5, DEXP_INF, result_fs_d # is FT an infinity?
+ bne t6, zero, result_ft_d # if FT is NAN, result is FT
+ bne t7, zero, result_ft_d
+ b invalid_d # infinity/infinity is invalid
+1:
+ bne t5, DEXP_INF, 1f # is FT an infinity?
+ bne t6, zero, result_ft_d # if FT is NAN, result is FT
+ bne t7, zero, result_ft_d
+ move t1, zero # x / infinity is zero
+ move t2, zero
+ move t3, zero
+ b result_fs_d
+1:
+ bne t1, zero, 2f # is FS zero?
+ bne t2, zero, 1f
+ bne t3, zero, 1f
+ bne t5, zero, result_fs_d # FS=zero, is FT zero?
+ bne t6, zero, result_fs_d
+ beq t7, zero, invalid_d # 0 / 0
+ b result_fs_d # result = zero
+1:
+ jal renorm_fs_d
+ b 3f
+2:
+ subu t1, t1, DEXP_BIAS # unbias FS exponent
+ or t2, t2, DIMPL_ONE # set implied one bit
+3:
+ bne t5, zero, 2f # is FT zero?
+ bne t6, zero, 1f
+ bne t7, zero, 1f
+ or a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0
+ and v0, a1, FPC_ENABLE_DIV0 # trap enabled?
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # Save exceptions
+ li t1, DEXP_INF # result is infinity
+ move t2, zero
+ move t3, zero
+ b result_fs_d
+1:
+ jal renorm_ft_d
+ b 3f
+2:
+ subu t5, t5, DEXP_BIAS # unbias FT exponent
+ or t6, t6, DIMPL_ONE # set implied one bit
+3:
+ subu t1, t1, t5 # compute exponent
+ subu t1, t1, 3 # compensate for result position
+ li v0, DFRAC_BITS+3 # number of bits to divide
+ move t8, t2 # init dividend
+ move t9, t3
+ move t2, zero # init result
+ move t3, zero
+1:
+ bltu t8, t6, 3f # is dividend >= divisor?
+ bne t8, t6, 2f
+ bltu t9, t7, 3f
+2:
+ sltu v1, t9, t7 # subtract divisor from dividend
+ subu t9, t9, t7
+ subu t8, t8, t6
+ subu t8, t8, v1
+ or t3, t3, 1 # remember that we did
+ bne t8, zero, 3f # if not done, continue
+ bne t9, zero, 3f
+ li v1, 32 # shift result to final position
+ blt v0, v1, 2f # shift < 32 bits?
+ subu v0, v0, v1 # shift by > 32 bits
+ sll t2, t3, v0 # shift upper part
+ move t3, zero
+ b norm_d
+2:
+ subu v1, v1, v0 # shift by < 32 bits
+ sll t2, t2, v0 # shift upper part
+ srl t9, t3, v1 # save bits shifted out
+ or t2, t2, t9 # and put into upper part
+ sll t3, t3, v0
+ b norm_d
+3:
+ sll t8, t8, 1 # shift dividend
+ srl v1, t9, 31 # save bit shifted out
+ or t8, t8, v1 # and put into upper part
+ sll t9, t9, 1
+ sll t2, t2, 1 # shift result
+ srl v1, t3, 31 # save bit shifted out
+ or t2, t2, v1 # and put into upper part
+ sll t3, t3, 1
+ subu v0, v0, 1 # are we done?
+ bne v0, zero, 1b # no, continue
+ sltu v0, zero, t9 # be sure to save any one bits
+ or t8, t8, v0 # from the lower remainder
+ b norm_d
+
+/*
+ * Single precision absolute value.
+ */
+abs_s:
+ jal get_fs_s
+ move t0, zero # set sign positive
+ b result_fs_s
+
+/*
+ * Double precision absolute value.
+ */
+abs_d:
+ jal get_fs_d
+ move t0, zero # set sign positive
+ b result_fs_d
+
+/*
+ * Single precision move.
+ */
+mov_s:
+ jal get_fs_s
+ b result_fs_s
+
+/*
+ * Double precision move.
+ */
+mov_d:
+ jal get_fs_d
+ b result_fs_d
+
+/*
+ * Single precision negate.
+ */
+neg_s:
+ jal get_fs_s
+ xor t0, t0, 1 # reverse sign
+ b result_fs_s
+
+/*
+ * Double precision negate.
+ */
+neg_d:
+ jal get_fs_d
+ xor t0, t0, 1 # reverse sign
+ b result_fs_d
+
+/*
+ * Convert double to single.
+ */
+cvt_s_d:
+ jal get_fs_d
+ bne t1, DEXP_INF, 1f # is FS an infinity?
+ li t1, SEXP_INF # convert to single
+ sll t2, t2, 3 # convert D fraction to S
+ srl t8, t3, 32 - 3
+ or t2, t2, t8
+ b result_fs_s
+1:
+ bne t1, zero, 2f # is FS zero?
+ bne t2, zero, 1f
+ beq t3, zero, result_fs_s # result=0
+1:
+ jal renorm_fs_d
+ subu t1, t1, 3 # correct exp for shift below
+ b 3f
+2:
+ subu t1, t1, DEXP_BIAS # unbias exponent
+ or t2, t2, DIMPL_ONE # add implied one bit
+3:
+ sll t2, t2, 3 # convert D fraction to S
+ srl t8, t3, 32 - 3
+ or t2, t2, t8
+ sll t8, t3, 3
+ b norm_noshift_s
+
+/*
+ * Convert integer to single.
+ */
+cvt_s_w:
+ jal get_fs_int
+ bne t2, zero, 1f # check for zero
+ move t1, zero
+ b result_fs_s
+/*
+ * Find out how many leading zero bits are in t2 and put in t9.
+ */
+1:
+ move v0, t2
+ move t9, zero
+ srl v1, v0, 16
+ bne v1, zero, 1f
+ addu t9, 16
+ sll v0, 16
+1:
+ srl v1, v0, 24
+ bne v1, zero, 1f
+ addu t9, 8
+ sll v0, 8
+1:
+ srl v1, v0, 28
+ bne v1, zero, 1f
+ addu t9, 4
+ sll v0, 4
+1:
+ srl v1, v0, 30
+ bne v1, zero, 1f
+ addu t9, 2
+ sll v0, 2
+1:
+ srl v1, v0, 31
+ bne v1, zero, 1f
+ addu t9, 1
+/*
+ * Now shift t2 the correct number of bits.
+ */
+1:
+ subu t9, t9, SLEAD_ZEROS # dont count leading zeros
+ li t1, 23 # init exponent
+ subu t1, t1, t9 # compute exponent
+ beq t9, zero, 1f
+ li v0, 32
+ blt t9, zero, 2f # if shift < 0, shift right
+ subu v0, v0, t9
+ sll t2, t2, t9 # shift left
+1:
+ add t1, t1, SEXP_BIAS # bias exponent
+ and t2, t2, ~SIMPL_ONE # clear implied one bit
+ b result_fs_s
+2:
+ negu t9 # shift right by t9
+ subu v0, v0, t9
+ sll t8, t2, v0 # save bits shifted out
+ srl t2, t2, t9
+ b norm_noshift_s
+
+/*
+ * Convert single to double.
+ */
+cvt_d_s:
+ jal get_fs_s
+ move t3, zero
+ bne t1, SEXP_INF, 1f # is FS an infinity?
+ li t1, DEXP_INF # convert to double
+ b result_fs_d
+1:
+ bne t1, zero, 2f # is FS denormalized or zero?
+ beq t2, zero, result_fs_d # is FS zero?
+ jal renorm_fs_s
+ move t8, zero
+ b norm_d
+2:
+ addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly
+ sll t3, t2, 32 - 3 # convert S fraction to D
+ srl t2, t2, 3
+ b result_fs_d
+
+/*
+ * Convert integer to double.
+ */
+cvt_d_w:
+ jal get_fs_int
+ bne t2, zero, 1f # check for zero
+ move t1, zero # result=0
+ move t3, zero
+ b result_fs_d
+/*
+ * Find out how many leading zero bits are in t2 and put in t9.
+ */
+1:
+ move v0, t2
+ move t9, zero
+ srl v1, v0, 16
+ bne v1, zero, 1f
+ addu t9, 16
+ sll v0, 16
+1:
+ srl v1, v0, 24
+ bne v1, zero, 1f
+ addu t9, 8
+ sll v0, 8
+1:
+ srl v1, v0, 28
+ bne v1, zero, 1f
+ addu t9, 4
+ sll v0, 4
+1:
+ srl v1, v0, 30
+ bne v1, zero, 1f
+ addu t9, 2
+ sll v0, 2
+1:
+ srl v1, v0, 31
+ bne v1, zero, 1f
+ addu t9, 1
+/*
+ * Now shift t2 the correct number of bits.
+ */
+1:
+ subu t9, t9, DLEAD_ZEROS # dont count leading zeros
+ li t1, DEXP_BIAS + 20 # init exponent
+ subu t1, t1, t9 # compute exponent
+ beq t9, zero, 1f
+ li v0, 32
+ blt t9, zero, 2f # if shift < 0, shift right
+ subu v0, v0, t9
+ sll t2, t2, t9 # shift left
+1:
+ and t2, t2, ~DIMPL_ONE # clear implied one bit
+ move t3, zero
+ b result_fs_d
+2:
+ negu t9 # shift right by t9
+ subu v0, v0, t9
+ sll t3, t2, v0
+ srl t2, t2, t9
+ and t2, t2, ~DIMPL_ONE # clear implied one bit
+ b result_fs_d
+
+/*
+ * Convert single to integer.
+ */
+cvt_w_s:
+ jal get_fs_s
+ bne t1, SEXP_INF, 1f # is FS an infinity?
+ bne t2, zero, invalid_w # invalid conversion
+1:
+ bne t1, zero, 1f # is FS zero?
+ beq t2, zero, result_fs_w # result is zero
+ move t2, zero # result is an inexact zero
+ b inexact_w
+1:
+ subu t1, t1, SEXP_BIAS # unbias exponent
+ or t2, t2, SIMPL_ONE # add implied one bit
+ sll t3, t2, 32 - 3 # convert S fraction to D
+ srl t2, t2, 3
+ b cvt_w
+
+/*
+ * Convert double to integer.
+ */
+cvt_w_d:
+ jal get_fs_d
+ bne t1, DEXP_INF, 1f # is FS an infinity?
+ bne t2, zero, invalid_w # invalid conversion
+ bne t3, zero, invalid_w # invalid conversion
+1:
+ bne t1, zero, 2f # is FS zero?
+ bne t2, zero, 1f
+ beq t3, zero, result_fs_w # result is zero
+1:
+ move t2, zero # result is an inexact zero
+ b inexact_w
+2:
+ subu t1, t1, DEXP_BIAS # unbias exponent
+ or t2, t2, DIMPL_ONE # add implied one bit
+cvt_w:
+ blt t1, WEXP_MIN, underflow_w # is exponent too small?
+ li v0, WEXP_MAX+1
+ bgt t1, v0, overflow_w # is exponent too large?
+ bne t1, v0, 1f # special check for INT_MIN
+ beq t0, zero, overflow_w # if positive, overflow
+ bne t2, DIMPL_ONE, overflow_w
+ bne t3, zero, overflow_w
+ li t2, INT_MIN # result is INT_MIN
+ b result_fs_w
+1:
+ subu v0, t1, 20 # compute amount to shift
+ beq v0, zero, 2f # is shift needed?
+ li v1, 32
+ blt v0, zero, 1f # if shift < 0, shift right
+ subu v1, v1, v0 # shift left
+ sll t2, t2, v0
+ srl t9, t3, v1 # save bits shifted out of t3
+ or t2, t2, t9 # and put into t2
+ sll t3, t3, v0 # shift FSs fraction
+ b 2f
+1:
+ negu v0 # shift right by v0
+ subu v1, v1, v0
+ sll t8, t3, v1 # save bits shifted out
+ sltu t8, zero, t8 # dont lose any ones
+ srl t3, t3, v0 # shift FSs fraction
+ or t3, t3, t8
+ sll t9, t2, v1 # save bits shifted out of t2
+ or t3, t3, t9 # and put into t3
+ srl t2, t2, v0
+/*
+ * round result (t0 is sign, t2 is integer part, t3 is fractional part).
+ */
+2:
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ beq v0, FPC_ROUND_RN, 3f # round to nearest
+ beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate)
+ beq v0, FPC_ROUND_RP, 1f # round to +infinity
+ beq t0, zero, 5f # if sign is positive, truncate
+ b 2f
+1:
+ bne t0, zero, 5f # if sign is negative, truncate
+2:
+ beq t3, zero, 5f # if no fraction bits, continue
+ addu t2, t2, 1 # add rounding bit
+ blt t2, zero, overflow_w # overflow?
+ b 5f
+3:
+ li v0, GUARDBIT # load guard bit for rounding
+ addu v0, v0, t3 # add remainder
+ sltu v1, v0, t3 # compute carry out
+ beq v1, zero, 4f # if no carry, continue
+ addu t2, t2, 1 # add carry to result
+ blt t2, zero, overflow_w # overflow?
+4:
+ bne v0, zero, 5f # if rounded remainder is zero
+ and t2, t2, ~1 # clear LSB (round to nearest)
+5:
+ beq t0, zero, 1f # result positive?
+ negu t2 # convert to negative integer
+1:
+ beq t3, zero, result_fs_w # is result exact?
+/*
+ * Handle inexact exception.
+ */
+inexact_w:
+ or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+ and v0, a1, FPC_ENABLE_INEXACT
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # save exceptions
+ b result_fs_w
+
+/*
+ * Conversions to integer which overflow will trap (if enabled),
+ * or generate an inexact trap (if enabled),
+ * or generate an invalid exception.
+ */
+overflow_w:
+ or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
+ and v0, a1, FPC_ENABLE_OVERFLOW
+ bne v0, zero, fpe_trap
+ and v0, a1, FPC_ENABLE_INEXACT
+ bne v0, zero, inexact_w # inexact traps enabled?
+ b invalid_w
+
+/*
+ * Conversions to integer which underflow will trap (if enabled),
+ * or generate an inexact trap (if enabled),
+ * or generate an invalid exception.
+ */
+underflow_w:
+ or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+ and v0, a1, FPC_ENABLE_UNDERFLOW
+ bne v0, zero, fpe_trap
+ and v0, a1, FPC_ENABLE_INEXACT
+ bne v0, zero, inexact_w # inexact traps enabled?
+ b invalid_w
+
+/*
+ * Compare single.
+ */
+cmp_s:
+ jal get_cmp_s
+ bne t1, SEXP_INF, 1f # is FS an infinity?
+ bne t2, zero, unordered # FS is a NAN
+1:
+ bne t5, SEXP_INF, 2f # is FT an infinity?
+ bne t6, zero, unordered # FT is a NAN
+2:
+ sll t1, t1, 23 # reassemble exp & frac
+ or t1, t1, t2
+ sll t5, t5, 23 # reassemble exp & frac
+ or t5, t5, t6
+ beq t0, zero, 1f # is FS positive?
+ negu t1
+1:
+ beq t4, zero, 1f # is FT positive?
+ negu t5
+1:
+ li v0, COND_LESS
+ blt t1, t5, test_cond # is FS < FT?
+ li v0, COND_EQUAL
+ beq t1, t5, test_cond # is FS == FT?
+ move v0, zero # FS > FT
+ b test_cond
+
+/*
+ * Compare double.
+ */
+cmp_d:
+ jal get_cmp_d
+ bne t1, DEXP_INF, 1f # is FS an infinity?
+ bne t2, zero, unordered
+ bne t3, zero, unordered # FS is a NAN
+1:
+ bne t5, DEXP_INF, 2f # is FT an infinity?
+ bne t6, zero, unordered
+ bne t7, zero, unordered # FT is a NAN
+2:
+ sll t1, t1, 20 # reassemble exp & frac
+ or t1, t1, t2
+ sll t5, t5, 20 # reassemble exp & frac
+ or t5, t5, t6
+ beq t0, zero, 1f # is FS positive?
+ not t3 # negate t1,t3
+ not t1
+ addu t3, t3, 1
+ seq v0, t3, zero # compute carry
+ addu t1, t1, v0
+1:
+ beq t4, zero, 1f # is FT positive?
+ not t7 # negate t5,t7
+ not t5
+ addu t7, t7, 1
+ seq v0, t7, zero # compute carry
+ addu t5, t5, v0
+1:
+ li v0, COND_LESS
+ blt t1, t5, test_cond # is FS(MSW) < FT(MSW)?
+ move v0, zero
+ bne t1, t5, test_cond # is FS(MSW) > FT(MSW)?
+ li v0, COND_LESS
+ bltu t3, t7, test_cond # is FS(LSW) < FT(LSW)?
+ li v0, COND_EQUAL
+ beq t3, t7, test_cond # is FS(LSW) == FT(LSW)?
+ move v0, zero # FS > FT
+test_cond:
+ and v0, v0, a0 # condition match instruction?
+set_cond:
+ bne v0, zero, 1f
+ and a1, a1, ~FPC_COND_BIT # clear condition bit
+ b 2f
+1:
+ or a1, a1, FPC_COND_BIT # set condition bit
+2:
+ ctc1 a1, FPC_CSR # save condition bit
+ b done
+
+unordered:
+ and v0, a0, COND_UNORDERED # this cmp match unordered?
+ bne v0, zero, 1f
+ and a1, a1, ~FPC_COND_BIT # clear condition bit
+ b 2f
+1:
+ or a1, a1, FPC_COND_BIT # set condition bit
+2:
+ and v0, a0, COND_SIGNAL
+ beq v0, zero, 1f # is this a signaling cmp?
+ or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
+ and v0, a1, FPC_ENABLE_INVALID
+ bne v0, zero, fpe_trap
+1:
+ ctc1 a1, FPC_CSR # save condition bit
+ b done
+
+/*
+ * Determine the amount to shift the fraction in order to restore the
+ * normalized position. After that, round and handle exceptions.
+ */
+norm_s:
+ move v0, t2
+ move t9, zero # t9 = num of leading zeros
+ bne t2, zero, 1f
+ move v0, t8
+ addu t9, 32
+1:
+ srl v1, v0, 16
+ bne v1, zero, 1f
+ addu t9, 16
+ sll v0, 16
+1:
+ srl v1, v0, 24
+ bne v1, zero, 1f
+ addu t9, 8
+ sll v0, 8
+1:
+ srl v1, v0, 28
+ bne v1, zero, 1f
+ addu t9, 4
+ sll v0, 4
+1:
+ srl v1, v0, 30
+ bne v1, zero, 1f
+ addu t9, 2
+ sll v0, 2
+1:
+ srl v1, v0, 31
+ bne v1, zero, 1f
+ addu t9, 1
+/*
+ * Now shift t2,t8 the correct number of bits.
+ */
+1:
+ subu t9, t9, SLEAD_ZEROS # dont count leading zeros
+ subu t1, t1, t9 # adjust the exponent
+ beq t9, zero, norm_noshift_s
+ li v1, 32
+ blt t9, zero, 1f # if shift < 0, shift right
+ subu v1, v1, t9
+ sll t2, t2, t9 # shift t2,t8 left
+ srl v0, t8, v1 # save bits shifted out
+ or t2, t2, v0
+ sll t8, t8, t9
+ b norm_noshift_s
+1:
+ negu t9 # shift t2,t8 right by t9
+ subu v1, v1, t9
+ sll v0, t8, v1 # save bits shifted out
+ sltu v0, zero, v0 # be sure to save any one bits
+ srl t8, t8, t9
+ or t8, t8, v0
+ sll v0, t2, v1 # save bits shifted out
+ or t8, t8, v0
+ srl t2, t2, t9
+norm_noshift_s:
+ move t5, t1 # save unrounded exponent
+ move t6, t2 # save unrounded fraction
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ beq v0, FPC_ROUND_RN, 3f # round to nearest
+ beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate)
+ beq v0, FPC_ROUND_RP, 1f # round to +infinity
+ beq t0, zero, 5f # if sign is positive, truncate
+ b 2f
+1:
+ bne t0, zero, 5f # if sign is negative, truncate
+2:
+ beq t8, zero, 5f # if exact, continue
+ addu t2, t2, 1 # add rounding bit
+ bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent?
+ addu t1, t1, 1 # adjust exponent
+ srl t2, t2, 1 # renormalize fraction
+ b 5f
+3:
+ li v0, GUARDBIT # load guard bit for rounding
+ addu v0, v0, t8 # add remainder
+ sltu v1, v0, t8 # compute carry out
+ beq v1, zero, 4f # if no carry, continue
+ addu t2, t2, 1 # add carry to result
+ bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent?
+ addu t1, t1, 1 # adjust exponent
+ srl t2, t2, 1 # renormalize fraction
+4:
+ bne v0, zero, 5f # if rounded remainder is zero
+ and t2, t2, ~1 # clear LSB (round to nearest)
+5:
+ bgt t1, SEXP_MAX, overflow_s # overflow?
+ blt t1, SEXP_MIN, underflow_s # underflow?
+ bne t8, zero, inexact_s # is result inexact?
+ addu t1, t1, SEXP_BIAS # bias exponent
+ and t2, t2, ~SIMPL_ONE # clear implied one bit
+ b result_fs_s
+
+/*
+ * Handle inexact exception.
+ */
+inexact_s:
+ addu t1, t1, SEXP_BIAS # bias exponent
+ and t2, t2, ~SIMPL_ONE # clear implied one bit
+inexact_nobias_s:
+ jal set_fd_s # save result
+ or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+ and v0, a1, FPC_ENABLE_INEXACT
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # save exceptions
+ b done
+
+/*
+ * Overflow will trap (if enabled),
+ * or generate an inexact trap (if enabled),
+ * or generate an infinity.
+ */
+overflow_s:
+ or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
+ and v0, a1, FPC_ENABLE_OVERFLOW
+ beq v0, zero, 1f
+ subu t1, t1, 192 # bias exponent
+ and t2, t2, ~SIMPL_ONE # clear implied one bit
+ jal set_fd_s # save result
+ b fpe_trap
+1:
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ beq v0, FPC_ROUND_RN, 3f # round to nearest
+ beq v0, FPC_ROUND_RZ, 1f # round to zero (truncate)
+ beq v0, FPC_ROUND_RP, 2f # round to +infinity
+ bne t0, zero, 3f
+1:
+ li t1, SEXP_MAX # result is max finite
+ li t2, 0x007fffff
+ b inexact_s
+2:
+ bne t0, zero, 1b
+3:
+ li t1, SEXP_MAX + 1 # result is infinity
+ move t2, zero
+ b inexact_s
+
+/*
+ * In this implementation, "tininess" is detected "after rounding" and
+ * "loss of accuracy" is detected as "an inexact result".
+ */
+underflow_s:
+ and v0, a1, FPC_ENABLE_UNDERFLOW
+ beq v0, zero, 1f
+/*
+ * Underflow is enabled so compute the result and trap.
+ */
+ addu t1, t1, 192 # bias exponent
+ and t2, t2, ~SIMPL_ONE # clear implied one bit
+ jal set_fd_s # save result
+ or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+ b fpe_trap
+/*
+ * Underflow is not enabled so compute the result,
+ * signal inexact result (if it is) and trap (if enabled).
+ */
+1:
+ move t1, t5 # get unrounded exponent
+ move t2, t6 # get unrounded fraction
+ li t9, SEXP_MIN # compute shift amount
+ subu t9, t9, t1 # shift t2,t8 right by t9
+ blt t9, SFRAC_BITS+2, 3f # shift all the bits out?
+ move t1, zero # result is inexact zero
+ move t2, zero
+ or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+/*
+ * Now round the zero result.
+ * Only need to worry about rounding to +- infinity when the sign matches.
+ */
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ beq v0, FPC_ROUND_RN, inexact_nobias_s # round to nearest
+ beq v0, FPC_ROUND_RZ, inexact_nobias_s # round to zero
+ beq v0, FPC_ROUND_RP, 1f # round to +infinity
+ beq t0, zero, inexact_nobias_s # if sign is positive, truncate
+ b 2f
+1:
+ bne t0, zero, inexact_nobias_s # if sign is negative, truncate
+2:
+ addu t2, t2, 1 # add rounding bit
+ b inexact_nobias_s
+3:
+ li v1, 32
+ subu v1, v1, t9
+ sltu v0, zero, t8 # be sure to save any one bits
+ sll t8, t2, v1 # save bits shifted out
+ or t8, t8, v0 # include sticky bits
+ srl t2, t2, t9
+/*
+ * Now round the denormalized result.
+ */
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ beq v0, FPC_ROUND_RN, 3f # round to nearest
+ beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate)
+ beq v0, FPC_ROUND_RP, 1f # round to +infinity
+ beq t0, zero, 5f # if sign is positive, truncate
+ b 2f
+1:
+ bne t0, zero, 5f # if sign is negative, truncate
+2:
+ beq t8, zero, 5f # if exact, continue
+ addu t2, t2, 1 # add rounding bit
+ b 5f
+3:
+ li v0, GUARDBIT # load guard bit for rounding
+ addu v0, v0, t8 # add remainder
+ sltu v1, v0, t8 # compute carry out
+ beq v1, zero, 4f # if no carry, continue
+ addu t2, t2, 1 # add carry to result
+4:
+ bne v0, zero, 5f # if rounded remainder is zero
+ and t2, t2, ~1 # clear LSB (round to nearest)
+5:
+ move t1, zero # denorm or zero exponent
+ jal set_fd_s # save result
+ beq t8, zero, done # check for exact result
+ or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+ or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+ and v0, a1, FPC_ENABLE_INEXACT
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # save exceptions
+ b done
+
+/*
+ * Determine the amount to shift the fraction in order to restore the
+ * normalized position. After that, round and handle exceptions.
+ */
+norm_d:
+ move v0, t2
+ move t9, zero # t9 = num of leading zeros
+ bne t2, zero, 1f
+ move v0, t3
+ addu t9, 32
+ bne t3, zero, 1f
+ move v0, t8
+ addu t9, 32
+1:
+ srl v1, v0, 16
+ bne v1, zero, 1f
+ addu t9, 16
+ sll v0, 16
+1:
+ srl v1, v0, 24
+ bne v1, zero, 1f
+ addu t9, 8
+ sll v0, 8
+1:
+ srl v1, v0, 28
+ bne v1, zero, 1f
+ addu t9, 4
+ sll v0, 4
+1:
+ srl v1, v0, 30
+ bne v1, zero, 1f
+ addu t9, 2
+ sll v0, 2
+1:
+ srl v1, v0, 31
+ bne v1, zero, 1f
+ addu t9, 1
+/*
+ * Now shift t2,t3,t8 the correct number of bits.
+ */
+1:
+ subu t9, t9, DLEAD_ZEROS # dont count leading zeros
+ subu t1, t1, t9 # adjust the exponent
+ beq t9, zero, norm_noshift_d
+ li v1, 32
+ blt t9, zero, 2f # if shift < 0, shift right
+ blt t9, v1, 1f # shift by < 32?
+ subu t9, t9, v1 # shift by >= 32
+ subu v1, v1, t9
+ sll t2, t3, t9 # shift left by t9
+ srl v0, t8, v1 # save bits shifted out
+ or t2, t2, v0
+ sll t3, t8, t9
+ move t8, zero
+ b norm_noshift_d
+1:
+ subu v1, v1, t9
+ sll t2, t2, t9 # shift left by t9
+ srl v0, t3, v1 # save bits shifted out
+ or t2, t2, v0
+ sll t3, t3, t9
+ srl v0, t8, v1 # save bits shifted out
+ or t3, t3, v0
+ sll t8, t8, t9
+ b norm_noshift_d
+2:
+ negu t9 # shift right by t9
+ subu v1, v1, t9 # (known to be < 32 bits)
+ sll v0, t8, v1 # save bits shifted out
+ sltu v0, zero, v0 # be sure to save any one bits
+ srl t8, t8, t9
+ or t8, t8, v0
+ sll v0, t3, v1 # save bits shifted out
+ or t8, t8, v0
+ srl t3, t3, t9
+ sll v0, t2, v1 # save bits shifted out
+ or t3, t3, v0
+ srl t2, t2, t9
+norm_noshift_d:
+ move t5, t1 # save unrounded exponent
+ move t6, t2 # save unrounded fraction (MS)
+ move t7, t3 # save unrounded fraction (LS)
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ beq v0, FPC_ROUND_RN, 3f # round to nearest
+ beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate)
+ beq v0, FPC_ROUND_RP, 1f # round to +infinity
+ beq t0, zero, 5f # if sign is positive, truncate
+ b 2f
+1:
+ bne t0, zero, 5f # if sign is negative, truncate
+2:
+ beq t8, zero, 5f # if exact, continue
+ addu t3, t3, 1 # add rounding bit
+ bne t3, zero, 5f # branch if no carry
+ addu t2, t2, 1 # add carry
+ bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent?
+ addu t1, t1, 1 # adjust exponent
+ srl t2, t2, 1 # renormalize fraction
+ b 5f
+3:
+ li v0, GUARDBIT # load guard bit for rounding
+ addu v0, v0, t8 # add remainder
+ sltu v1, v0, t8 # compute carry out
+ beq v1, zero, 4f # branch if no carry
+ addu t3, t3, 1 # add carry
+ bne t3, zero, 4f # branch if no carry
+ addu t2, t2, 1 # add carry to result
+ bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent?
+ addu t1, t1, 1 # adjust exponent
+ srl t2, t2, 1 # renormalize fraction
+4:
+ bne v0, zero, 5f # if rounded remainder is zero
+ and t3, t3, ~1 # clear LSB (round to nearest)
+5:
+ bgt t1, DEXP_MAX, overflow_d # overflow?
+ blt t1, DEXP_MIN, underflow_d # underflow?
+ bne t8, zero, inexact_d # is result inexact?
+ addu t1, t1, DEXP_BIAS # bias exponent
+ and t2, t2, ~DIMPL_ONE # clear implied one bit
+ b result_fs_d
+
+/*
+ * Handle inexact exception.
+ */
+inexact_d:
+ addu t1, t1, DEXP_BIAS # bias exponent
+ and t2, t2, ~DIMPL_ONE # clear implied one bit
+inexact_nobias_d:
+ jal set_fd_d # save result
+ or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+ and v0, a1, FPC_ENABLE_INEXACT
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # save exceptions
+ b done
+
+/*
+ * Overflow will trap (if enabled),
+ * or generate an inexact trap (if enabled),
+ * or generate an infinity.
+ */
+overflow_d:
+ or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
+ and v0, a1, FPC_ENABLE_OVERFLOW
+ beq v0, zero, 1f
+ subu t1, t1, 1536 # bias exponent
+ and t2, t2, ~DIMPL_ONE # clear implied one bit
+ jal set_fd_d # save result
+ b fpe_trap
+1:
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ beq v0, FPC_ROUND_RN, 3f # round to nearest
+ beq v0, FPC_ROUND_RZ, 1f # round to zero (truncate)
+ beq v0, FPC_ROUND_RP, 2f # round to +infinity
+ bne t0, zero, 3f
+1:
+ li t1, DEXP_MAX # result is max finite
+ li t2, 0x000fffff
+ li t3, 0xffffffff
+ b inexact_d
+2:
+ bne t0, zero, 1b
+3:
+ li t1, DEXP_MAX + 1 # result is infinity
+ move t2, zero
+ move t3, zero
+ b inexact_d
+
+/*
+ * In this implementation, "tininess" is detected "after rounding" and
+ * "loss of accuracy" is detected as "an inexact result".
+ */
+underflow_d:
+ and v0, a1, FPC_ENABLE_UNDERFLOW
+ beq v0, zero, 1f
+/*
+ * Underflow is enabled so compute the result and trap.
+ */
+ addu t1, t1, 1536 # bias exponent
+ and t2, t2, ~DIMPL_ONE # clear implied one bit
+ jal set_fd_d # save result
+ or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+ b fpe_trap
+/*
+ * Underflow is not enabled so compute the result,
+ * signal inexact result (if it is) and trap (if enabled).
+ */
+1:
+ move t1, t5 # get unrounded exponent
+ move t2, t6 # get unrounded fraction (MS)
+ move t3, t7 # get unrounded fraction (LS)
+ li t9, DEXP_MIN # compute shift amount
+ subu t9, t9, t1 # shift t2,t8 right by t9
+ blt t9, DFRAC_BITS+2, 3f # shift all the bits out?
+ move t1, zero # result is inexact zero
+ move t2, zero
+ move t3, zero
+ or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+/*
+ * Now round the zero result.
+ * Only need to worry about rounding to +- infinity when the sign matches.
+ */
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ beq v0, FPC_ROUND_RN, inexact_nobias_d # round to nearest
+ beq v0, FPC_ROUND_RZ, inexact_nobias_d # round to zero
+ beq v0, FPC_ROUND_RP, 1f # round to +infinity
+ beq t0, zero, inexact_nobias_d # if sign is positive, truncate
+ b 2f
+1:
+ bne t0, zero, inexact_nobias_d # if sign is negative, truncate
+2:
+ addu t3, t3, 1 # add rounding bit
+ b inexact_nobias_d
+3:
+ li v1, 32
+ blt t9, v1, 1f # shift by < 32?
+ subu t9, t9, v1 # shift right by >= 32
+ subu v1, v1, t9
+ sltu v0, zero, t8 # be sure to save any one bits
+ sll t8, t2, v1 # save bits shifted out
+ or t8, t8, v0 # include sticky bits
+ srl t3, t2, t9
+ move t2, zero
+ b 2f
+1:
+ subu v1, v1, t9 # shift right by t9
+ sltu v0, zero, t8 # be sure to save any one bits
+ sll t8, t3, v1 # save bits shifted out
+ or t8, t8, v0 # include sticky bits
+ srl t3, t3, t9
+ sll v0, t2, v1 # save bits shifted out
+ or t3, t3, v0
+ srl t2, t2, t9
+/*
+ * Now round the denormalized result.
+ */
+2:
+ and v0, a1, FPC_ROUNDING_BITS # get rounding mode
+ beq v0, FPC_ROUND_RN, 3f # round to nearest
+ beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate)
+ beq v0, FPC_ROUND_RP, 1f # round to +infinity
+ beq t0, zero, 5f # if sign is positive, truncate
+ b 2f
+1:
+ bne t0, zero, 5f # if sign is negative, truncate
+2:
+ beq t8, zero, 5f # if exact, continue
+ addu t3, t3, 1 # add rounding bit
+ bne t3, zero, 5f # if no carry, continue
+ addu t2, t2, 1 # add carry
+ b 5f
+3:
+ li v0, GUARDBIT # load guard bit for rounding
+ addu v0, v0, t8 # add remainder
+ sltu v1, v0, t8 # compute carry out
+ beq v1, zero, 4f # if no carry, continue
+ addu t3, t3, 1 # add rounding bit
+ bne t3, zero, 4f # if no carry, continue
+ addu t2, t2, 1 # add carry
+4:
+ bne v0, zero, 5f # if rounded remainder is zero
+ and t3, t3, ~1 # clear LSB (round to nearest)
+5:
+ move t1, zero # denorm or zero exponent
+ jal set_fd_d # save result
+ beq t8, zero, done # check for exact result
+ or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
+ or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
+ and v0, a1, FPC_ENABLE_INEXACT
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # save exceptions
+ b done
+
+/*
+ * Signal an invalid operation if the trap is enabled; otherwise,
+ * the result is a quiet NAN.
+ */
+invalid_s: # trap invalid operation
+ or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
+ and v0, a1, FPC_ENABLE_INVALID
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # save exceptions
+ move t0, zero # result is a quiet NAN
+ li t1, SEXP_INF
+ li t2, SQUIET_NAN
+ jal set_fd_s # save result (in t0,t1,t2)
+ b done
+
+/*
+ * Signal an invalid operation if the trap is enabled; otherwise,
+ * the result is a quiet NAN.
+ */
+invalid_d: # trap invalid operation
+ or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
+ and v0, a1, FPC_ENABLE_INVALID
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # save exceptions
+ move t0, zero # result is a quiet NAN
+ li t1, DEXP_INF
+ li t2, DQUIET_NAN0
+ li t3, DQUIET_NAN1
+ jal set_fd_d # save result (in t0,t1,t2,t3)
+ b done
+
+/*
+ * Signal an invalid operation if the trap is enabled; otherwise,
+ * the result is INT_MAX or INT_MIN.
+ */
+invalid_w: # trap invalid operation
+ or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
+ and v0, a1, FPC_ENABLE_INVALID
+ bne v0, zero, fpe_trap
+ ctc1 a1, FPC_CSR # save exceptions
+ bne t0, zero, 1f
+ li t2, INT_MAX # result is INT_MAX
+ b result_fs_w
+1:
+ li t2, INT_MIN # result is INT_MIN
+ b result_fs_w
+
+/*
+ * Trap if the hardware should have handled this case.
+ */
+fpe_trap:
+ move a2, a1 # code = FP CSR
+ ctc1 a1, FPC_CSR # save exceptions
+ break 0
+
+/*
+ * Send an illegal instruction signal to the current process.
+ */
+ill:
+ ctc1 a1, FPC_CSR # save exceptions
+ move a2, a0 # code = FP instruction
+ break 0
+
+result_ft_s:
+ move t0, t4 # result is FT
+ move t1, t5
+ move t2, t6
+result_fs_s: # result is FS
+ jal set_fd_s # save result (in t0,t1,t2)
+ b done
+
+result_fs_w:
+ jal set_fd_word # save result (in t2)
+ b done
+
+result_ft_d:
+ move t0, t4 # result is FT
+ move t1, t5
+ move t2, t6
+ move t3, t7
+result_fs_d: # result is FS
+ jal set_fd_d # save result (in t0,t1,t2,t3)
+
+done:
+ lw ra, STAND_RA_OFFSET(sp)
+ addu sp, sp, STAND_FRAME_SIZE
+ j ra
+END(MachEmulateFP)
+
+/*----------------------------------------------------------------------------
+ * get_fs_int --
+ *
+ * Read (integer) the FS register (bits 15-11).
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Results:
+ * t0 contains the sign
+ * t2 contains the fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_fs_int)
+ srl a3, a0, 12 - 2 # get FS field (even regs only)
+ and a3, a3, 0xF << 2 # mask FS field
+ lw a3, get_fs_int_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+get_fs_int_tbl:
+ .word get_fs_int_f0
+ .word get_fs_int_f2
+ .word get_fs_int_f4
+ .word get_fs_int_f6
+ .word get_fs_int_f8
+ .word get_fs_int_f10
+ .word get_fs_int_f12
+ .word get_fs_int_f14
+ .word get_fs_int_f16
+ .word get_fs_int_f18
+ .word get_fs_int_f20
+ .word get_fs_int_f22
+ .word get_fs_int_f24
+ .word get_fs_int_f26
+ .word get_fs_int_f28
+ .word get_fs_int_f30
+ .text
+
+get_fs_int_f0:
+ mfc1 t2, $f0
+ b get_fs_int_done
+get_fs_int_f2:
+ mfc1 t2, $f2
+ b get_fs_int_done
+get_fs_int_f4:
+ mfc1 t2, $f4
+ b get_fs_int_done
+get_fs_int_f6:
+ mfc1 t2, $f6
+ b get_fs_int_done
+get_fs_int_f8:
+ mfc1 t2, $f8
+ b get_fs_int_done
+get_fs_int_f10:
+ mfc1 t2, $f10
+ b get_fs_int_done
+get_fs_int_f12:
+ mfc1 t2, $f12
+ b get_fs_int_done
+get_fs_int_f14:
+ mfc1 t2, $f14
+ b get_fs_int_done
+get_fs_int_f16:
+ mfc1 t2, $f16
+ b get_fs_int_done
+get_fs_int_f18:
+ mfc1 t2, $f18
+ b get_fs_int_done
+get_fs_int_f20:
+ mfc1 t2, $f20
+ b get_fs_int_done
+get_fs_int_f22:
+ mfc1 t2, $f22
+ b get_fs_int_done
+get_fs_int_f24:
+ mfc1 t2, $f24
+ b get_fs_int_done
+get_fs_int_f26:
+ mfc1 t2, $f26
+ b get_fs_int_done
+get_fs_int_f28:
+ mfc1 t2, $f28
+ b get_fs_int_done
+get_fs_int_f30:
+ mfc1 t2, $f30
+get_fs_int_done:
+ srl t0, t2, 31 # init the sign bit
+ bge t2, zero, 1f
+ negu t2
+1:
+ j ra
+END(get_fs_int)
+
+/*----------------------------------------------------------------------------
+ * get_ft_fs_s --
+ *
+ * Read (single precision) the FT register (bits 20-16) and
+ * the FS register (bits 15-11) and break up into fields.
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Results:
+ * t0 contains the FS sign
+ * t1 contains the FS (biased) exponent
+ * t2 contains the FS fraction
+ * t4 contains the FT sign
+ * t5 contains the FT (biased) exponent
+ * t6 contains the FT fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_ft_fs_s)
+ srl a3, a0, 17 - 2 # get FT field (even regs only)
+ and a3, a3, 0xF << 2 # mask FT field
+ lw a3, get_ft_s_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+get_ft_s_tbl:
+ .word get_ft_s_f0
+ .word get_ft_s_f2
+ .word get_ft_s_f4
+ .word get_ft_s_f6
+ .word get_ft_s_f8
+ .word get_ft_s_f10
+ .word get_ft_s_f12
+ .word get_ft_s_f14
+ .word get_ft_s_f16
+ .word get_ft_s_f18
+ .word get_ft_s_f20
+ .word get_ft_s_f22
+ .word get_ft_s_f24
+ .word get_ft_s_f26
+ .word get_ft_s_f28
+ .word get_ft_s_f30
+ .text
+
+get_ft_s_f0:
+ mfc1 t4, $f0
+ b get_ft_s_done
+get_ft_s_f2:
+ mfc1 t4, $f2
+ b get_ft_s_done
+get_ft_s_f4:
+ mfc1 t4, $f4
+ b get_ft_s_done
+get_ft_s_f6:
+ mfc1 t4, $f6
+ b get_ft_s_done
+get_ft_s_f8:
+ mfc1 t4, $f8
+ b get_ft_s_done
+get_ft_s_f10:
+ mfc1 t4, $f10
+ b get_ft_s_done
+get_ft_s_f12:
+ mfc1 t4, $f12
+ b get_ft_s_done
+get_ft_s_f14:
+ mfc1 t4, $f14
+ b get_ft_s_done
+get_ft_s_f16:
+ mfc1 t4, $f16
+ b get_ft_s_done
+get_ft_s_f18:
+ mfc1 t4, $f18
+ b get_ft_s_done
+get_ft_s_f20:
+ mfc1 t4, $f20
+ b get_ft_s_done
+get_ft_s_f22:
+ mfc1 t4, $f22
+ b get_ft_s_done
+get_ft_s_f24:
+ mfc1 t4, $f24
+ b get_ft_s_done
+get_ft_s_f26:
+ mfc1 t4, $f26
+ b get_ft_s_done
+get_ft_s_f28:
+ mfc1 t4, $f28
+ b get_ft_s_done
+get_ft_s_f30:
+ mfc1 t4, $f30
+get_ft_s_done:
+ srl t5, t4, 23 # get exponent
+ and t5, t5, 0xFF
+ and t6, t4, 0x7FFFFF # get fraction
+ srl t4, t4, 31 # get sign
+ bne t5, SEXP_INF, 1f # is it a signaling NAN?
+ and v0, t6, SSIGNAL_NAN
+ bne v0, zero, invalid_s
+1:
+ /* fall through to get FS */
+
+/*----------------------------------------------------------------------------
+ * get_fs_s --
+ *
+ * Read (single precision) the FS register (bits 15-11) and
+ * break up into fields.
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Results:
+ * t0 contains the sign
+ * t1 contains the (biased) exponent
+ * t2 contains the fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+ALEAF(get_fs_s)
+ srl a3, a0, 12 - 2 # get FS field (even regs only)
+ and a3, a3, 0xF << 2 # mask FS field
+ lw a3, get_fs_s_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+get_fs_s_tbl:
+ .word get_fs_s_f0
+ .word get_fs_s_f2
+ .word get_fs_s_f4
+ .word get_fs_s_f6
+ .word get_fs_s_f8
+ .word get_fs_s_f10
+ .word get_fs_s_f12
+ .word get_fs_s_f14
+ .word get_fs_s_f16
+ .word get_fs_s_f18
+ .word get_fs_s_f20
+ .word get_fs_s_f22
+ .word get_fs_s_f24
+ .word get_fs_s_f26
+ .word get_fs_s_f28
+ .word get_fs_s_f30
+ .text
+
+get_fs_s_f0:
+ mfc1 t0, $f0
+ b get_fs_s_done
+get_fs_s_f2:
+ mfc1 t0, $f2
+ b get_fs_s_done
+get_fs_s_f4:
+ mfc1 t0, $f4
+ b get_fs_s_done
+get_fs_s_f6:
+ mfc1 t0, $f6
+ b get_fs_s_done
+get_fs_s_f8:
+ mfc1 t0, $f8
+ b get_fs_s_done
+get_fs_s_f10:
+ mfc1 t0, $f10
+ b get_fs_s_done
+get_fs_s_f12:
+ mfc1 t0, $f12
+ b get_fs_s_done
+get_fs_s_f14:
+ mfc1 t0, $f14
+ b get_fs_s_done
+get_fs_s_f16:
+ mfc1 t0, $f16
+ b get_fs_s_done
+get_fs_s_f18:
+ mfc1 t0, $f18
+ b get_fs_s_done
+get_fs_s_f20:
+ mfc1 t0, $f20
+ b get_fs_s_done
+get_fs_s_f22:
+ mfc1 t0, $f22
+ b get_fs_s_done
+get_fs_s_f24:
+ mfc1 t0, $f24
+ b get_fs_s_done
+get_fs_s_f26:
+ mfc1 t0, $f26
+ b get_fs_s_done
+get_fs_s_f28:
+ mfc1 t0, $f28
+ b get_fs_s_done
+get_fs_s_f30:
+ mfc1 t0, $f30
+get_fs_s_done:
+ srl t1, t0, 23 # get exponent
+ and t1, t1, 0xFF
+ and t2, t0, 0x7FFFFF # get fraction
+ srl t0, t0, 31 # get sign
+ bne t1, SEXP_INF, 1f # is it a signaling NAN?
+ and v0, t2, SSIGNAL_NAN
+ bne v0, zero, invalid_s
+1:
+ j ra
+END(get_ft_fs_s)
+
+/*----------------------------------------------------------------------------
+ * get_ft_fs_d --
+ *
+ * Read (double precision) the FT register (bits 20-16) and
+ * the FS register (bits 15-11) and break up into fields.
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Results:
+ * t0 contains the FS sign
+ * t1 contains the FS (biased) exponent
+ * t2 contains the FS fraction
+ * t3 contains the FS remaining fraction
+ * t4 contains the FT sign
+ * t5 contains the FT (biased) exponent
+ * t6 contains the FT fraction
+ * t7 contains the FT remaining fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_ft_fs_d)
+ srl a3, a0, 17 - 2 # get FT field (even regs only)
+ and a3, a3, 0xF << 2 # mask FT field
+ lw a3, get_ft_d_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+get_ft_d_tbl:
+ .word get_ft_d_f0
+ .word get_ft_d_f2
+ .word get_ft_d_f4
+ .word get_ft_d_f6
+ .word get_ft_d_f8
+ .word get_ft_d_f10
+ .word get_ft_d_f12
+ .word get_ft_d_f14
+ .word get_ft_d_f16
+ .word get_ft_d_f18
+ .word get_ft_d_f20
+ .word get_ft_d_f22
+ .word get_ft_d_f24
+ .word get_ft_d_f26
+ .word get_ft_d_f28
+ .word get_ft_d_f30
+ .text
+
+get_ft_d_f0:
+ mfc1 t7, $f0
+ mfc1 t4, $f1
+ b get_ft_d_done
+get_ft_d_f2:
+ mfc1 t7, $f2
+ mfc1 t4, $f3
+ b get_ft_d_done
+get_ft_d_f4:
+ mfc1 t7, $f4
+ mfc1 t4, $f5
+ b get_ft_d_done
+get_ft_d_f6:
+ mfc1 t7, $f6
+ mfc1 t4, $f7
+ b get_ft_d_done
+get_ft_d_f8:
+ mfc1 t7, $f8
+ mfc1 t4, $f9
+ b get_ft_d_done
+get_ft_d_f10:
+ mfc1 t7, $f10
+ mfc1 t4, $f11
+ b get_ft_d_done
+get_ft_d_f12:
+ mfc1 t7, $f12
+ mfc1 t4, $f13
+ b get_ft_d_done
+get_ft_d_f14:
+ mfc1 t7, $f14
+ mfc1 t4, $f15
+ b get_ft_d_done
+get_ft_d_f16:
+ mfc1 t7, $f16
+ mfc1 t4, $f17
+ b get_ft_d_done
+get_ft_d_f18:
+ mfc1 t7, $f18
+ mfc1 t4, $f19
+ b get_ft_d_done
+get_ft_d_f20:
+ mfc1 t7, $f20
+ mfc1 t4, $f21
+ b get_ft_d_done
+get_ft_d_f22:
+ mfc1 t7, $f22
+ mfc1 t4, $f23
+ b get_ft_d_done
+get_ft_d_f24:
+ mfc1 t7, $f24
+ mfc1 t4, $f25
+ b get_ft_d_done
+get_ft_d_f26:
+ mfc1 t7, $f26
+ mfc1 t4, $f27
+ b get_ft_d_done
+get_ft_d_f28:
+ mfc1 t7, $f28
+ mfc1 t4, $f29
+ b get_ft_d_done
+get_ft_d_f30:
+ mfc1 t7, $f30
+ mfc1 t4, $f31
+get_ft_d_done:
+ srl t5, t4, 20 # get exponent
+ and t5, t5, 0x7FF
+ and t6, t4, 0xFFFFF # get fraction
+ srl t4, t4, 31 # get sign
+ bne t5, DEXP_INF, 1f # is it a signaling NAN?
+ and v0, t6, DSIGNAL_NAN
+ bne v0, zero, invalid_d
+1:
+ /* fall through to get FS */
+
+/*----------------------------------------------------------------------------
+ * get_fs_d --
+ *
+ * Read (double precision) the FS register (bits 15-11) and
+ * break up into fields.
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Results:
+ * t0 contains the sign
+ * t1 contains the (biased) exponent
+ * t2 contains the fraction
+ * t3 contains the remaining fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+ALEAF(get_fs_d)
+ srl a3, a0, 12 - 2 # get FS field (even regs only)
+ and a3, a3, 0xF << 2 # mask FS field
+ lw a3, get_fs_d_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+get_fs_d_tbl:
+ .word get_fs_d_f0
+ .word get_fs_d_f2
+ .word get_fs_d_f4
+ .word get_fs_d_f6
+ .word get_fs_d_f8
+ .word get_fs_d_f10
+ .word get_fs_d_f12
+ .word get_fs_d_f14
+ .word get_fs_d_f16
+ .word get_fs_d_f18
+ .word get_fs_d_f20
+ .word get_fs_d_f22
+ .word get_fs_d_f24
+ .word get_fs_d_f26
+ .word get_fs_d_f28
+ .word get_fs_d_f30
+ .text
+
+get_fs_d_f0:
+ mfc1 t3, $f0
+ mfc1 t0, $f1
+ b get_fs_d_done
+get_fs_d_f2:
+ mfc1 t3, $f2
+ mfc1 t0, $f3
+ b get_fs_d_done
+get_fs_d_f4:
+ mfc1 t3, $f4
+ mfc1 t0, $f5
+ b get_fs_d_done
+get_fs_d_f6:
+ mfc1 t3, $f6
+ mfc1 t0, $f7
+ b get_fs_d_done
+get_fs_d_f8:
+ mfc1 t3, $f8
+ mfc1 t0, $f9
+ b get_fs_d_done
+get_fs_d_f10:
+ mfc1 t3, $f10
+ mfc1 t0, $f11
+ b get_fs_d_done
+get_fs_d_f12:
+ mfc1 t3, $f12
+ mfc1 t0, $f13
+ b get_fs_d_done
+get_fs_d_f14:
+ mfc1 t3, $f14
+ mfc1 t0, $f15
+ b get_fs_d_done
+get_fs_d_f16:
+ mfc1 t3, $f16
+ mfc1 t0, $f17
+ b get_fs_d_done
+get_fs_d_f18:
+ mfc1 t3, $f18
+ mfc1 t0, $f19
+ b get_fs_d_done
+get_fs_d_f20:
+ mfc1 t3, $f20
+ mfc1 t0, $f21
+ b get_fs_d_done
+get_fs_d_f22:
+ mfc1 t3, $f22
+ mfc1 t0, $f23
+ b get_fs_d_done
+get_fs_d_f24:
+ mfc1 t3, $f24
+ mfc1 t0, $f25
+ b get_fs_d_done
+get_fs_d_f26:
+ mfc1 t3, $f26
+ mfc1 t0, $f27
+ b get_fs_d_done
+get_fs_d_f28:
+ mfc1 t3, $f28
+ mfc1 t0, $f29
+ b get_fs_d_done
+get_fs_d_f30:
+ mfc1 t3, $f30
+ mfc1 t0, $f31
+get_fs_d_done:
+ srl t1, t0, 20 # get exponent
+ and t1, t1, 0x7FF
+ and t2, t0, 0xFFFFF # get fraction
+ srl t0, t0, 31 # get sign
+ bne t1, DEXP_INF, 1f # is it a signaling NAN?
+ and v0, t2, DSIGNAL_NAN
+ bne v0, zero, invalid_d
+1:
+ j ra
+END(get_ft_fs_d)
+
+/*----------------------------------------------------------------------------
+ * get_cmp_s --
+ *
+ * Read (single precision) the FS register (bits 15-11) and
+ * the FT register (bits 20-16) and break up into fields.
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Results:
+ * t0 contains the sign
+ * t1 contains the (biased) exponent
+ * t2 contains the fraction
+ * t4 contains the sign
+ * t5 contains the (biased) exponent
+ * t6 contains the fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_cmp_s)
+ srl a3, a0, 12 - 2 # get FS field (even regs only)
+ and a3, a3, 0xF << 2 # mask FS field
+ lw a3, cmp_fs_s_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+cmp_fs_s_tbl:
+ .word cmp_fs_s_f0
+ .word cmp_fs_s_f2
+ .word cmp_fs_s_f4
+ .word cmp_fs_s_f6
+ .word cmp_fs_s_f8
+ .word cmp_fs_s_f10
+ .word cmp_fs_s_f12
+ .word cmp_fs_s_f14
+ .word cmp_fs_s_f16
+ .word cmp_fs_s_f18
+ .word cmp_fs_s_f20
+ .word cmp_fs_s_f22
+ .word cmp_fs_s_f24
+ .word cmp_fs_s_f26
+ .word cmp_fs_s_f28
+ .word cmp_fs_s_f30
+ .text
+
+cmp_fs_s_f0:
+ mfc1 t0, $f0
+ b cmp_fs_s_done
+cmp_fs_s_f2:
+ mfc1 t0, $f2
+ b cmp_fs_s_done
+cmp_fs_s_f4:
+ mfc1 t0, $f4
+ b cmp_fs_s_done
+cmp_fs_s_f6:
+ mfc1 t0, $f6
+ b cmp_fs_s_done
+cmp_fs_s_f8:
+ mfc1 t0, $f8
+ b cmp_fs_s_done
+cmp_fs_s_f10:
+ mfc1 t0, $f10
+ b cmp_fs_s_done
+cmp_fs_s_f12:
+ mfc1 t0, $f12
+ b cmp_fs_s_done
+cmp_fs_s_f14:
+ mfc1 t0, $f14
+ b cmp_fs_s_done
+cmp_fs_s_f16:
+ mfc1 t0, $f16
+ b cmp_fs_s_done
+cmp_fs_s_f18:
+ mfc1 t0, $f18
+ b cmp_fs_s_done
+cmp_fs_s_f20:
+ mfc1 t0, $f20
+ b cmp_fs_s_done
+cmp_fs_s_f22:
+ mfc1 t0, $f22
+ b cmp_fs_s_done
+cmp_fs_s_f24:
+ mfc1 t0, $f24
+ b cmp_fs_s_done
+cmp_fs_s_f26:
+ mfc1 t0, $f26
+ b cmp_fs_s_done
+cmp_fs_s_f28:
+ mfc1 t0, $f28
+ b cmp_fs_s_done
+cmp_fs_s_f30:
+ mfc1 t0, $f30
+cmp_fs_s_done:
+ srl t1, t0, 23 # get exponent
+ and t1, t1, 0xFF
+ and t2, t0, 0x7FFFFF # get fraction
+ srl t0, t0, 31 # get sign
+
+ srl a3, a0, 17 - 2 # get FT field (even regs only)
+ and a3, a3, 0xF << 2 # mask FT field
+ lw a3, cmp_ft_s_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+cmp_ft_s_tbl:
+ .word cmp_ft_s_f0
+ .word cmp_ft_s_f2
+ .word cmp_ft_s_f4
+ .word cmp_ft_s_f6
+ .word cmp_ft_s_f8
+ .word cmp_ft_s_f10
+ .word cmp_ft_s_f12
+ .word cmp_ft_s_f14
+ .word cmp_ft_s_f16
+ .word cmp_ft_s_f18
+ .word cmp_ft_s_f20
+ .word cmp_ft_s_f22
+ .word cmp_ft_s_f24
+ .word cmp_ft_s_f26
+ .word cmp_ft_s_f28
+ .word cmp_ft_s_f30
+ .text
+
+cmp_ft_s_f0:
+ mfc1 t4, $f0
+ b cmp_ft_s_done
+cmp_ft_s_f2:
+ mfc1 t4, $f2
+ b cmp_ft_s_done
+cmp_ft_s_f4:
+ mfc1 t4, $f4
+ b cmp_ft_s_done
+cmp_ft_s_f6:
+ mfc1 t4, $f6
+ b cmp_ft_s_done
+cmp_ft_s_f8:
+ mfc1 t4, $f8
+ b cmp_ft_s_done
+cmp_ft_s_f10:
+ mfc1 t4, $f10
+ b cmp_ft_s_done
+cmp_ft_s_f12:
+ mfc1 t4, $f12
+ b cmp_ft_s_done
+cmp_ft_s_f14:
+ mfc1 t4, $f14
+ b cmp_ft_s_done
+cmp_ft_s_f16:
+ mfc1 t4, $f16
+ b cmp_ft_s_done
+cmp_ft_s_f18:
+ mfc1 t4, $f18
+ b cmp_ft_s_done
+cmp_ft_s_f20:
+ mfc1 t4, $f20
+ b cmp_ft_s_done
+cmp_ft_s_f22:
+ mfc1 t4, $f22
+ b cmp_ft_s_done
+cmp_ft_s_f24:
+ mfc1 t4, $f24
+ b cmp_ft_s_done
+cmp_ft_s_f26:
+ mfc1 t4, $f26
+ b cmp_ft_s_done
+cmp_ft_s_f28:
+ mfc1 t4, $f28
+ b cmp_ft_s_done
+cmp_ft_s_f30:
+ mfc1 t4, $f30
+cmp_ft_s_done:
+ srl t5, t4, 23 # get exponent
+ and t5, t5, 0xFF
+ and t6, t4, 0x7FFFFF # get fraction
+ srl t4, t4, 31 # get sign
+ j ra
+END(get_cmp_s)
+
+/*----------------------------------------------------------------------------
+ * get_cmp_d --
+ *
+ * Read (double precision) the FS register (bits 15-11) and
+ * the FT register (bits 20-16) and break up into fields.
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Results:
+ * t0 contains the sign
+ * t1 contains the (biased) exponent
+ * t2 contains the fraction
+ * t3 contains the remaining fraction
+ * t4 contains the sign
+ * t5 contains the (biased) exponent
+ * t6 contains the fraction
+ * t7 contains the remaining fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(get_cmp_d)
+ srl a3, a0, 12 - 2 # get FS field (even regs only)
+ and a3, a3, 0xF << 2 # mask FS field
+ lw a3, cmp_fs_d_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+cmp_fs_d_tbl:
+ .word cmp_fs_d_f0
+ .word cmp_fs_d_f2
+ .word cmp_fs_d_f4
+ .word cmp_fs_d_f6
+ .word cmp_fs_d_f8
+ .word cmp_fs_d_f10
+ .word cmp_fs_d_f12
+ .word cmp_fs_d_f14
+ .word cmp_fs_d_f16
+ .word cmp_fs_d_f18
+ .word cmp_fs_d_f20
+ .word cmp_fs_d_f22
+ .word cmp_fs_d_f24
+ .word cmp_fs_d_f26
+ .word cmp_fs_d_f28
+ .word cmp_fs_d_f30
+ .text
+
+cmp_fs_d_f0:
+ mfc1 t3, $f0
+ mfc1 t0, $f1
+ b cmp_fs_d_done
+cmp_fs_d_f2:
+ mfc1 t3, $f2
+ mfc1 t0, $f3
+ b cmp_fs_d_done
+cmp_fs_d_f4:
+ mfc1 t3, $f4
+ mfc1 t0, $f5
+ b cmp_fs_d_done
+cmp_fs_d_f6:
+ mfc1 t3, $f6
+ mfc1 t0, $f7
+ b cmp_fs_d_done
+cmp_fs_d_f8:
+ mfc1 t3, $f8
+ mfc1 t0, $f9
+ b cmp_fs_d_done
+cmp_fs_d_f10:
+ mfc1 t3, $f10
+ mfc1 t0, $f11
+ b cmp_fs_d_done
+cmp_fs_d_f12:
+ mfc1 t3, $f12
+ mfc1 t0, $f13
+ b cmp_fs_d_done
+cmp_fs_d_f14:
+ mfc1 t3, $f14
+ mfc1 t0, $f15
+ b cmp_fs_d_done
+cmp_fs_d_f16:
+ mfc1 t3, $f16
+ mfc1 t0, $f17
+ b cmp_fs_d_done
+cmp_fs_d_f18:
+ mfc1 t3, $f18
+ mfc1 t0, $f19
+ b cmp_fs_d_done
+cmp_fs_d_f20:
+ mfc1 t3, $f20
+ mfc1 t0, $f21
+ b cmp_fs_d_done
+cmp_fs_d_f22:
+ mfc1 t3, $f22
+ mfc1 t0, $f23
+ b cmp_fs_d_done
+cmp_fs_d_f24:
+ mfc1 t3, $f24
+ mfc1 t0, $f25
+ b cmp_fs_d_done
+cmp_fs_d_f26:
+ mfc1 t3, $f26
+ mfc1 t0, $f27
+ b cmp_fs_d_done
+cmp_fs_d_f28:
+ mfc1 t3, $f28
+ mfc1 t0, $f29
+ b cmp_fs_d_done
+cmp_fs_d_f30:
+ mfc1 t3, $f30
+ mfc1 t0, $f31
+cmp_fs_d_done:
+ srl t1, t0, 20 # get exponent
+ and t1, t1, 0x7FF
+ and t2, t0, 0xFFFFF # get fraction
+ srl t0, t0, 31 # get sign
+
+ srl a3, a0, 17 - 2 # get FT field (even regs only)
+ and a3, a3, 0xF << 2 # mask FT field
+ lw a3, cmp_ft_d_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+cmp_ft_d_tbl:
+ .word cmp_ft_d_f0
+ .word cmp_ft_d_f2
+ .word cmp_ft_d_f4
+ .word cmp_ft_d_f6
+ .word cmp_ft_d_f8
+ .word cmp_ft_d_f10
+ .word cmp_ft_d_f12
+ .word cmp_ft_d_f14
+ .word cmp_ft_d_f16
+ .word cmp_ft_d_f18
+ .word cmp_ft_d_f20
+ .word cmp_ft_d_f22
+ .word cmp_ft_d_f24
+ .word cmp_ft_d_f26
+ .word cmp_ft_d_f28
+ .word cmp_ft_d_f30
+ .text
+
+cmp_ft_d_f0:
+ mfc1 t7, $f0
+ mfc1 t4, $f1
+ b cmp_ft_d_done
+cmp_ft_d_f2:
+ mfc1 t7, $f2
+ mfc1 t4, $f3
+ b cmp_ft_d_done
+cmp_ft_d_f4:
+ mfc1 t7, $f4
+ mfc1 t4, $f5
+ b cmp_ft_d_done
+cmp_ft_d_f6:
+ mfc1 t7, $f6
+ mfc1 t4, $f7
+ b cmp_ft_d_done
+cmp_ft_d_f8:
+ mfc1 t7, $f8
+ mfc1 t4, $f9
+ b cmp_ft_d_done
+cmp_ft_d_f10:
+ mfc1 t7, $f10
+ mfc1 t4, $f11
+ b cmp_ft_d_done
+cmp_ft_d_f12:
+ mfc1 t7, $f12
+ mfc1 t4, $f13
+ b cmp_ft_d_done
+cmp_ft_d_f14:
+ mfc1 t7, $f14
+ mfc1 t4, $f15
+ b cmp_ft_d_done
+cmp_ft_d_f16:
+ mfc1 t7, $f16
+ mfc1 t4, $f17
+ b cmp_ft_d_done
+cmp_ft_d_f18:
+ mfc1 t7, $f18
+ mfc1 t4, $f19
+ b cmp_ft_d_done
+cmp_ft_d_f20:
+ mfc1 t7, $f20
+ mfc1 t4, $f21
+ b cmp_ft_d_done
+cmp_ft_d_f22:
+ mfc1 t7, $f22
+ mfc1 t4, $f23
+ b cmp_ft_d_done
+cmp_ft_d_f24:
+ mfc1 t7, $f24
+ mfc1 t4, $f25
+ b cmp_ft_d_done
+cmp_ft_d_f26:
+ mfc1 t7, $f26
+ mfc1 t4, $f27
+ b cmp_ft_d_done
+cmp_ft_d_f28:
+ mfc1 t7, $f28
+ mfc1 t4, $f29
+ b cmp_ft_d_done
+cmp_ft_d_f30:
+ mfc1 t7, $f30
+ mfc1 t4, $f31
+cmp_ft_d_done:
+ srl t5, t4, 20 # get exponent
+ and t5, t5, 0x7FF
+ and t6, t4, 0xFFFFF # get fraction
+ srl t4, t4, 31 # get sign
+ j ra
+END(get_cmp_d)
+
+/*----------------------------------------------------------------------------
+ * set_fd_s --
+ *
+ * Write (single precision) the FD register (bits 10-6).
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Arguments:
+ * a0 contains the FP instruction
+ * t0 contains the sign
+ * t1 contains the (biased) exponent
+ * t2 contains the fraction
+ *
+ * set_fd_word --
+ *
+ * Write (integer) the FD register (bits 10-6).
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Arguments:
+ * a0 contains the FP instruction
+ * t2 contains the integer
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(set_fd_s)
+ sll t0, t0, 31 # position sign
+ sll t1, t1, 23 # position exponent
+ or t2, t2, t0
+ or t2, t2, t1
+ALEAF(set_fd_word)
+ srl a3, a0, 7 - 2 # get FD field (even regs only)
+ and a3, a3, 0xF << 2 # mask FT field
+ lw a3, set_fd_s_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+set_fd_s_tbl:
+ .word set_fd_s_f0
+ .word set_fd_s_f2
+ .word set_fd_s_f4
+ .word set_fd_s_f6
+ .word set_fd_s_f8
+ .word set_fd_s_f10
+ .word set_fd_s_f12
+ .word set_fd_s_f14
+ .word set_fd_s_f16
+ .word set_fd_s_f18
+ .word set_fd_s_f20
+ .word set_fd_s_f22
+ .word set_fd_s_f24
+ .word set_fd_s_f26
+ .word set_fd_s_f28
+ .word set_fd_s_f30
+ .text
+
+set_fd_s_f0:
+ mtc1 t2, $f0
+ j ra
+set_fd_s_f2:
+ mtc1 t2, $f2
+ j ra
+set_fd_s_f4:
+ mtc1 t2, $f4
+ j ra
+set_fd_s_f6:
+ mtc1 t2, $f6
+ j ra
+set_fd_s_f8:
+ mtc1 t2, $f8
+ j ra
+set_fd_s_f10:
+ mtc1 t2, $f10
+ j ra
+set_fd_s_f12:
+ mtc1 t2, $f12
+ j ra
+set_fd_s_f14:
+ mtc1 t2, $f14
+ j ra
+set_fd_s_f16:
+ mtc1 t2, $f16
+ j ra
+set_fd_s_f18:
+ mtc1 t2, $f18
+ j ra
+set_fd_s_f20:
+ mtc1 t2, $f20
+ j ra
+set_fd_s_f22:
+ mtc1 t2, $f22
+ j ra
+set_fd_s_f24:
+ mtc1 t2, $f24
+ j ra
+set_fd_s_f26:
+ mtc1 t2, $f26
+ j ra
+set_fd_s_f28:
+ mtc1 t2, $f28
+ j ra
+set_fd_s_f30:
+ mtc1 t2, $f30
+ j ra
+END(set_fd_s)
+
+/*----------------------------------------------------------------------------
+ * set_fd_d --
+ *
+ * Write (double precision) the FT register (bits 10-6).
+ * This is an internal routine used by MachEmulateFP only.
+ *
+ * Arguments:
+ * a0 contains the FP instruction
+ * t0 contains the sign
+ * t1 contains the (biased) exponent
+ * t2 contains the fraction
+ * t3 contains the remaining fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(set_fd_d)
+ sll t0, t0, 31 # set sign
+ sll t1, t1, 20 # set exponent
+ or t0, t0, t1
+ or t0, t0, t2 # set fraction
+ srl a3, a0, 7 - 2 # get FD field (even regs only)
+ and a3, a3, 0xF << 2 # mask FD field
+ lw a3, set_fd_d_tbl(a3) # switch on register number
+ j a3
+
+ .rdata
+set_fd_d_tbl:
+ .word set_fd_d_f0
+ .word set_fd_d_f2
+ .word set_fd_d_f4
+ .word set_fd_d_f6
+ .word set_fd_d_f8
+ .word set_fd_d_f10
+ .word set_fd_d_f12
+ .word set_fd_d_f14
+ .word set_fd_d_f16
+ .word set_fd_d_f18
+ .word set_fd_d_f20
+ .word set_fd_d_f22
+ .word set_fd_d_f24
+ .word set_fd_d_f26
+ .word set_fd_d_f28
+ .word set_fd_d_f30
+ .text
+
+set_fd_d_f0:
+ mtc1 t3, $f0
+ mtc1 t0, $f1
+ j ra
+set_fd_d_f2:
+ mtc1 t3, $f2
+ mtc1 t0, $f3
+ j ra
+set_fd_d_f4:
+ mtc1 t3, $f4
+ mtc1 t0, $f5
+ j ra
+set_fd_d_f6:
+ mtc1 t3, $f6
+ mtc1 t0, $f7
+ j ra
+set_fd_d_f8:
+ mtc1 t3, $f8
+ mtc1 t0, $f9
+ j ra
+set_fd_d_f10:
+ mtc1 t3, $f10
+ mtc1 t0, $f11
+ j ra
+set_fd_d_f12:
+ mtc1 t3, $f12
+ mtc1 t0, $f13
+ j ra
+set_fd_d_f14:
+ mtc1 t3, $f14
+ mtc1 t0, $f15
+ j ra
+set_fd_d_f16:
+ mtc1 t3, $f16
+ mtc1 t0, $f17
+ j ra
+set_fd_d_f18:
+ mtc1 t3, $f18
+ mtc1 t0, $f19
+ j ra
+set_fd_d_f20:
+ mtc1 t3, $f20
+ mtc1 t0, $f21
+ j ra
+set_fd_d_f22:
+ mtc1 t3, $f22
+ mtc1 t0, $f23
+ j ra
+set_fd_d_f24:
+ mtc1 t3, $f24
+ mtc1 t0, $f25
+ j ra
+set_fd_d_f26:
+ mtc1 t3, $f26
+ mtc1 t0, $f27
+ j ra
+set_fd_d_f28:
+ mtc1 t3, $f28
+ mtc1 t0, $f29
+ j ra
+set_fd_d_f30:
+ mtc1 t3, $f30
+ mtc1 t0, $f31
+ j ra
+END(set_fd_d)
+
+/*----------------------------------------------------------------------------
+ * renorm_fs_s --
+ *
+ * Results:
+ * t1 unbiased exponent
+ * t2 normalized fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(renorm_fs_s)
+/*
+ * Find out how many leading zero bits are in t2 and put in t9.
+ */
+ move v0, t2
+ move t9, zero
+ srl v1, v0, 16
+ bne v1, zero, 1f
+ addu t9, 16
+ sll v0, 16
+1:
+ srl v1, v0, 24
+ bne v1, zero, 1f
+ addu t9, 8
+ sll v0, 8
+1:
+ srl v1, v0, 28
+ bne v1, zero, 1f
+ addu t9, 4
+ sll v0, 4
+1:
+ srl v1, v0, 30
+ bne v1, zero, 1f
+ addu t9, 2
+ sll v0, 2
+1:
+ srl v1, v0, 31
+ bne v1, zero, 1f
+ addu t9, 1
+/*
+ * Now shift t2 the correct number of bits.
+ */
+1:
+ subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
+ li t1, SEXP_MIN
+ subu t1, t1, t9 # adjust exponent
+ sll t2, t2, t9
+ j ra
+END(renorm_fs_s)
+
+/*----------------------------------------------------------------------------
+ * renorm_fs_d --
+ *
+ * Results:
+ * t1 unbiased exponent
+ * t2,t3 normalized fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(renorm_fs_d)
+/*
+ * Find out how many leading zero bits are in t2,t3 and put in t9.
+ */
+ move v0, t2
+ move t9, zero
+ bne t2, zero, 1f
+ move v0, t3
+ addu t9, 32
+1:
+ srl v1, v0, 16
+ bne v1, zero, 1f
+ addu t9, 16
+ sll v0, 16
+1:
+ srl v1, v0, 24
+ bne v1, zero, 1f
+ addu t9, 8
+ sll v0, 8
+1:
+ srl v1, v0, 28
+ bne v1, zero, 1f
+ addu t9, 4
+ sll v0, 4
+1:
+ srl v1, v0, 30
+ bne v1, zero, 1f
+ addu t9, 2
+ sll v0, 2
+1:
+ srl v1, v0, 31
+ bne v1, zero, 1f
+ addu t9, 1
+/*
+ * Now shift t2,t3 the correct number of bits.
+ */
+1:
+ subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
+ li t1, DEXP_MIN
+ subu t1, t1, t9 # adjust exponent
+ li v0, 32
+ blt t9, v0, 1f
+ subu t9, t9, v0 # shift fraction left >= 32 bits
+ sll t2, t3, t9
+ move t3, zero
+ j ra
+1:
+ subu v0, v0, t9 # shift fraction left < 32 bits
+ sll t2, t2, t9
+ srl v1, t3, v0
+ or t2, t2, v1
+ sll t3, t3, t9
+ j ra
+END(renorm_fs_d)
+
+/*----------------------------------------------------------------------------
+ * renorm_ft_s --
+ *
+ * Results:
+ * t5 unbiased exponent
+ * t6 normalized fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(renorm_ft_s)
+/*
+ * Find out how many leading zero bits are in t6 and put in t9.
+ */
+ move v0, t6
+ move t9, zero
+ srl v1, v0, 16
+ bne v1, zero, 1f
+ addu t9, 16
+ sll v0, 16
+1:
+ srl v1, v0, 24
+ bne v1, zero, 1f
+ addu t9, 8
+ sll v0, 8
+1:
+ srl v1, v0, 28
+ bne v1, zero, 1f
+ addu t9, 4
+ sll v0, 4
+1:
+ srl v1, v0, 30
+ bne v1, zero, 1f
+ addu t9, 2
+ sll v0, 2
+1:
+ srl v1, v0, 31
+ bne v1, zero, 1f
+ addu t9, 1
+/*
+ * Now shift t6 the correct number of bits.
+ */
+1:
+ subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
+ li t5, SEXP_MIN
+ subu t5, t5, t9 # adjust exponent
+ sll t6, t6, t9
+ j ra
+END(renorm_ft_s)
+
+/*----------------------------------------------------------------------------
+ * renorm_ft_d --
+ *
+ * Results:
+ * t5 unbiased exponent
+ * t6,t7 normalized fraction
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(renorm_ft_d)
+/*
+ * Find out how many leading zero bits are in t6,t7 and put in t9.
+ */
+ move v0, t6
+ move t9, zero
+ bne t6, zero, 1f
+ move v0, t7
+ addu t9, 32
+1:
+ srl v1, v0, 16
+ bne v1, zero, 1f
+ addu t9, 16
+ sll v0, 16
+1:
+ srl v1, v0, 24
+ bne v1, zero, 1f
+ addu t9, 8
+ sll v0, 8
+1:
+ srl v1, v0, 28
+ bne v1, zero, 1f
+ addu t9, 4
+ sll v0, 4
+1:
+ srl v1, v0, 30
+ bne v1, zero, 1f
+ addu t9, 2
+ sll v0, 2
+1:
+ srl v1, v0, 31
+ bne v1, zero, 1f
+ addu t9, 1
+/*
+ * Now shift t6,t7 the correct number of bits.
+ */
+1:
+ subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
+ li t5, DEXP_MIN
+ subu t5, t5, t9 # adjust exponent
+ li v0, 32
+ blt t9, v0, 1f
+ subu t9, t9, v0 # shift fraction left >= 32 bits
+ sll t6, t7, t9
+ move t7, zero
+ j ra
+1:
+ subu v0, v0, t9 # shift fraction left < 32 bits
+ sll t6, t6, t9
+ srl v1, t7, v0
+ or t6, t6, v1
+ sll t7, t7, t9
+ j ra
+END(renorm_ft_d)
diff --git a/sys/arch/arc/arc/genassym.c b/sys/arch/arc/arc/genassym.c
new file mode 100644
index 00000000000..5e3be6b774a
--- /dev/null
+++ b/sys/arch/arc/arc/genassym.c
@@ -0,0 +1,74 @@
+/* $OpenBSD: genassym.c,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)genassym.c 8.2 (Berkeley) 9/23/93
+ * $Id: genassym.c,v 1.1 1996/06/24 09:07:20 pefo Exp $
+ */
+
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/user.h>
+
+#include <machine/reg.h>
+
+main()
+{
+ register struct proc *p = (struct proc *)0;
+ register struct user *up = (struct user *)0;
+ register struct vmmeter *vm = (struct vmmeter *)0;
+ register int size, s, n;
+
+ printf("#define\tP_FORW %d\n", &p->p_forw);
+ printf("#define\tP_BACK %d\n", &p->p_back);
+ printf("#define\tP_PRIORITY %d\n", &p->p_priority);
+ printf("#define\tP_ADDR %d\n", &p->p_addr);
+ printf("#define\tP_UPTE %d\n", p->p_md.md_upte);
+ printf("#define\tU_PCB_REGS %d\n", up->u_pcb.pcb_regs);
+ printf("#define\tU_PCB_FPREGS %d\n", &up->u_pcb.pcb_regs[F0]);
+ printf("#define\tU_PCB_CONTEXT %d\n", &up->u_pcb.pcb_context);
+ printf("#define\tU_PCB_ONFAULT %d\n", &up->u_pcb.pcb_onfault);
+ printf("#define\tU_PCB_SEGTAB %d\n", &up->u_pcb.pcb_segtab);
+ printf("#define\tVM_MIN_ADDRESS 0x%x\n", VM_MIN_ADDRESS);
+ printf("#define\tVM_MIN_KERNEL_ADDRESS 0x%x\n", VM_MIN_KERNEL_ADDRESS);
+ printf("#define\tV_SWTCH %d\n", &vm->v_swtch);
+ printf("#define\tSIGILL %d\n", SIGILL);
+ printf("#define\tSIGFPE %d\n", SIGFPE);
+ exit(0);
+}
diff --git a/sys/arch/arc/arc/locore.S b/sys/arch/arc/arc/locore.S
new file mode 100644
index 00000000000..5c3e375c0d1
--- /dev/null
+++ b/sys/arch/arc/arc/locore.S
@@ -0,0 +1,2880 @@
+/* $OpenBSD: locore.S,v 1.1 1996/06/24 09:07:20 pefo Exp $ */
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Digital Equipment Corporation and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (C) 1989 Digital Equipment Corporation.
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies.
+ * Digital Equipment Corporation makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
+ * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL)
+ * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
+ * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL)
+ * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
+ * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL)
+ *
+ * from: @(#)locore.s 8.5 (Berkeley) 1/4/94
+ * $Id: locore.S,v 1.1 1996/06/24 09:07:20 pefo Exp $
+ */
+
+/*
+ * Contains code that is the first executed at boot time plus
+ * assembly language support routines.
+ */
+
+#include <sys/errno.h>
+#include <sys/syscall.h>
+
+#include <machine/param.h>
+#include <machine/psl.h>
+#include <machine/asm.h>
+#include <machine/cpu.h>
+#include <machine/regnum.h>
+#include <machine/pte.h>
+
+#include "assym.h"
+
+ .set noreorder
+
+/*
+ * Amount to take off of the stack for the benefit of the debugger.
+ */
+#define START_FRAME ((4 * 4) + 4 + 4)
+
+ .globl start
+start:
+ mtc0 zero, COP_0_STATUS_REG # Disable interrupts
+ mtc0 zero, COP_0_CAUSE_REG # Clear soft interrupts
+
+/*
+ * Initialize stack and call machine startup.
+ */
+ la sp, start - START_FRAME
+ la gp, _gp
+ sw zero, START_FRAME - 4(sp) # Zero out old ra for debugger
+ jal mips_init # mips_init(argc, argv, envp)
+ sw zero, START_FRAME - 8(sp) # Zero out old fp for debugger
+
+ li t0, SR_COP_1_BIT # Disable interrupts and
+ mtc0 t0, COP_0_STATUS_REG # enable the fp coprocessor
+ li sp, KERNELSTACK - START_FRAME # switch to standard stack
+ mfc0 t0, COP_0_PRID # read processor ID register
+ nop
+ nop # wait for new status to
+ nop # to be effective
+ nop
+ cfc1 t1, FPC_ID # read FPU ID register
+ sw t0, cpu_id # save PRID register
+ sw t1, fpu_id # save FPU ID register
+ jal main # main(regs)
+ move a0, zero
+/*
+ * proc[1] == /etc/init now running here.
+ * Restore user registers and return.
+ */
+ .set noat
+ li v0, SR_EXL
+ mtc0 v0, COP_0_STATUS_REG # set exeption level bit.
+ lw a0, UADDR+U_PCB_REGS+(SR * 4)
+ lw t0, UADDR+U_PCB_REGS+(MULLO * 4)
+ lw t1, UADDR+U_PCB_REGS+(MULHI * 4)
+ mtlo t0
+ mthi t1
+ lw a0, UADDR+U_PCB_REGS+(PC * 4)
+ lw AT, UADDR+U_PCB_REGS+(AST * 4)
+ lw v0, UADDR+U_PCB_REGS+(V0 * 4)
+ dmtc0 a0, COP_0_EXC_PC # set return address
+ li a0, PSL_USERSET
+ mtc0 a0, COP_0_STATUS_REG # switch to user mode (when eret...)
+ lw v1, UADDR+U_PCB_REGS+(V1 * 4)
+ lw a0, UADDR+U_PCB_REGS+(A0 * 4)
+ lw a1, UADDR+U_PCB_REGS+(A1 * 4)
+ lw a2, UADDR+U_PCB_REGS+(A2 * 4)
+ lw a3, UADDR+U_PCB_REGS+(A3 * 4)
+ lw t0, UADDR+U_PCB_REGS+(T0 * 4)
+ lw t1, UADDR+U_PCB_REGS+(T1 * 4)
+ lw t2, UADDR+U_PCB_REGS+(T2 * 4)
+ lw t3, UADDR+U_PCB_REGS+(T3 * 4)
+ lw t4, UADDR+U_PCB_REGS+(T4 * 4)
+ lw t5, UADDR+U_PCB_REGS+(T5 * 4)
+ lw t6, UADDR+U_PCB_REGS+(T6 * 4)
+ lw t7, UADDR+U_PCB_REGS+(T7 * 4)
+ lw s0, UADDR+U_PCB_REGS+(S0 * 4)
+ lw s1, UADDR+U_PCB_REGS+(S1 * 4)
+ lw s2, UADDR+U_PCB_REGS+(S2 * 4)
+ lw s3, UADDR+U_PCB_REGS+(S3 * 4)
+ lw s4, UADDR+U_PCB_REGS+(S4 * 4)
+ lw s5, UADDR+U_PCB_REGS+(S5 * 4)
+ lw s6, UADDR+U_PCB_REGS+(S6 * 4)
+ lw s7, UADDR+U_PCB_REGS+(S7 * 4)
+ lw t8, UADDR+U_PCB_REGS+(T8 * 4)
+ lw gp, UADDR+U_PCB_REGS+(GP * 4)
+ lw sp, UADDR+U_PCB_REGS+(SP * 4)
+ lw s8, UADDR+U_PCB_REGS+(S8 * 4)
+ lw ra, UADDR+U_PCB_REGS+(RA * 4)
+ lw t9, UADDR+U_PCB_REGS+(T9 * 4)
+ eret
+ .set at
+
+/*
+ * Primitives
+ */
+
+/*
+ * This table is indexed by u.u_pcb.pcb_onfault in trap().
+ * The reason for using this table rather than storing an address in
+ * u.u_pcb.pcb_onfault is simply to make the code faster.
+ */
+ .globl onfault_table
+ .data
+ .align 2
+onfault_table:
+ .word 0 # invalid index number
+#define BADERR 1
+ .word baderr
+#define COPYERR 2
+ .word copyerr
+#define FSWBERR 3
+ .word fswberr
+#define FSWINTRBERR 4
+ .word fswintrberr
+#ifdef DEBUG
+#define MDBERR 5
+ .word mdberr
+#endif
+ .text
+
+/*
+ * See if access to addr with a len type instruction causes a machine check.
+ * len is length of access (1=byte, 2=short, 4=long)
+ *
+ * badaddr(addr, len)
+ * char *addr;
+ * int len;
+ */
+LEAF(badaddr)
+ li v0, BADERR
+ bne a1, 1, 2f
+ sw v0, UADDR+U_PCB_ONFAULT
+ b 5f
+ lbu v0, (a0)
+2:
+ bne a1, 2, 4f
+ nop
+ b 5f
+ lhu v0, (a0)
+4:
+ lw v0, (a0)
+5:
+ sw zero, UADDR+U_PCB_ONFAULT
+ j ra
+ move v0, zero # made it w/o errors
+baderr:
+ j ra
+ li v0, 1 # trap sends us here
+END(badaddr)
+
+/*
+ * This code is copied the user's stack for returning from signal handlers
+ * (see sendsig() and sigreturn()). We have to compute the address
+ * of the sigcontext struct for the sigreturn call.
+ */
+ .globl sigcode
+sigcode:
+ addu a0, sp, 16 # address of sigcontext
+ li v0, SYS_sigreturn # sigreturn(scp)
+ syscall
+ break 0 # just in case sigreturn fails
+ .globl esigcode
+esigcode:
+
+/*
+ * Copy a null terminated string within the kernel address space.
+ * Maxlength may be null if count not wanted.
+ * copystr(fromaddr, toaddr, maxlength, &lencopied)
+ * caddr_t fromaddr;
+ * caddr_t toaddr;
+ * u_int maxlength;
+ * u_int *lencopied;
+ */
+LEAF(copystr)
+ move t2, a2 # Save the number of bytes
+1:
+ lbu t0, 0(a0)
+ subu a2, a2, 1
+ beq t0, zero, 2f
+ sb t0, 0(a1)
+ addu a0, a0, 1
+ bne a2, zero, 1b
+ addu a1, a1, 1
+2:
+ beq a3, zero, 3f
+ subu a2, t2, a2 # compute length copied
+ sw a2, 0(a3)
+3:
+ j ra
+ move v0, zero
+END(copystr)
+
+/*
+ * fillw(pat, addr, count)
+ */
+LEAF(fillw)
+1:
+ addiu a2, a2, -1
+ sh a0, 0(a1)
+ bne a2,zero, 1b
+ addiu a1, a1, 2
+
+ jr ra
+ nop
+END(fillw)
+
+/*
+ * Copy a null terminated string from the user address space into
+ * the kernel address space.
+ *
+ * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
+ * caddr_t fromaddr;
+ * caddr_t toaddr;
+ * u_int maxlength;
+ * u_int *lencopied;
+ */
+NON_LEAF(copyinstr, STAND_FRAME_SIZE, ra)
+ subu sp, sp, STAND_FRAME_SIZE
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+ sw ra, STAND_RA_OFFSET(sp)
+ blt a0, zero, copyerr # make sure address is in user space
+ li v0, COPYERR
+ jal copystr
+ sw v0, UADDR+U_PCB_ONFAULT
+ lw ra, STAND_RA_OFFSET(sp)
+ sw zero, UADDR+U_PCB_ONFAULT
+ addu sp, sp, STAND_FRAME_SIZE
+ j ra
+ move v0, zero
+END(copyinstr)
+
+/*
+ * Copy a null terminated string from the kernel address space into
+ * the user address space.
+ *
+ * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
+ * caddr_t fromaddr;
+ * caddr_t toaddr;
+ * u_int maxlength;
+ * u_int *lencopied;
+ */
+NON_LEAF(copyoutstr, STAND_FRAME_SIZE, ra)
+ subu sp, sp, STAND_FRAME_SIZE
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+ sw ra, STAND_RA_OFFSET(sp)
+ blt a1, zero, copyerr # make sure address is in user space
+ li v0, COPYERR
+ jal copystr
+ sw v0, UADDR+U_PCB_ONFAULT
+ lw ra, STAND_RA_OFFSET(sp)
+ sw zero, UADDR+U_PCB_ONFAULT
+ addu sp, sp, STAND_FRAME_SIZE
+ j ra
+ move v0, zero
+END(copyoutstr)
+
+/*
+ * Copy specified amount of data from user space into the kernel
+ * copyin(from, to, len)
+ * caddr_t *from; (user source address)
+ * caddr_t *to; (kernel destination address)
+ * unsigned len;
+ */
+NON_LEAF(copyin, STAND_FRAME_SIZE, ra)
+ subu sp, sp, STAND_FRAME_SIZE
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+ sw ra, STAND_RA_OFFSET(sp)
+ blt a0, zero, copyerr # make sure address is in user space
+ li v0, COPYERR
+ jal bcopy
+ sw v0, UADDR+U_PCB_ONFAULT
+ lw ra, STAND_RA_OFFSET(sp)
+ sw zero, UADDR+U_PCB_ONFAULT
+ addu sp, sp, STAND_FRAME_SIZE
+ j ra
+ move v0, zero
+END(copyin)
+
+/*
+ * Copy specified amount of data from kernel to the user space
+ * copyout(from, to, len)
+ * caddr_t *from; (kernel source address)
+ * caddr_t *to; (user destination address)
+ * unsigned len;
+ */
+NON_LEAF(copyout, STAND_FRAME_SIZE, ra)
+ subu sp, sp, STAND_FRAME_SIZE
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+ sw ra, STAND_RA_OFFSET(sp)
+ blt a1, zero, copyerr # make sure address is in user space
+ li v0, COPYERR
+ jal bcopy
+ sw v0, UADDR+U_PCB_ONFAULT
+ lw ra, STAND_RA_OFFSET(sp)
+ sw zero, UADDR+U_PCB_ONFAULT
+ addu sp, sp, STAND_FRAME_SIZE
+ j ra
+ move v0, zero
+END(copyout)
+
+LEAF(copyerr)
+ lw ra, STAND_RA_OFFSET(sp)
+ sw zero, UADDR+U_PCB_ONFAULT
+ addu sp, sp, STAND_FRAME_SIZE
+ j ra
+ li v0, EFAULT # return error
+END(copyerr)
+
+/*
+ * Copy the kernel stack to the new process and save the current context so
+ * the new process will return nonzero when it is resumed by cpu_switch().
+ *
+ * copykstack(up)
+ * struct user *up;
+ */
+LEAF(copykstack)
+ subu v0, sp, UADDR # compute offset into stack
+ addu v0, v0, a0 # v0 = new stack address
+ move v1, sp # v1 = old stack address
+ li t1, KERNELSTACK
+1:
+ lw t0, 0(v1) # copy stack data
+ addu v1, v1, 4
+ sw t0, 0(v0)
+ bne v1, t1, 1b
+ addu v0, v0, 4
+ /* FALLTHROUGH */
+/*
+ * Save registers and state so we can do a longjmp later.
+ * Note: this only works if p != curproc since
+ * cpu_switch() will copy over pcb_context.
+ *
+ * savectx(up)
+ * struct user *up;
+ */
+ALEAF(savectx)
+ sw s0, U_PCB_CONTEXT+0(a0)
+ sw s1, U_PCB_CONTEXT+4(a0)
+ sw s2, U_PCB_CONTEXT+8(a0)
+ sw s3, U_PCB_CONTEXT+12(a0)
+ mfc0 v0, COP_0_STATUS_REG
+ sw s4, U_PCB_CONTEXT+16(a0)
+ sw s5, U_PCB_CONTEXT+20(a0)
+ sw s6, U_PCB_CONTEXT+24(a0)
+ sw s7, U_PCB_CONTEXT+28(a0)
+ sw sp, U_PCB_CONTEXT+32(a0)
+ sw s8, U_PCB_CONTEXT+36(a0)
+ sw ra, U_PCB_CONTEXT+40(a0)
+ sw v0, U_PCB_CONTEXT+44(a0)
+ j ra
+ move v0, zero
+END(copykstack)
+
+/*
+ * The following primitives manipulate the run queues. _whichqs tells which
+ * of the 32 queues _qs have processes in them. Setrunqueue puts processes
+ * into queues, Remrq removes them from queues. The running process is on
+ * no queue, other processes are on a queue related to p->p_priority, divided
+ * by 4 actually to shrink the 0-127 range of priorities into the 32 available
+ * queues.
+ */
+/*
+ * setrunqueue(p)
+ * proc *p;
+ *
+ * Call should be made at splclock(), and p->p_stat should be SRUN.
+ */
+NON_LEAF(setrunqueue, STAND_FRAME_SIZE, ra)
+ subu sp, sp, STAND_FRAME_SIZE
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+ lw t0, P_BACK(a0) ## firewall: p->p_back must be 0
+ sw ra, STAND_RA_OFFSET(sp) ##
+ beq t0, zero, 1f ##
+ lbu t0, P_PRIORITY(a0) # put on p->p_priority / 4 queue
+ PANIC("setrunqueue") ##
+1:
+ li t1, 1 # compute corresponding bit
+ srl t0, t0, 2 # compute index into 'whichqs'
+ sll t1, t1, t0
+ lw t2, whichqs # set corresponding bit
+ nop
+ or t2, t2, t1
+ sw t2, whichqs
+ sll t0, t0, 3 # compute index into 'qs'
+ la t1, qs
+ addu t0, t0, t1 # t0 = qp = &qs[pri >> 2]
+ lw t1, P_BACK(t0) # t1 = qp->ph_rlink
+ sw t0, P_FORW(a0) # p->p_forw = qp
+ sw t1, P_BACK(a0) # p->p_back = qp->ph_rlink
+ sw a0, P_FORW(t1) # p->p_back->p_forw = p;
+ sw a0, P_BACK(t0) # qp->ph_rlink = p
+ j ra
+ addu sp, sp, STAND_FRAME_SIZE
+END(setrunqueue)
+
+/*
+ * Remrq(p)
+ *
+ * Call should be made at splclock().
+ */
+NON_LEAF(remrq, STAND_FRAME_SIZE, ra)
+ subu sp, sp, STAND_FRAME_SIZE
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+ lbu t0, P_PRIORITY(a0) # get from p->p_priority / 4 queue
+ li t1, 1 # compute corresponding bit
+ srl t0, t0, 2 # compute index into 'whichqs'
+ lw t2, whichqs # check corresponding bit
+ sll t1, t1, t0
+ and v0, t2, t1
+ sw ra, STAND_RA_OFFSET(sp) ##
+ bne v0, zero, 1f ##
+ lw v0, P_BACK(a0) # v0 = p->p_back
+ PANIC("remrq") ## it wasnt recorded to be on its q
+1:
+ lw v1, P_FORW(a0) # v1 = p->p_forw
+ nop
+ sw v1, P_FORW(v0) # p->p_back->p_forw = p->p_forw;
+ sw v0, P_BACK(v1) # p->p_forw->p_back = p->r_rlink
+ sll t0, t0, 3 # compute index into 'qs'
+ la v0, qs
+ addu t0, t0, v0 # t0 = qp = &qs[pri >> 2]
+ lw v0, P_FORW(t0) # check if queue empty
+ nop
+ bne v0, t0, 2f # No. qp->ph_link != qp
+ nop
+ xor t2, t2, t1 # clear corresponding bit in 'whichqs'
+ sw t2, whichqs
+2:
+ sw zero, P_BACK(a0) ## for firewall checking
+ j ra
+ addu sp, sp, STAND_FRAME_SIZE
+END(remrq)
+
+/*
+ * switch_exit()
+ *
+ * At exit of a process, do a cpu_switch for the last time.
+ * The mapping of the pcb at p->p_addr has already been deleted,
+ * and the memory for the pcb+stack has been freed.
+ * All interrupts should be blocked at this point.
+ */
+LEAF(switch_exit)
+ la v1, nullproc # save state into garbage proc
+ lw t0, P_UPTE+0(v1) # t0 = first u. pte
+ lw t1, P_UPTE+4(v1) # t1 = 2nd u. pte
+ li v0, UADDR # v0 = first HI entry
+ mtc0 zero, COP_0_TLB_INDEX # set the index register
+ dmtc0 v0, COP_0_TLB_HI # init high entry
+ dmtc0 t0, COP_0_TLB_LO0 # init low entry0
+ dmtc0 t1, COP_0_TLB_LO1 # init low entry1
+ nop
+ tlbwi # Write the TLB entry.
+ nop
+ nop
+ sw zero, curproc
+ b cpu_switch
+ li sp, KERNELSTACK - START_FRAME # switch to standard stack
+END(switch_exit)
+
+/*
+ * When no processes are on the runq, cpu_switch branches to idle
+ * to wait for something to come ready.
+ * Note: this is really a part of cpu_switch() but defined here for kernel
+ * profiling.
+ */
+LEAF(idle)
+ li t0, (INT_MASK | SR_INT_ENAB)
+ mtc0 t0, COP_0_STATUS_REG # enable all interrupts
+ sw zero, curproc # set curproc NULL for stats
+1:
+ lw t0, whichqs # look for non-empty queue
+ nop
+ beq t0, zero, 1b
+ nop
+ b sw1
+ mtc0 zero, COP_0_STATUS_REG # Disable all interrupts
+END(idle)
+
+/*
+ * cpu_switch()
+ * Find the highest priority process and resume it.
+ */
+NON_LEAF(cpu_switch, STAND_FRAME_SIZE, ra)
+ sw sp, UADDR+U_PCB_CONTEXT+32 # save old sp
+ subu sp, sp, STAND_FRAME_SIZE
+ sw ra, STAND_RA_OFFSET(sp)
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+ lw t2, cnt+V_SWTCH # for statistics
+ lw t1, whichqs # look for non-empty queue
+ sw s0, UADDR+U_PCB_CONTEXT+0 # do a 'savectx()'
+ sw s1, UADDR+U_PCB_CONTEXT+4
+ sw s2, UADDR+U_PCB_CONTEXT+8
+ sw s3, UADDR+U_PCB_CONTEXT+12
+ mfc0 t0, COP_0_STATUS_REG # t0 = saved status register
+ sw s4, UADDR+U_PCB_CONTEXT+16
+ sw s5, UADDR+U_PCB_CONTEXT+20
+ sw s6, UADDR+U_PCB_CONTEXT+24
+ sw s7, UADDR+U_PCB_CONTEXT+28
+ sw s8, UADDR+U_PCB_CONTEXT+36
+ sw ra, UADDR+U_PCB_CONTEXT+40 # save return address
+ sw t0, UADDR+U_PCB_CONTEXT+44 # save status register
+ addu t2, t2, 1
+ sw t2, cnt+V_SWTCH
+ beq t1, zero, idle # if none, idle
+ mtc0 zero, COP_0_STATUS_REG # Disable all interrupts
+sw1:
+ nop # wait for intrs disabled
+ nop
+ nop
+ nop
+ lw t0, whichqs # look for non-empty queue
+ li t2, -1 # t2 = lowest bit set
+ beq t0, zero, idle # if none, idle
+ move t3, t0 # t3 = saved whichqs
+1:
+ addu t2, t2, 1
+ and t1, t0, 1 # bit set?
+ beq t1, zero, 1b
+ srl t0, t0, 1 # try next bit
+/*
+ * Remove process from queue.
+ */
+ sll t0, t2, 3
+ la t1, qs
+ addu t0, t0, t1 # t0 = qp = &qs[highbit]
+ lw a0, P_FORW(t0) # a0 = p = highest pri process
+ nop
+ lw v0, P_FORW(a0) # v0 = p->p_forw
+ bne t0, a0, 2f # make sure something in queue
+ sw v0, P_FORW(t0) # qp->ph_link = p->p_forw;
+ PANIC("cpu_switch") # nothing in queue
+2:
+ sw t0, P_BACK(v0) # p->p_forw->p_back = qp
+ bne v0, t0, 3f # queue still not empty
+ sw zero, P_BACK(a0) ## for firewall checking
+ li v1, 1 # compute bit in 'whichqs'
+ sll v1, v1, t2
+ xor t3, t3, v1 # clear bit in 'whichqs'
+ sw t3, whichqs
+3:
+/*
+ * Switch to new context.
+ */
+ sw zero, want_resched
+ jal pmap_alloc_tlbpid # v0 = TLB PID
+ move s0, a0 # BDSLOT: save p
+ sw s0, curproc # set curproc
+ lw t0, P_UPTE+0(s0) # t0 = first u. pte
+ lw t1, P_UPTE+4(s0) # t1 = 2nd u. pte
+ or v0, v0, UADDR # v0 = first HI entry
+/*
+ * Resume process indicated by the pte's for its u struct
+ * NOTE: This is hard coded to UPAGES == 2.
+ * Also, there should be no TLB faults at this point.
+ */
+ mtc0 zero, COP_0_TLB_INDEX # set the index register
+ dmtc0 v0, COP_0_TLB_HI # init high entry
+ dmtc0 t0, COP_0_TLB_LO0 # init low entry0
+ dmtc0 t1, COP_0_TLB_LO1 # init low entry1
+ nop
+ tlbwi # Write the TLB entry.
+ nop # Delay for effect
+ nop # Delay for effect
+ nop
+ nop
+/*
+ * Now running on new u struct.
+ * Restore registers and return.
+ */
+ lw v0, UADDR+U_PCB_CONTEXT+44 # restore kernel context
+ lw ra, UADDR+U_PCB_CONTEXT+40
+ lw s0, UADDR+U_PCB_CONTEXT+0
+ lw s1, UADDR+U_PCB_CONTEXT+4
+ lw s2, UADDR+U_PCB_CONTEXT+8
+ lw s3, UADDR+U_PCB_CONTEXT+12
+ lw s4, UADDR+U_PCB_CONTEXT+16
+ lw s5, UADDR+U_PCB_CONTEXT+20
+ lw s6, UADDR+U_PCB_CONTEXT+24
+ lw s7, UADDR+U_PCB_CONTEXT+28
+ lw sp, UADDR+U_PCB_CONTEXT+32
+ lw s8, UADDR+U_PCB_CONTEXT+36
+ mtc0 v0, COP_0_STATUS_REG
+ j ra
+ li v0, 1 # possible return to 'savectx()'
+END(cpu_switch)
+
+/*
+ * {fu,su},{ibyte,isword,iword}, fetch or store a byte, short or word to
+ * user text space.
+ * {fu,su},{byte,sword,word}, fetch or store a byte, short or word to
+ * user data space.
+ */
+LEAF(fuword)
+ALEAF(fuiword)
+ blt a0, zero, fswberr # make sure address is in user space
+ li v0, FSWBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ lw v0, 0(a0) # fetch word
+ j ra
+ sw zero, UADDR+U_PCB_ONFAULT
+END(fuword)
+
+LEAF(fusword)
+ALEAF(fuisword)
+ blt a0, zero, fswberr # make sure address is in user space
+ li v0, FSWBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ lhu v0, 0(a0) # fetch short
+ j ra
+ sw zero, UADDR+U_PCB_ONFAULT
+END(fusword)
+
+LEAF(fubyte)
+ALEAF(fuibyte)
+ blt a0, zero, fswberr # make sure address is in user space
+ li v0, FSWBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ lbu v0, 0(a0) # fetch byte
+ j ra
+ sw zero, UADDR+U_PCB_ONFAULT
+END(fubyte)
+
+LEAF(suword)
+ blt a0, zero, fswberr # make sure address is in user space
+ li v0, FSWBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ sw a1, 0(a0) # store word
+ sw zero, UADDR+U_PCB_ONFAULT
+ j ra
+ move v0, zero
+END(suword)
+
+/*
+ * Have to flush instruction cache afterwards.
+ */
+LEAF(suiword)
+ blt a0, zero, fswberr # make sure address is in user space
+ li v0, FSWBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ sw a1, 0(a0) # store word
+ sw zero, UADDR+U_PCB_ONFAULT
+ move v0, zero
+ b MachFlushICache # NOTE: this should not clobber v0!
+ li a1, 4 # size of word
+END(suiword)
+
+/*
+ * Will have to flush the instruction cache if byte merging is done in hardware.
+ */
+LEAF(susword)
+ALEAF(suisword)
+ blt a0, zero, fswberr # make sure address is in user space
+ li v0, FSWBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ sh a1, 0(a0) # store short
+ sw zero, UADDR+U_PCB_ONFAULT
+ j ra
+ move v0, zero
+END(susword)
+
+LEAF(subyte)
+ALEAF(suibyte)
+ blt a0, zero, fswberr # make sure address is in user space
+ li v0, FSWBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ sb a1, 0(a0) # store byte
+ sw zero, UADDR+U_PCB_ONFAULT
+ j ra
+ move v0, zero
+END(subyte)
+
+LEAF(fswberr)
+ j ra
+ li v0, -1
+END(fswberr)
+
+/*
+ * fuswintr and suswintr are just like fusword and susword except that if
+ * the page is not in memory or would cause a trap, then we return an error.
+ * The important thing is to prevent sleep() and switch().
+ */
+LEAF(fuswintr)
+ blt a0, zero, fswintrberr # make sure address is in user space
+ li v0, FSWINTRBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ lhu v0, 0(a0) # fetch short
+ j ra
+ sw zero, UADDR+U_PCB_ONFAULT
+END(fuswintr)
+
+LEAF(suswintr)
+ blt a0, zero, fswintrberr # make sure address is in user space
+ li v0, FSWINTRBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ sh a1, 0(a0) # store short
+ sw zero, UADDR+U_PCB_ONFAULT
+ j ra
+ move v0, zero
+END(suswintr)
+
+LEAF(fswintrberr)
+ j ra
+ li v0, -1
+END(fswintrberr)
+
+/*
+ * Insert 'p' after 'q'.
+ * _insque(p, q)
+ * caddr_t p, q;
+ */
+LEAF(_insque)
+ lw v0, 0(a1) # v0 = q->next
+ sw a1, 4(a0) # p->prev = q
+ sw v0, 0(a0) # p->next = q->next
+ sw a0, 4(v0) # q->next->prev = p
+ j ra
+ sw a0, 0(a1) # q->next = p
+END(_insque)
+
+/*
+ * Remove item 'p' from queue.
+ * _remque(p)
+ * caddr_t p;
+ */
+LEAF(_remque)
+ lw v0, 0(a0) # v0 = p->next
+ lw v1, 4(a0) # v1 = p->prev
+ nop
+ sw v0, 0(v1) # p->prev->next = p->next
+ j ra
+ sw v1, 4(v0) # p->next->prev = p->prev
+END(_remque)
+
+/*
+ * This code is copied to the TLB exception vector address to
+ * handle TLB translation misses.
+ * NOTE: This code must be relocatable and max 32 instructions!!!
+ * Don't check for invalid pte's here. We load them as well and
+ * let the processor trap to load the correct value after service.
+ */
+ .globl MachTLBMiss
+MachTLBMiss:
+ .set noat
+ dmfc0 k0, COP_0_BAD_VADDR # get the virtual address
+ lw k1, UADDR+U_PCB_SEGTAB # get the current segment table
+ bltz k0, 1f # kernel address space ->
+ srl k0, k0, SEGSHIFT - 2 # compute segment table index
+ andi k0, k0, 0x7fc # PMAP_SEGTABSIZ-1
+ addu k1, k1, k0
+ dmfc0 k0, COP_0_BAD_VADDR # get the virtual address
+ lw k1, 0(k1) # get pointer to segment map
+ srl k0, k0, PGSHIFT - 2 # compute segment map index
+ andi k0, k0, ((NPTEPG/2) - 1) << 3
+ beq k1, zero, 2f # invalid segment map
+ addu k1, k1, k0 # index into segment map
+ lw k0, 0(k1) # get page PTE
+ lw k1, 4(k1)
+ dsll k0, k0, 34
+ dsrl k0, k0, 34
+ dmtc0 k0, COP_0_TLB_LO0
+ dsll k1, k1, 34
+ dsrl k1, k1, 34
+ dmtc0 k1, COP_0_TLB_LO1
+ nop
+ tlbwr # update TLB
+ nop
+ nop
+ nop
+ nop
+ nop
+ eret
+1:
+ j MachTLBMissException
+ nop
+2:
+ j SlowFault
+ nop
+
+ .globl MachTLBMissEnd
+MachTLBMissEnd:
+ .set at
+
+/*
+ * This code is copied to the general exception vector address to
+ * handle all execptions except RESET and TLBMiss.
+ * NOTE: This code must be relocatable!!!
+ */
+ .globl MachException
+MachException:
+/*
+ * Find out what mode we came from and jump to the proper handler.
+ */
+ .set noat
+ mfc0 k0, COP_0_STATUS_REG # Get the status register
+ mfc0 k1, COP_0_CAUSE_REG # Get the cause register value.
+ and k0, k0, SR_KSU_USER # test for user mode
+ # sneaky but the bits are
+ # with us........
+ sll k0, k0, 3 # shift user bit for cause index
+ and k1, k1, CR_EXC_CODE # Mask out the cause bits.
+ or k1, k1, k0 # change index to user table
+1:
+ la k0, machExceptionTable # get base of the jump table
+ addu k0, k0, k1 # Get the address of the
+ # function entry. Note that
+ # the cause is already
+ # shifted left by 2 bits so
+ # we dont have to shift.
+ lw k0, 0(k0) # Get the function address
+ nop
+ j k0 # Jump to the function.
+ nop
+ .set at
+ .globl MachExceptionEnd
+MachExceptionEnd:
+
+/*
+ * We couldn't find a TLB entry.
+ * Find out what mode we came from and call the appropriate handler.
+ */
+SlowFault:
+ .set noat
+ mfc0 k0, COP_0_STATUS_REG
+ nop
+ and k0, k0, SR_KSU_USER
+ bne k0, zero, MachUserGenException
+ nop
+ .set at
+/*
+ * Fall though ...
+ */
+
+/*----------------------------------------------------------------------------
+ *
+ * MachKernGenException --
+ *
+ * Handle an exception from kernel mode.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*
+ * The kernel exception stack contains 18 saved general registers,
+ * the status register and the multiply lo and high registers.
+ * In addition, we set this up for linkage conventions.
+ */
+#define KERN_REG_SIZE (18 * 4)
+#define KERN_REG_OFFSET (STAND_FRAME_SIZE)
+#define KERN_SR_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE)
+#define KERN_MULT_LO_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 4)
+#define KERN_MULT_HI_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 8)
+#define KERN_EXC_FRAME_SIZE (STAND_FRAME_SIZE + KERN_REG_SIZE + 12)
+
+NNON_LEAF(MachKernGenException, KERN_EXC_FRAME_SIZE, ra)
+ .set noat
+#ifdef DEBUG
+ la k0, mdbpcb # save registers for mdb
+ sw s0, (S0 * 4)(k0)
+ sw s1, (S1 * 4)(k0)
+ sw s2, (S2 * 4)(k0)
+ sw s3, (S3 * 4)(k0)
+ sw s4, (S4 * 4)(k0)
+ sw s5, (S5 * 4)(k0)
+ sw s6, (S6 * 4)(k0)
+ sw s7, (S7 * 4)(k0)
+ sw s8, (S8 * 4)(k0)
+ sw gp, (GP * 4)(k0)
+ sw sp, (SP * 4)(k0)
+#endif
+ subu sp, sp, KERN_EXC_FRAME_SIZE
+ .mask 0x80000000, (STAND_RA_OFFSET - KERN_EXC_FRAME_SIZE)
+/*
+ * Save the relevant kernel registers onto the stack.
+ * We don't need to save s0 - s8, sp and gp because
+ * the compiler does it for us.
+ */
+ sw AT, KERN_REG_OFFSET + 0(sp)
+ sw v0, KERN_REG_OFFSET + 4(sp)
+ sw v1, KERN_REG_OFFSET + 8(sp)
+ sw a0, KERN_REG_OFFSET + 12(sp)
+ mflo v0
+ mfhi v1
+ sw a1, KERN_REG_OFFSET + 16(sp)
+ sw a2, KERN_REG_OFFSET + 20(sp)
+ sw a3, KERN_REG_OFFSET + 24(sp)
+ sw t0, KERN_REG_OFFSET + 28(sp)
+ mfc0 a0, COP_0_STATUS_REG # First arg is the status reg.
+ sw t1, KERN_REG_OFFSET + 32(sp)
+ sw t2, KERN_REG_OFFSET + 36(sp)
+ sw t3, KERN_REG_OFFSET + 40(sp)
+ sw t4, KERN_REG_OFFSET + 44(sp)
+ mfc0 a1, COP_0_CAUSE_REG # Second arg is the cause reg.
+ sw t5, KERN_REG_OFFSET + 48(sp)
+ sw t6, KERN_REG_OFFSET + 52(sp)
+ sw t7, KERN_REG_OFFSET + 56(sp)
+ sw t8, KERN_REG_OFFSET + 60(sp)
+ mfc0 a2, COP_0_BAD_VADDR # Third arg is the fault addr.
+ sw t9, KERN_REG_OFFSET + 64(sp)
+ sw ra, KERN_REG_OFFSET + 68(sp)
+ sw v0, KERN_MULT_LO_OFFSET(sp)
+ sw v1, KERN_MULT_HI_OFFSET(sp)
+ mfc0 a3, COP_0_EXC_PC # Fourth arg is the pc.
+ sw a0, KERN_SR_OFFSET(sp)
+
+ mtc0 zero,COP_0_STATUS_REG # Set kernel no error level
+/*
+ * Call the exception handler.
+ */
+ jal trap
+ sw a3, STAND_RA_OFFSET(sp) # for debugging
+/*
+ * Restore registers and return from the exception.
+ * v0 contains the return address.
+ */
+ mtc0 zero,COP_0_STATUS_REG # Make shure int disabled
+ lw a0, KERN_SR_OFFSET(sp)
+ lw t0, KERN_MULT_LO_OFFSET(sp)
+ lw t1, KERN_MULT_HI_OFFSET(sp)
+ mtc0 a0, COP_0_STATUS_REG # Restore the SR, disable intrs
+ mtlo t0
+ mthi t1
+ dmtc0 v0, COP_0_EXC_PC # set return address
+ lw AT, KERN_REG_OFFSET + 0(sp)
+ lw v0, KERN_REG_OFFSET + 4(sp)
+ lw v1, KERN_REG_OFFSET + 8(sp)
+ lw a0, KERN_REG_OFFSET + 12(sp)
+ lw a1, KERN_REG_OFFSET + 16(sp)
+ lw a2, KERN_REG_OFFSET + 20(sp)
+ lw a3, KERN_REG_OFFSET + 24(sp)
+ lw t0, KERN_REG_OFFSET + 28(sp)
+ lw t1, KERN_REG_OFFSET + 32(sp)
+ lw t2, KERN_REG_OFFSET + 36(sp)
+ lw t3, KERN_REG_OFFSET + 40(sp)
+ lw t4, KERN_REG_OFFSET + 44(sp)
+ lw t5, KERN_REG_OFFSET + 48(sp)
+ lw t6, KERN_REG_OFFSET + 52(sp)
+ lw t7, KERN_REG_OFFSET + 56(sp)
+ lw t8, KERN_REG_OFFSET + 60(sp)
+ lw t9, KERN_REG_OFFSET + 64(sp)
+ lw ra, KERN_REG_OFFSET + 68(sp)
+ addu sp, sp, KERN_EXC_FRAME_SIZE
+ eret # exception.
+ .set at
+END(MachKernGenException)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachUserGenException --
+ *
+ * Handle an exception from user mode.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NNON_LEAF(MachUserGenException, STAND_FRAME_SIZE, ra)
+ .set noat
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+/*
+ * Save all of the registers except for the kernel temporaries in u.u_pcb.
+ */
+ sw AT, UADDR+U_PCB_REGS+(AST * 4)
+ sw v0, UADDR+U_PCB_REGS+(V0 * 4)
+ sw v1, UADDR+U_PCB_REGS+(V1 * 4)
+ sw a0, UADDR+U_PCB_REGS+(A0 * 4)
+ mflo v0
+ sw a1, UADDR+U_PCB_REGS+(A1 * 4)
+ sw a2, UADDR+U_PCB_REGS+(A2 * 4)
+ sw a3, UADDR+U_PCB_REGS+(A3 * 4)
+ sw t0, UADDR+U_PCB_REGS+(T0 * 4)
+ mfhi v1
+ sw t1, UADDR+U_PCB_REGS+(T1 * 4)
+ sw t2, UADDR+U_PCB_REGS+(T2 * 4)
+ sw t3, UADDR+U_PCB_REGS+(T3 * 4)
+ sw t4, UADDR+U_PCB_REGS+(T4 * 4)
+ mfc0 a0, COP_0_STATUS_REG # First arg is the status reg.
+ sw t5, UADDR+U_PCB_REGS+(T5 * 4)
+ sw t6, UADDR+U_PCB_REGS+(T6 * 4)
+ sw t7, UADDR+U_PCB_REGS+(T7 * 4)
+ sw s0, UADDR+U_PCB_REGS+(S0 * 4)
+ mfc0 a1, COP_0_CAUSE_REG # Second arg is the cause reg.
+ sw s1, UADDR+U_PCB_REGS+(S1 * 4)
+ sw s2, UADDR+U_PCB_REGS+(S2 * 4)
+ sw s3, UADDR+U_PCB_REGS+(S3 * 4)
+ sw s4, UADDR+U_PCB_REGS+(S4 * 4)
+ mfc0 a2, COP_0_BAD_VADDR # Third arg is the fault addr
+ sw s5, UADDR+U_PCB_REGS+(S5 * 4)
+ sw s6, UADDR+U_PCB_REGS+(S6 * 4)
+ sw s7, UADDR+U_PCB_REGS+(S7 * 4)
+ sw t8, UADDR+U_PCB_REGS+(T8 * 4)
+ mfc0 a3, COP_0_EXC_PC # Fourth arg is the pc.
+ sw t9, UADDR+U_PCB_REGS+(T9 * 4)
+ sw gp, UADDR+U_PCB_REGS+(GP * 4)
+ sw sp, UADDR+U_PCB_REGS+(SP * 4)
+ sw s8, UADDR+U_PCB_REGS+(S8 * 4)
+ li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP
+ sw ra, UADDR+U_PCB_REGS+(RA * 4)
+ sw v0, UADDR+U_PCB_REGS+(MULLO * 4)
+ sw v1, UADDR+U_PCB_REGS+(MULHI * 4)
+ sw a0, UADDR+U_PCB_REGS+(SR * 4)
+ la gp, _gp # switch to kernel GP
+ sw a3, UADDR+U_PCB_REGS+(PC * 4)
+ sw a3, STAND_RA_OFFSET(sp) # for debugging
+ .set at
+# Turn off fpu and enter kernel mode
+ and t0, a0, ~(SR_COP_1_BIT | SR_EXL | SR_KSU_MASK | SR_INT_ENAB)
+ .set noat
+/*
+ * Call the exception handler.
+ */
+ jal trap
+ mtc0 t0, COP_0_STATUS_REG
+/*
+ * Restore user registers and return.
+ * First disable interrupts and set exeption level.
+ */
+ mtc0 zero, COP_0_STATUS_REG # disable int
+ nop
+ nop
+ nop
+ li v0, SR_EXL
+ mtc0 v0, COP_0_STATUS_REG # set exeption level
+
+ lw a0, UADDR+U_PCB_REGS+(SR * 4)
+ lw t0, UADDR+U_PCB_REGS+(MULLO * 4)
+ lw t1, UADDR+U_PCB_REGS+(MULHI * 4)
+ mtc0 a0, COP_0_STATUS_REG # still exeption level
+ mtlo t0
+ mthi t1
+ lw a0, UADDR+U_PCB_REGS+(PC * 4)
+ lw AT, UADDR+U_PCB_REGS+(AST * 4)
+ lw v0, UADDR+U_PCB_REGS+(V0 * 4)
+ dmtc0 a0, COP_0_EXC_PC # set return address
+ lw v1, UADDR+U_PCB_REGS+(V1 * 4)
+ lw a0, UADDR+U_PCB_REGS+(A0 * 4)
+ lw a1, UADDR+U_PCB_REGS+(A1 * 4)
+ lw a2, UADDR+U_PCB_REGS+(A2 * 4)
+ lw a3, UADDR+U_PCB_REGS+(A3 * 4)
+ lw t0, UADDR+U_PCB_REGS+(T0 * 4)
+ lw t1, UADDR+U_PCB_REGS+(T1 * 4)
+ lw t2, UADDR+U_PCB_REGS+(T2 * 4)
+ lw t3, UADDR+U_PCB_REGS+(T3 * 4)
+ lw t4, UADDR+U_PCB_REGS+(T4 * 4)
+ lw t5, UADDR+U_PCB_REGS+(T5 * 4)
+ lw t6, UADDR+U_PCB_REGS+(T6 * 4)
+ lw t7, UADDR+U_PCB_REGS+(T7 * 4)
+ lw s0, UADDR+U_PCB_REGS+(S0 * 4)
+ lw s1, UADDR+U_PCB_REGS+(S1 * 4)
+ lw s2, UADDR+U_PCB_REGS+(S2 * 4)
+ lw s3, UADDR+U_PCB_REGS+(S3 * 4)
+ lw s4, UADDR+U_PCB_REGS+(S4 * 4)
+ lw s5, UADDR+U_PCB_REGS+(S5 * 4)
+ lw s6, UADDR+U_PCB_REGS+(S6 * 4)
+ lw s7, UADDR+U_PCB_REGS+(S7 * 4)
+ lw t8, UADDR+U_PCB_REGS+(T8 * 4)
+ lw t9, UADDR+U_PCB_REGS+(T9 * 4)
+ lw gp, UADDR+U_PCB_REGS+(GP * 4)
+ lw sp, UADDR+U_PCB_REGS+(SP * 4)
+ lw s8, UADDR+U_PCB_REGS+(S8 * 4)
+ lw ra, UADDR+U_PCB_REGS+(RA * 4)
+ eret
+ .set at
+END(MachUserGenException)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachKernIntr --
+ *
+ * Handle an interrupt from kernel mode.
+ * Interrupts use the standard kernel stack.
+ * switch_exit sets up a kernel stack after exit so interrupts won't fail.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+#define KINTR_REG_OFFSET (STAND_FRAME_SIZE)
+#define KINTR_SR_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE)
+#define KINTR_MULT_LO_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 4)
+#define KINTR_MULT_HI_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 8)
+#define KINTR_MULT_GP_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 12)
+#define KINTR_FRAME_SIZE (STAND_FRAME_SIZE + KERN_REG_SIZE + 16)
+
+NNON_LEAF(MachKernIntr, KINTR_FRAME_SIZE, ra)
+ .set noat
+ subu sp, sp, KINTR_FRAME_SIZE # allocate stack frame
+ .mask 0x80000000, (STAND_RA_OFFSET - KINTR_FRAME_SIZE)
+/*
+ * Save the relevant kernel registers onto the stack.
+ * We don't need to save s0 - s8, sp and gp because
+ * the compiler does it for us.
+ */
+ sw AT, KINTR_REG_OFFSET + 0(sp)
+ sw v0, KINTR_REG_OFFSET + 4(sp)
+ sw v1, KINTR_REG_OFFSET + 8(sp)
+ sw a0, KINTR_REG_OFFSET + 12(sp)
+ mflo v0
+ mfhi v1
+ sw a1, KINTR_REG_OFFSET + 16(sp)
+ sw a2, KINTR_REG_OFFSET + 20(sp)
+ sw a3, KINTR_REG_OFFSET + 24(sp)
+ sw t0, KINTR_REG_OFFSET + 28(sp)
+ mfc0 a0, COP_0_STATUS_REG # First arg is the status reg.
+ sw t1, KINTR_REG_OFFSET + 32(sp)
+ sw t2, KINTR_REG_OFFSET + 36(sp)
+ sw t3, KINTR_REG_OFFSET + 40(sp)
+ sw t4, KINTR_REG_OFFSET + 44(sp)
+ mfc0 a1, COP_0_CAUSE_REG # Second arg is the cause reg.
+ sw t5, KINTR_REG_OFFSET + 48(sp)
+ sw t6, KINTR_REG_OFFSET + 52(sp)
+ sw t7, KINTR_REG_OFFSET + 56(sp)
+ sw t8, KINTR_REG_OFFSET + 60(sp)
+ mfc0 a2, COP_0_EXC_PC # Third arg is the pc.
+ sw t9, KINTR_REG_OFFSET + 64(sp)
+ sw ra, KINTR_REG_OFFSET + 68(sp)
+ sw v0, KINTR_MULT_LO_OFFSET(sp)
+ sw v1, KINTR_MULT_HI_OFFSET(sp)
+ sw a0, KINTR_SR_OFFSET(sp)
+
+ mtc0 zero, COP_0_STATUS_REG # Reset exl, trap possible.
+/*
+ * Call the interrupt handler.
+ */
+ jal interrupt
+ sw a2, STAND_RA_OFFSET(sp) # for debugging
+/*
+ * Restore registers and return from the interrupt.
+ */
+ mtc0 zero, COP_0_STATUS_REG # Disable interrupt
+ lw a0, KINTR_SR_OFFSET(sp)
+ lw t0, KINTR_MULT_LO_OFFSET(sp)
+ lw t1, KINTR_MULT_HI_OFFSET(sp)
+ mtc0 a0, COP_0_STATUS_REG # Restore the SR, disable intrs
+ mtlo t0
+ mthi t1
+ lw a0, STAND_RA_OFFSET(sp)
+ lw AT, KINTR_REG_OFFSET + 0(sp)
+ lw v0, KINTR_REG_OFFSET + 4(sp)
+ dmtc0 a0, COP_0_EXC_PC # set return address
+ lw v1, KINTR_REG_OFFSET + 8(sp)
+ lw a0, KINTR_REG_OFFSET + 12(sp)
+ lw a1, KINTR_REG_OFFSET + 16(sp)
+ lw a2, KINTR_REG_OFFSET + 20(sp)
+ lw a3, KINTR_REG_OFFSET + 24(sp)
+ lw t0, KINTR_REG_OFFSET + 28(sp)
+ lw t1, KINTR_REG_OFFSET + 32(sp)
+ lw t2, KINTR_REG_OFFSET + 36(sp)
+ lw t3, KINTR_REG_OFFSET + 40(sp)
+ lw t4, KINTR_REG_OFFSET + 44(sp)
+ lw t5, KINTR_REG_OFFSET + 48(sp)
+ lw t6, KINTR_REG_OFFSET + 52(sp)
+ lw t7, KINTR_REG_OFFSET + 56(sp)
+ lw t8, KINTR_REG_OFFSET + 60(sp)
+ lw t9, KINTR_REG_OFFSET + 64(sp)
+ lw ra, KINTR_REG_OFFSET + 68(sp)
+ addu sp, sp, KINTR_FRAME_SIZE
+ eret # interrupt.
+ .set at
+END(MachKernIntr)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachUserIntr --
+ *
+ * Handle an interrupt from user mode.
+ * Note: we save minimal state in the u.u_pcb struct and use the standard
+ * kernel stack since there has to be a u page if we came from user mode.
+ * If there is a pending software interrupt, then save the remaining state
+ * and call softintr(). This is all because if we call switch() inside
+ * interrupt(), not all the user registers have been saved in u.u_pcb.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NNON_LEAF(MachUserIntr, STAND_FRAME_SIZE, ra)
+ .set noat
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+/*
+ * Save the relevant user registers into the u.u_pcb struct.
+ * We don't need to save s0 - s8 because
+ * the compiler does it for us.
+ */
+ sw AT, UADDR+U_PCB_REGS+(AST * 4)
+ sw v0, UADDR+U_PCB_REGS+(V0 * 4)
+ sw v1, UADDR+U_PCB_REGS+(V1 * 4)
+ sw a0, UADDR+U_PCB_REGS+(A0 * 4)
+ mflo v0
+ mfhi v1
+ sw a1, UADDR+U_PCB_REGS+(A1 * 4)
+ sw a2, UADDR+U_PCB_REGS+(A2 * 4)
+ sw a3, UADDR+U_PCB_REGS+(A3 * 4)
+ sw t0, UADDR+U_PCB_REGS+(T0 * 4)
+ mfc0 a0, COP_0_STATUS_REG # First arg is the status reg.
+ sw t1, UADDR+U_PCB_REGS+(T1 * 4)
+ sw t2, UADDR+U_PCB_REGS+(T2 * 4)
+ sw t3, UADDR+U_PCB_REGS+(T3 * 4)
+ sw t4, UADDR+U_PCB_REGS+(T4 * 4)
+ mfc0 a1, COP_0_CAUSE_REG # Second arg is the cause reg.
+ sw t5, UADDR+U_PCB_REGS+(T5 * 4)
+ sw t6, UADDR+U_PCB_REGS+(T6 * 4)
+ sw t7, UADDR+U_PCB_REGS+(T7 * 4)
+ sw t8, UADDR+U_PCB_REGS+(T8 * 4)
+ mfc0 a2, COP_0_EXC_PC # Third arg is the pc.
+ sw t9, UADDR+U_PCB_REGS+(T9 * 4)
+ sw gp, UADDR+U_PCB_REGS+(GP * 4)
+ sw sp, UADDR+U_PCB_REGS+(SP * 4)
+ sw ra, UADDR+U_PCB_REGS+(RA * 4)
+ li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP
+ sw v0, UADDR+U_PCB_REGS+(MULLO * 4)
+ sw v1, UADDR+U_PCB_REGS+(MULHI * 4)
+ sw a0, UADDR+U_PCB_REGS+(SR * 4)
+ sw a2, UADDR+U_PCB_REGS+(PC * 4)
+ la gp, _gp # switch to kernel GP
+# Turn off fpu and enter kernel mode
+ .set at
+ and t0, a0, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
+ .set noat
+ mtc0 t0, COP_0_STATUS_REG
+/*
+ * Call the interrupt handler.
+ */
+ jal interrupt
+ sw a2, STAND_RA_OFFSET(sp) # for debugging
+/*
+ * Restore registers and return from the interrupt.
+ */
+ mtc0 zero, COP_0_STATUS_REG
+ nop
+ nop
+ nop
+ li v0, SR_EXL
+ mtc0 v0, COP_0_STATUS_REG # set exeption level bit.
+
+ lw a0, UADDR+U_PCB_REGS+(SR * 4)
+ lw v0, astpending # any pending interrupts?
+ mtc0 a0, COP_0_STATUS_REG # Restore the SR, disable intrs
+ bne v0, zero, 1f # dont restore, call softintr
+ lw t0, UADDR+U_PCB_REGS+(MULLO * 4)
+ lw t1, UADDR+U_PCB_REGS+(MULHI * 4)
+ lw a0, UADDR+U_PCB_REGS+(PC * 4)
+ lw AT, UADDR+U_PCB_REGS+(AST * 4)
+ lw v0, UADDR+U_PCB_REGS+(V0 * 4)
+ dmtc0 a0, COP_0_EXC_PC # set return address
+ lw v1, UADDR+U_PCB_REGS+(V1 * 4)
+ lw a0, UADDR+U_PCB_REGS+(A0 * 4)
+ lw a1, UADDR+U_PCB_REGS+(A1 * 4)
+ lw a2, UADDR+U_PCB_REGS+(A2 * 4)
+ lw a3, UADDR+U_PCB_REGS+(A3 * 4)
+ mtlo t0
+ mthi t1
+ lw t0, UADDR+U_PCB_REGS+(T0 * 4)
+ lw t1, UADDR+U_PCB_REGS+(T1 * 4)
+ lw t2, UADDR+U_PCB_REGS+(T2 * 4)
+ lw t3, UADDR+U_PCB_REGS+(T3 * 4)
+ lw t4, UADDR+U_PCB_REGS+(T4 * 4)
+ lw t5, UADDR+U_PCB_REGS+(T5 * 4)
+ lw t6, UADDR+U_PCB_REGS+(T6 * 4)
+ lw t7, UADDR+U_PCB_REGS+(T7 * 4)
+ lw t8, UADDR+U_PCB_REGS+(T8 * 4)
+ lw t9, UADDR+U_PCB_REGS+(T9 * 4)
+ lw gp, UADDR+U_PCB_REGS+(GP * 4)
+ lw sp, UADDR+U_PCB_REGS+(SP * 4)
+ lw ra, UADDR+U_PCB_REGS+(RA * 4)
+ eret # interrupt.
+
+1:
+/*
+ * We have pending software interrupts; save remaining user state in u.u_pcb.
+ */
+ sw s0, UADDR+U_PCB_REGS+(S0 * 4)
+ sw s1, UADDR+U_PCB_REGS+(S1 * 4)
+ sw s2, UADDR+U_PCB_REGS+(S2 * 4)
+ sw s3, UADDR+U_PCB_REGS+(S3 * 4)
+ sw s4, UADDR+U_PCB_REGS+(S4 * 4)
+ sw s5, UADDR+U_PCB_REGS+(S5 * 4)
+ sw s6, UADDR+U_PCB_REGS+(S6 * 4)
+ sw s7, UADDR+U_PCB_REGS+(S7 * 4)
+ sw s8, UADDR+U_PCB_REGS+(S8 * 4)
+ li t0, HARD_INT_MASK | SR_INT_ENAB
+/*
+ * Call the software interrupt handler.
+ */
+ jal softintr
+ mtc0 t0, COP_0_STATUS_REG # enable interrupts (spl0)
+/*
+ * Restore user registers and return. NOTE: interrupts are enabled.
+ */
+ mtc0 zero, COP_0_STATUS_REG
+ nop
+ nop
+ nop
+ li v0, SR_EXL
+ mtc0 v0, COP_0_STATUS_REG # set exeption level bit.
+
+ lw a0, UADDR+U_PCB_REGS+(SR * 4)
+ lw t0, UADDR+U_PCB_REGS+(MULLO * 4)
+ lw t1, UADDR+U_PCB_REGS+(MULHI * 4)
+ mtc0 a0, COP_0_STATUS_REG # this should disable interrupts
+ mtlo t0
+ mthi t1
+ lw a0, UADDR+U_PCB_REGS+(PC * 4)
+ lw AT, UADDR+U_PCB_REGS+(AST * 4)
+ lw v0, UADDR+U_PCB_REGS+(V0 * 4)
+ dmtc0 a0, COP_0_EXC_PC # set return address
+ lw v1, UADDR+U_PCB_REGS+(V1 * 4)
+ lw a0, UADDR+U_PCB_REGS+(A0 * 4)
+ lw a1, UADDR+U_PCB_REGS+(A1 * 4)
+ lw a2, UADDR+U_PCB_REGS+(A2 * 4)
+ lw a3, UADDR+U_PCB_REGS+(A3 * 4)
+ lw t0, UADDR+U_PCB_REGS+(T0 * 4)
+ lw t1, UADDR+U_PCB_REGS+(T1 * 4)
+ lw t2, UADDR+U_PCB_REGS+(T2 * 4)
+ lw t3, UADDR+U_PCB_REGS+(T3 * 4)
+ lw t4, UADDR+U_PCB_REGS+(T4 * 4)
+ lw t5, UADDR+U_PCB_REGS+(T5 * 4)
+ lw t6, UADDR+U_PCB_REGS+(T6 * 4)
+ lw t7, UADDR+U_PCB_REGS+(T7 * 4)
+ lw s0, UADDR+U_PCB_REGS+(S0 * 4)
+ lw s1, UADDR+U_PCB_REGS+(S1 * 4)
+ lw s2, UADDR+U_PCB_REGS+(S2 * 4)
+ lw s3, UADDR+U_PCB_REGS+(S3 * 4)
+ lw s4, UADDR+U_PCB_REGS+(S4 * 4)
+ lw s5, UADDR+U_PCB_REGS+(S5 * 4)
+ lw s6, UADDR+U_PCB_REGS+(S6 * 4)
+ lw s7, UADDR+U_PCB_REGS+(S7 * 4)
+ lw t8, UADDR+U_PCB_REGS+(T8 * 4)
+ lw t9, UADDR+U_PCB_REGS+(T9 * 4)
+ lw gp, UADDR+U_PCB_REGS+(GP * 4)
+ lw sp, UADDR+U_PCB_REGS+(SP * 4)
+ lw s8, UADDR+U_PCB_REGS+(S8 * 4)
+ lw ra, UADDR+U_PCB_REGS+(RA * 4)
+ eret
+ .set at
+END(MachUserIntr)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachTLBMInvalidException --
+ *
+ * Handle a TLB invalid exception from kernel mode in kernel space.
+ * The BaddVAddr, Context, and EntryHi registers contain the failed
+ * virtual address.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NLEAF(MachTLBInvalidException)
+ .set noat
+ dmfc0 k0, COP_0_BAD_VADDR # get the fault address
+ li k1, VM_MIN_KERNEL_ADDRESS # compute index
+ subu k0, k0, k1
+ lw k1, Sysmapsize # index within range?
+ srl k0, k0, PGSHIFT
+ sltu k1, k0, k1
+ beq k1, zero, sys_stk_chk # No. check for valid stack
+ lw k1, Sysmap
+
+ sll k0, k0, 2 # compute offset from index
+ tlbp # Probe the invalid entry
+ addu k1, k1, k0
+ and k0, k0, 4 # check even/odd page
+ bne k0, zero, KernTLBIOdd
+ nop
+
+ mfc0 k0, COP_0_TLB_INDEX
+ nop
+ bltz k0, sys_stk_chk
+ sltiu k0, k0, 8
+
+ bne k0, zero, sys_stk_chk
+ lw k0, 0(k1) # get PTE entry
+
+ dsll k0, k0, 34 # get rid of "wired" bit
+ dsrl k0, k0, 34
+ dmtc0 k0, COP_0_TLB_LO0 # load PTE entry
+ and k0, k0, PG_V # check for valid entry
+ beq k0, zero, MachKernGenException # PTE invalid
+ lw k0, 4(k1) # get odd PTE entry
+ dsll k0, k0, 34
+ dsrl k0, k0, 34
+ dmtc0 k0, COP_0_TLB_LO1 # load PTE entry
+ nop
+ tlbwi # write TLB
+ nop
+ nop
+ nop
+ nop
+ nop
+ eret
+
+KernTLBIOdd:
+ mfc0 k0, COP_0_TLB_INDEX
+ nop
+ bltz k0, sys_stk_chk
+ sltiu k0, k0, 8
+
+ bne k0, zero, sys_stk_chk
+ lw k0, 0(k1) # get PTE entry
+
+ dsll k0, k0, 34 # get rid of wired bit
+ dsrl k0, k0, 34
+ dmtc0 k0, COP_0_TLB_LO1 # save PTE entry
+ and k0, k0, PG_V # check for valid entry
+ beq k0, zero, MachKernGenException # PTE invalid
+ lw k0, -4(k1) # get even PTE entry
+ dsll k0, k0, 34
+ dsrl k0, k0, 34
+ dmtc0 k0, COP_0_TLB_LO0 # save PTE entry
+ nop
+ tlbwi # update TLB
+ nop
+ nop
+ nop
+ nop
+ nop
+ eret
+END(MachTLBInvalidException)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachTLBMissException --
+ *
+ * Handle a TLB miss exception from kernel mode in kernel space.
+ * The BaddVAddr, Context, and EntryHi registers contain the failed
+ * virtual address.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NLEAF(MachTLBMissException)
+ .set noat
+ dmfc0 k0, COP_0_BAD_VADDR # get the fault address
+ li k1, VM_MIN_KERNEL_ADDRESS # compute index
+ subu k0, k0, k1
+ lw k1, Sysmapsize # index within range?
+ srl k0, k0, PGSHIFT
+ sltu k1, k0, k1
+ beq k1, zero, sys_stk_chk # No. check for valid stack
+ lw k1, Sysmap
+ srl k0, k0, 1
+ sll k0, k0, 3 # compute offset from index
+ addu k1, k1, k0
+ lw k0, 0(k1) # get PTE entry
+ lw k1, 4(k1) # get odd PTE entry
+ dsll k0, k0, 34 # get rid of "wired" bit
+ dsrl k0, k0, 34
+ dmtc0 k0, COP_0_TLB_LO0 # load PTE entry
+ dsll k1, k1, 34
+ dsrl k1, k1, 34
+ dmtc0 k1, COP_0_TLB_LO1 # load PTE entry
+ nop
+ tlbwr # write TLB
+ nop
+ nop
+ nop
+ nop
+ nop
+ eret
+
+sys_stk_chk:
+ subu k0, sp, UADDR + 0x200 # check to see if we have a
+ sltiu k0, UPAGES*NBPG - 0x200 # valid kernel stack
+ bne k0, zero, MachKernGenException # Go panic
+ nop
+
+ la a0, start - START_FRAME - 8 # set sp to a valid place
+ sw sp, 24(a0)
+ move sp, a0
+ la a0, 1f
+ mfc0 a2, COP_0_STATUS_REG
+ mfc0 a3, COP_0_CAUSE_REG
+ dmfc0 a1, COP_0_EXC_PC
+ sw a2, 16(sp)
+ sw a3, 20(sp)
+ move a2, ra
+ jal printf
+ dmfc0 a3, COP_0_BAD_VADDR
+ .data
+1:
+ .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n"
+ .text
+
+ la sp, start - START_FRAME # set sp to a valid place
+ PANIC("kernel stack overflow")
+ .set at
+END(MachTLBMissException)
+
+/*
+ * Set/clear software interrupt routines.
+ */
+
+LEAF(setsoftclock)
+ mfc0 v0, COP_0_CAUSE_REG # read cause register
+ nop
+ or v0, v0, SOFT_INT_MASK_0 # set soft clock interrupt
+ mtc0 v0, COP_0_CAUSE_REG # save it
+ j ra
+ nop
+END(setsoftclock)
+
+LEAF(clearsoftclock)
+ mfc0 v0, COP_0_CAUSE_REG # read cause register
+ nop
+ and v0, v0, ~SOFT_INT_MASK_0 # clear soft clock interrupt
+ mtc0 v0, COP_0_CAUSE_REG # save it
+ j ra
+ nop
+END(clearsoftclock)
+
+LEAF(setsoftnet)
+ mfc0 v0, COP_0_CAUSE_REG # read cause register
+ nop
+ or v0, v0, SOFT_INT_MASK_1 # set soft net interrupt
+ mtc0 v0, COP_0_CAUSE_REG # save it
+ j ra
+ nop
+END(setsoftnet)
+
+LEAF(clearsoftnet)
+ mfc0 v0, COP_0_CAUSE_REG # read cause register
+ nop
+ and v0, v0, ~SOFT_INT_MASK_1 # clear soft net interrupt
+ mtc0 v0, COP_0_CAUSE_REG # save it
+ j ra
+ nop
+END(clearsoftnet)
+
+/*
+ * Set/change interrupt priority routines.
+ */
+
+LEAF(MachEnableIntr)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ nop
+ or v0, v0, SR_INT_ENAB
+ mtc0 v0, COP_0_STATUS_REG # enable all interrupts
+ j ra
+ nop
+END(MachEnableIntr)
+
+LEAF(spl0)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ nop
+ or t0, v0, (INT_MASK | SR_INT_ENAB)
+ mtc0 t0, COP_0_STATUS_REG # enable all interrupts
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(spl0)
+
+LEAF(splsoftclock)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ li t0, ~SOFT_INT_MASK_0 # disable soft clock
+ and t0, t0, v0
+ mtc0 t0, COP_0_STATUS_REG # save it
+ nop # 3 ins to disable
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(splsoftclock)
+
+LEAF(splsoftnet)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ li t0, ~(SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+ and t0, t0, v0
+ mtc0 t0, COP_0_STATUS_REG # save it
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(splsoftnet)
+
+LEAF(Mach_spl0)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ li t0, ~(INT_MASK_0|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+ and t0, t0, v0
+ mtc0 t0, COP_0_STATUS_REG # save it
+ nop # 3 ins to disable
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(Mach_spl0)
+
+LEAF(Mach_spl1)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ li t0, ~(INT_MASK_1|SOFT_INT_MASK_0|SOFT_INT_MASK_1)
+ and t0, t0, v0
+ mtc0 t0, COP_0_STATUS_REG # save it
+ nop # 3 ins to disable
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(Mach_spl1)
+
+LEAF(Mach_spl2)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ li t0, ~(INT_MASK_2|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+ and t0, t0, v0
+ mtc0 t0, COP_0_STATUS_REG # save it
+ nop # 3 ins to disable
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(Mach_spl2)
+
+LEAF(Mach_spl3)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ li t0, ~(INT_MASK_3|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+ and t0, t0, v0
+ mtc0 t0, COP_0_STATUS_REG # save it
+ nop # 3 ins to disable
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(Mach_spl3)
+
+LEAF(Mach_spl4)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ li t0, ~(INT_MASK_4|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+ and t0, t0, v0
+ mtc0 t0, COP_0_STATUS_REG # save it
+ nop # 3 ins to disable
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(Mach_spl4)
+
+LEAF(Mach_spl5)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ li t0, ~(INT_MASK_5|SOFT_INT_MASK_1|SOFT_INT_MASK_0)
+ and t0, t0, v0
+ mtc0 t0, COP_0_STATUS_REG # save it
+ nop # 3 ins to disable
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(Mach_spl5)
+
+/*
+ * We define an alternate entry point after mcount is called so it
+ * can be used in mcount without causeing a recursive loop.
+ */
+LEAF(splhigh)
+ALEAF(_splhigh)
+ mfc0 v0, COP_0_STATUS_REG # read status register
+ li t0, ~SR_INT_ENAB # disable all interrupts
+ and t0, t0, v0
+ mtc0 t0, COP_0_STATUS_REG # save it
+ nop # 3 ins to disable
+ j ra
+ and v0, v0, (INT_MASK | SR_INT_ENAB)
+END(splhigh)
+
+/*
+ * Restore saved interrupt mask.
+ */
+LEAF(splx)
+ALEAF(_splx)
+ mfc0 v0, COP_0_STATUS_REG
+ li t0, ~(INT_MASK | SR_INT_ENAB)
+ and t0, t0, v0
+ or t0, t0, a0
+ mtc0 t0, COP_0_STATUS_REG
+ nop # 3 ins to disable
+ j ra
+ nop
+END(splx)
+
+/*----------------------------------------------------------------------------
+ *
+ * wbflush --
+ *
+ * Return when the write buffer is empty.
+ *
+ * wbflush()
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(wbflush)
+ nop
+ sync
+ j ra
+ nop
+END(wbflush)
+
+/*--------------------------------------------------------------------------
+ *
+ * MachTLBWriteIndexed --
+ *
+ * Write the given entry into the TLB at the given index.
+ *
+ * MachTLBWriteIndexed(index, tlb)
+ * unsigned index;
+ * tlb *tlb;
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * TLB entry set.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(MachTLBWriteIndexed)
+ mfc0 v1, COP_0_STATUS_REG # Save the status register.
+ mtc0 zero, COP_0_STATUS_REG # Disable interrupts
+ nop
+ lw a2, 8(a1)
+ lw a3, 12(a1)
+ dmfc0 t0, COP_0_TLB_HI # Save the current PID.
+
+ dmtc0 a2, COP_0_TLB_LO0 # Set up entry low0.
+ dmtc0 a3, COP_0_TLB_LO1 # Set up entry low1.
+ lw a2, 0(a1)
+ lw a3, 4(a1)
+ mtc0 a0, COP_0_TLB_INDEX # Set the index.
+ dmtc0 a2, COP_0_TLB_PG_MASK # Set up entry mask.
+ dmtc0 a3, COP_0_TLB_HI # Set up entry high.
+ nop
+ tlbwi # Write the TLB
+ nop
+ nop
+ nop # Delay for effect
+ nop
+
+ dmtc0 t0, COP_0_TLB_HI # Restore the PID.
+ nop
+ dmtc0 zero, COP_0_TLB_PG_MASK # Default mask value.
+ j ra
+ mtc0 v1, COP_0_STATUS_REG # Restore the status register
+END(MachTLBWriteIndexed)
+
+/*--------------------------------------------------------------------------
+ *
+ * MachSetPID --
+ *
+ * Write the given pid into the TLB pid reg.
+ *
+ * MachSetPID(pid)
+ * int pid;
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * PID set in the entry hi register.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(MachSetPID)
+ dmtc0 a0, COP_0_TLB_HI # Write the hi reg value
+ j ra
+ nop
+END(MachSetPID)
+
+/*--------------------------------------------------------------------------
+ *
+ * MachSetWIRED --
+ *
+ * Write the given value into the TLB wired reg.
+ *
+ * MachSetPID(wired)
+ * int wired;
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * WIRED set in the wired register.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(MachSetWIRED)
+ mtc0 a0, COP_0_TLB_WIRED
+ j ra
+ nop
+END(MachSetWIRED)
+
+/*--------------------------------------------------------------------------
+ *
+ * MachGetWIRED --
+ *
+ * Get the value from the TLB wired reg.
+ *
+ * MachGetWIRED(void)
+ *
+ * Results:
+ * Value of wired reg.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(MachGetWIRED)
+ mfc0 v0, COP_0_TLB_WIRED
+ j ra
+ nop
+END(MachGetWIRED)
+
+/*--------------------------------------------------------------------------
+ *
+ * MachTLBFlush --
+ *
+ * Flush the "random" entries from the TLB.
+ * Uses "wired" register to determine what register to start with.
+ *
+ * MachTLBFlush()
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The TLB is flushed.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(MachTLBFlush)
+ mfc0 v1, COP_0_STATUS_REG # Save the status register.
+ mtc0 zero, COP_0_STATUS_REG # Disable interrupts
+ mfc0 t1, COP_0_TLB_WIRED
+ li t2, VMNUM_TLB_ENTRIES
+ li v0, CACHED_MEMORY_ADDR # invalid address
+ dmfc0 t0, COP_0_TLB_HI # Save the PID
+
+ dmtc0 v0, COP_0_TLB_HI # Mark entry high as invalid
+ dmtc0 zero, COP_0_TLB_LO0 # Zero out low entry0.
+ dmtc0 zero, COP_0_TLB_LO1 # Zero out low entry1.
+ mtc0 zero, COP_0_TLB_PG_MASK # Zero out mask entry.
+/*
+ * Align the starting value (t1) and the upper bound (t2).
+ */
+1:
+ mtc0 t1, COP_0_TLB_INDEX # Set the index register.
+ addu t1, t1, 1 # Increment index.
+ tlbwi # Write the TLB entry.
+ nop
+ nop
+ bne t1, t2, 1b
+ nop
+
+ dmtc0 t0, COP_0_TLB_HI # Restore the PID
+ j ra
+ mtc0 v1, COP_0_STATUS_REG # Restore the status register
+END(MachTLBFlush)
+
+
+/*--------------------------------------------------------------------------
+ *
+ * MachTLBFlushAddr --
+ *
+ * Flush any TLB entries for the given address and TLB PID.
+ *
+ * MachTLBFlushAddr(TLBhi)
+ * unsigned TLBhi;
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The process's page is flushed from the TLB.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(MachTLBFlushAddr)
+ mfc0 v1, COP_0_STATUS_REG # Save the status register.
+ mtc0 zero, COP_0_STATUS_REG # Disable interrupts
+ nop
+ li v0, (PG_HVPN | PG_ASID)
+ and a0, a0, v0 # Make shure valid hi value.
+ dmfc0 t0, COP_0_TLB_HI # Get current PID
+ dmtc0 a0, COP_0_TLB_HI # look for addr & PID
+ nop
+ nop
+ nop
+ tlbp # Probe for the entry.
+ nop
+ nop # Delay for effect
+ nop
+ mfc0 v0, COP_0_TLB_INDEX # See what we got
+ li t1, CACHED_MEMORY_ADDR # Load invalid entry.
+ bltz v0, 1f # index < 0 => !found
+ nop
+ dmtc0 t1, COP_0_TLB_HI # Mark entry high as invalid
+
+ dmtc0 zero, COP_0_TLB_LO0 # Zero out low entry.
+ dmtc0 zero, COP_0_TLB_LO1 # Zero out low entry.
+ nop
+ tlbwi
+ nop
+ nop
+ nop
+ nop
+1:
+ dmtc0 t0, COP_0_TLB_HI # restore PID
+ j ra
+ mtc0 v1, COP_0_STATUS_REG # Restore the status register
+END(MachTLBFlushAddr)
+
+/*--------------------------------------------------------------------------
+ *
+ * MachTLBUpdate --
+ *
+ * Update the TLB if highreg is found; otherwise, enter the data.
+ *
+ * MachTLBUpdate(virpageadr, lowregx)
+ * unsigned virpageadr, lowregx;
+ *
+ * Results:
+ * < 0 if loaded >= 0 if updated.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(MachTLBUpdate)
+ mfc0 v1, COP_0_STATUS_REG # Save the status register.
+ mtc0 zero, COP_0_STATUS_REG # Disable interrupts
+ and t1, a0, 0x1000 # t1 = Even/Odd flag
+ li v0, (PG_HVPN | PG_ASID)
+ and a0, a0, v0
+ dmfc0 t0, COP_0_TLB_HI # Save current PID
+ dmtc0 a0, COP_0_TLB_HI # Init high reg
+ and a2, a1, PG_G # Copy global bit
+ nop
+ nop
+ tlbp # Probe for the entry.
+ dsll a1, a1, 34
+ dsrl a1, a1, 34
+ bne t1, zero, 2f # Decide even odd
+ mfc0 v0, COP_0_TLB_INDEX # See what we got
+# EVEN
+ nop
+ bltz v0, 1f # index < 0 => !found
+ nop
+
+ tlbr # update, read entry first
+ nop
+ nop
+ nop
+ dmtc0 a1, COP_0_TLB_LO0 # init low reg0.
+ nop
+ tlbwi # update slot found
+ b 4f
+ nop
+1:
+ mtc0 zero, COP_0_TLB_PG_MASK # init mask.
+ dmtc0 a0, COP_0_TLB_HI # init high reg.
+ dmtc0 a1, COP_0_TLB_LO0 # init low reg0.
+ dmtc0 a2, COP_0_TLB_LO1 # init low reg1.
+ nop
+ tlbwr # enter into a random slot
+ b 4f
+ nop
+# ODD
+2:
+ nop
+ bltz v0, 3f # index < 0 => !found
+ nop
+
+ tlbr # read the entry first
+ nop
+ nop
+ nop
+ dmtc0 a1, COP_0_TLB_LO1 # init low reg1.
+ nop
+ tlbwi # update slot found
+ b 4f
+ nop
+3:
+ mtc0 zero, COP_0_TLB_PG_MASK # init mask.
+ dmtc0 a0, COP_0_TLB_HI # init high reg.
+ dmtc0 a2, COP_0_TLB_LO0 # init low reg0.
+ dmtc0 a1, COP_0_TLB_LO1 # init low reg1.
+ nop
+ tlbwr # enter into a random slot
+
+4: # Make shure pipeline
+ nop # advances before we
+ nop # uses the tlb.
+ nop
+ nop
+ dmtc0 t0, COP_0_TLB_HI # restore PID
+ j ra
+ mtc0 v1, COP_0_STATUS_REG # Restore the status register
+END(MachTLBUpdate)
+
+/*--------------------------------------------------------------------------
+ *
+ * MachTLBRead --
+ *
+ * Read the TLB entry.
+ *
+ * MachTLBRead(entry, tlb)
+ * unsigned entry;
+ * struct tlb *tlb;
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * tlb will contain the TLB entry found.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(MachTLBRead)
+ mfc0 v1, COP_0_STATUS_REG # Save the status register.
+ mtc0 zero, COP_0_STATUS_REG # Disable interrupts
+ nop
+ nop
+ nop
+ dmfc0 t0, COP_0_TLB_HI # Get current PID
+
+ mtc0 a0, COP_0_TLB_INDEX # Set the index register
+ nop
+ tlbr # Read from the TLB
+ nop
+ nop
+ nop
+ mfc0 t2, COP_0_TLB_PG_MASK # fetch the hi entry
+ dmfc0 t3, COP_0_TLB_HI # fetch the hi entry
+ dmfc0 t4, COP_0_TLB_LO0 # See what we got
+ dmfc0 t5, COP_0_TLB_LO1 # See what we got
+ dmtc0 t0, COP_0_TLB_HI # restore PID
+ nop
+ nop
+ nop # wait for PID active
+ mtc0 v1, COP_0_STATUS_REG # Restore the status register
+ sw t2, 0(a1)
+ sw t3, 4(a1)
+ sw t4, 8(a1)
+ j ra
+ sw t5, 12(a1)
+END(MachTLBRead)
+
+/*--------------------------------------------------------------------------
+ *
+ * MachTLBGetPID --
+ *
+ * MachTLBGetPID()
+ *
+ * Results:
+ * Returns the current TLB pid reg.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------------------
+ */
+LEAF(MachTLBGetPID)
+ dmfc0 v0, COP_0_TLB_HI # get PID
+ j ra
+ and v0, v0, VMTLB_PID # mask off PID
+END(MachTLBGetPID)
+
+
+/*----------------------------------------------------------------------------
+ *
+ * MachSwitchFPState --
+ *
+ * Save the current state into 'from' and restore it from 'to'.
+ *
+ * MachSwitchFPState(from, to)
+ * struct proc *from;
+ * struct user *to;
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(MachSwitchFPState)
+ mfc0 t1, COP_0_STATUS_REG # Save old SR
+ li t0, SR_COP_1_BIT # enable the coprocessor
+ mtc0 t0, COP_0_STATUS_REG
+
+ beq a0, zero, 1f # skip save if NULL pointer
+ nop
+/*
+ * First read out the status register to make sure that all FP operations
+ * have completed.
+ */
+ lw a0, P_ADDR(a0) # get pointer to pcb for proc
+ cfc1 t0, FPC_CSR # stall til FP done
+ cfc1 t0, FPC_CSR # now get status
+ li t3, ~SR_COP_1_BIT
+ lw t2, U_PCB_REGS+(PS * 4)(a0) # get CPU status register
+ sw t0, U_PCB_FPREGS+(32 * 4)(a0) # save FP status
+ and t2, t2, t3 # clear COP_1 enable bit
+ sw t2, U_PCB_REGS+(PS * 4)(a0) # save new status register
+/*
+ * Save the floating point registers.
+ */
+ swc1 $f0, U_PCB_FPREGS+(0 * 4)(a0)
+ swc1 $f1, U_PCB_FPREGS+(1 * 4)(a0)
+ swc1 $f2, U_PCB_FPREGS+(2 * 4)(a0)
+ swc1 $f3, U_PCB_FPREGS+(3 * 4)(a0)
+ swc1 $f4, U_PCB_FPREGS+(4 * 4)(a0)
+ swc1 $f5, U_PCB_FPREGS+(5 * 4)(a0)
+ swc1 $f6, U_PCB_FPREGS+(6 * 4)(a0)
+ swc1 $f7, U_PCB_FPREGS+(7 * 4)(a0)
+ swc1 $f8, U_PCB_FPREGS+(8 * 4)(a0)
+ swc1 $f9, U_PCB_FPREGS+(9 * 4)(a0)
+ swc1 $f10, U_PCB_FPREGS+(10 * 4)(a0)
+ swc1 $f11, U_PCB_FPREGS+(11 * 4)(a0)
+ swc1 $f12, U_PCB_FPREGS+(12 * 4)(a0)
+ swc1 $f13, U_PCB_FPREGS+(13 * 4)(a0)
+ swc1 $f14, U_PCB_FPREGS+(14 * 4)(a0)
+ swc1 $f15, U_PCB_FPREGS+(15 * 4)(a0)
+ swc1 $f16, U_PCB_FPREGS+(16 * 4)(a0)
+ swc1 $f17, U_PCB_FPREGS+(17 * 4)(a0)
+ swc1 $f18, U_PCB_FPREGS+(18 * 4)(a0)
+ swc1 $f19, U_PCB_FPREGS+(19 * 4)(a0)
+ swc1 $f20, U_PCB_FPREGS+(20 * 4)(a0)
+ swc1 $f21, U_PCB_FPREGS+(21 * 4)(a0)
+ swc1 $f22, U_PCB_FPREGS+(22 * 4)(a0)
+ swc1 $f23, U_PCB_FPREGS+(23 * 4)(a0)
+ swc1 $f24, U_PCB_FPREGS+(24 * 4)(a0)
+ swc1 $f25, U_PCB_FPREGS+(25 * 4)(a0)
+ swc1 $f26, U_PCB_FPREGS+(26 * 4)(a0)
+ swc1 $f27, U_PCB_FPREGS+(27 * 4)(a0)
+ swc1 $f28, U_PCB_FPREGS+(28 * 4)(a0)
+ swc1 $f29, U_PCB_FPREGS+(29 * 4)(a0)
+ swc1 $f30, U_PCB_FPREGS+(30 * 4)(a0)
+ swc1 $f31, U_PCB_FPREGS+(31 * 4)(a0)
+
+1:
+/*
+ * Restore the floating point registers.
+ */
+ lw t0, U_PCB_FPREGS+(32 * 4)(a1) # get status register
+ lwc1 $f0, U_PCB_FPREGS+(0 * 4)(a1)
+ lwc1 $f1, U_PCB_FPREGS+(1 * 4)(a1)
+ lwc1 $f2, U_PCB_FPREGS+(2 * 4)(a1)
+ lwc1 $f3, U_PCB_FPREGS+(3 * 4)(a1)
+ lwc1 $f4, U_PCB_FPREGS+(4 * 4)(a1)
+ lwc1 $f5, U_PCB_FPREGS+(5 * 4)(a1)
+ lwc1 $f6, U_PCB_FPREGS+(6 * 4)(a1)
+ lwc1 $f7, U_PCB_FPREGS+(7 * 4)(a1)
+ lwc1 $f8, U_PCB_FPREGS+(8 * 4)(a1)
+ lwc1 $f9, U_PCB_FPREGS+(9 * 4)(a1)
+ lwc1 $f10, U_PCB_FPREGS+(10 * 4)(a1)
+ lwc1 $f11, U_PCB_FPREGS+(11 * 4)(a1)
+ lwc1 $f12, U_PCB_FPREGS+(12 * 4)(a1)
+ lwc1 $f13, U_PCB_FPREGS+(13 * 4)(a1)
+ lwc1 $f14, U_PCB_FPREGS+(14 * 4)(a1)
+ lwc1 $f15, U_PCB_FPREGS+(15 * 4)(a1)
+ lwc1 $f16, U_PCB_FPREGS+(16 * 4)(a1)
+ lwc1 $f17, U_PCB_FPREGS+(17 * 4)(a1)
+ lwc1 $f18, U_PCB_FPREGS+(18 * 4)(a1)
+ lwc1 $f19, U_PCB_FPREGS+(19 * 4)(a1)
+ lwc1 $f20, U_PCB_FPREGS+(20 * 4)(a1)
+ lwc1 $f21, U_PCB_FPREGS+(21 * 4)(a1)
+ lwc1 $f22, U_PCB_FPREGS+(22 * 4)(a1)
+ lwc1 $f23, U_PCB_FPREGS+(23 * 4)(a1)
+ lwc1 $f24, U_PCB_FPREGS+(24 * 4)(a1)
+ lwc1 $f25, U_PCB_FPREGS+(25 * 4)(a1)
+ lwc1 $f26, U_PCB_FPREGS+(26 * 4)(a1)
+ lwc1 $f27, U_PCB_FPREGS+(27 * 4)(a1)
+ lwc1 $f28, U_PCB_FPREGS+(28 * 4)(a1)
+ lwc1 $f29, U_PCB_FPREGS+(29 * 4)(a1)
+ lwc1 $f30, U_PCB_FPREGS+(30 * 4)(a1)
+ lwc1 $f31, U_PCB_FPREGS+(31 * 4)(a1)
+
+ and t0, t0, ~FPC_EXCEPTION_BITS
+ ctc1 t0, FPC_CSR
+ nop
+
+ mtc0 t1, COP_0_STATUS_REG # Restore the status register.
+ j ra
+ nop
+END(MachSwitchFPState)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachSaveCurFPState --
+ *
+ * Save the current floating point coprocessor state.
+ *
+ * MachSaveCurFPState(p)
+ * struct proc *p;
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * machFPCurProcPtr is cleared.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(MachSaveCurFPState)
+ lw a0, P_ADDR(a0) # get pointer to pcb for proc
+ mfc0 t1, COP_0_STATUS_REG # Disable interrupts and
+ li t0, SR_COP_1_BIT # enable the coprocessor
+ mtc0 t0, COP_0_STATUS_REG
+ sw zero, machFPCurProcPtr # indicate state has been saved
+/*
+ * First read out the status register to make sure that all FP operations
+ * have completed.
+ */
+ lw t2, U_PCB_REGS+(PS * 4)(a0) # get CPU status register
+ li t3, ~SR_COP_1_BIT
+ and t2, t2, t3 # clear COP_1 enable bit
+ cfc1 t0, FPC_CSR # stall til FP done
+ cfc1 t0, FPC_CSR # now get status
+ sw t2, U_PCB_REGS+(PS * 4)(a0) # save new status register
+ sw t0, U_PCB_FPREGS+(32 * 4)(a0) # save FP status
+/*
+ * Save the floating point registers.
+ */
+ swc1 $f0, U_PCB_FPREGS+(0 * 4)(a0)
+ swc1 $f1, U_PCB_FPREGS+(1 * 4)(a0)
+ swc1 $f2, U_PCB_FPREGS+(2 * 4)(a0)
+ swc1 $f3, U_PCB_FPREGS+(3 * 4)(a0)
+ swc1 $f4, U_PCB_FPREGS+(4 * 4)(a0)
+ swc1 $f5, U_PCB_FPREGS+(5 * 4)(a0)
+ swc1 $f6, U_PCB_FPREGS+(6 * 4)(a0)
+ swc1 $f7, U_PCB_FPREGS+(7 * 4)(a0)
+ swc1 $f8, U_PCB_FPREGS+(8 * 4)(a0)
+ swc1 $f9, U_PCB_FPREGS+(9 * 4)(a0)
+ swc1 $f10, U_PCB_FPREGS+(10 * 4)(a0)
+ swc1 $f11, U_PCB_FPREGS+(11 * 4)(a0)
+ swc1 $f12, U_PCB_FPREGS+(12 * 4)(a0)
+ swc1 $f13, U_PCB_FPREGS+(13 * 4)(a0)
+ swc1 $f14, U_PCB_FPREGS+(14 * 4)(a0)
+ swc1 $f15, U_PCB_FPREGS+(15 * 4)(a0)
+ swc1 $f16, U_PCB_FPREGS+(16 * 4)(a0)
+ swc1 $f17, U_PCB_FPREGS+(17 * 4)(a0)
+ swc1 $f18, U_PCB_FPREGS+(18 * 4)(a0)
+ swc1 $f19, U_PCB_FPREGS+(19 * 4)(a0)
+ swc1 $f20, U_PCB_FPREGS+(20 * 4)(a0)
+ swc1 $f21, U_PCB_FPREGS+(21 * 4)(a0)
+ swc1 $f22, U_PCB_FPREGS+(22 * 4)(a0)
+ swc1 $f23, U_PCB_FPREGS+(23 * 4)(a0)
+ swc1 $f24, U_PCB_FPREGS+(24 * 4)(a0)
+ swc1 $f25, U_PCB_FPREGS+(25 * 4)(a0)
+ swc1 $f26, U_PCB_FPREGS+(26 * 4)(a0)
+ swc1 $f27, U_PCB_FPREGS+(27 * 4)(a0)
+ swc1 $f28, U_PCB_FPREGS+(28 * 4)(a0)
+ swc1 $f29, U_PCB_FPREGS+(29 * 4)(a0)
+ swc1 $f30, U_PCB_FPREGS+(30 * 4)(a0)
+ swc1 $f31, U_PCB_FPREGS+(31 * 4)(a0)
+
+ mtc0 t1, COP_0_STATUS_REG # Restore the status register.
+ j ra
+ nop
+END(MachSaveCurFPState)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachFPTrap --
+ *
+ * Handle a floating point Trap.
+ *
+ * MachFPTrap(statusReg, causeReg, pc)
+ * unsigned statusReg;
+ * unsigned causeReg;
+ * unsigned pc;
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+NON_LEAF(MachFPTrap, STAND_FRAME_SIZE, ra)
+ subu sp, sp, STAND_FRAME_SIZE
+ mfc0 t0, COP_0_STATUS_REG
+ sw ra, STAND_RA_OFFSET(sp)
+ .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
+
+ or t1, t0, SR_COP_1_BIT
+ mtc0 t1, COP_0_STATUS_REG
+ nop
+ nop
+ nop
+ nop
+ cfc1 t1, FPC_CSR # stall til FP done
+ cfc1 t1, FPC_CSR # now get status
+ nop
+ sll t2, t1, (31 - 17) # unimplemented operation?
+ bgez t2, 3f # no, normal trap
+ nop
+/*
+ * We got an unimplemented operation trap so
+ * fetch the instruction, compute the next PC and emulate the instruction.
+ */
+ bgez a1, 1f # Check the branch delay bit.
+ nop
+/*
+ * The instruction is in the branch delay slot so the branch will have to
+ * be emulated to get the resulting PC.
+ */
+ sw a2, STAND_FRAME_SIZE + 8(sp)
+ li a0, UADDR+U_PCB_REGS # first arg is ptr to CPU registers
+ move a1, a2 # second arg is instruction PC
+ move a2, t1 # third arg is floating point CSR
+ jal MachEmulateBranch # compute PC after branch
+ move a3, zero # fourth arg is FALSE
+/*
+ * Now load the floating-point instruction in the branch delay slot
+ * to be emulated.
+ */
+ lw a2, STAND_FRAME_SIZE + 8(sp) # restore EXC pc
+ b 2f
+ lw a0, 4(a2) # a0 = coproc instruction
+/*
+ * This is not in the branch delay slot so calculate the resulting
+ * PC (epc + 4) into v0 and continue to MachEmulateFP().
+ */
+1:
+ lw a0, 0(a2) # a0 = coproc instruction
+ addu v0, a2, 4 # v0 = next pc
+2:
+ sw v0, UADDR+U_PCB_REGS+(PC * 4) # save new pc
+/*
+ * Check to see if the instruction to be emulated is a floating-point
+ * instruction.
+ */
+ srl a3, a0, OPCODE_SHIFT
+ beq a3, OPCODE_C1, 4f # this should never fail
+ nop
+/*
+ * Send a floating point exception signal to the current process.
+ */
+3:
+ lw a0, curproc # get current process
+ cfc1 a2, FPC_CSR # code = FP execptions
+ ctc1 zero, FPC_CSR # Clear exceptions
+ jal trapsignal
+ li a1, SIGFPE
+ b FPReturn
+ nop
+
+/*
+ * Finally, we can call MachEmulateFP() where a0 is the instruction to emulate.
+ */
+4:
+ jal MachEmulateFP
+ nop
+
+/*
+ * Turn off the floating point coprocessor and return.
+ */
+FPReturn:
+ mfc0 t0, COP_0_STATUS_REG
+ lw ra, STAND_RA_OFFSET(sp)
+ and t0, t0, ~SR_COP_1_BIT
+ mtc0 t0, COP_0_STATUS_REG
+ j ra
+ addu sp, sp, STAND_FRAME_SIZE
+END(MachFPTrap)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachConfigCache --
+ *
+ * Size the caches.
+ * NOTE: should only be called from mach_init().
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The size of the data cache is stored into machPrimaryDataCacheSize.
+ * The size of instruction cache is stored into machPrimaryInstCacheSize.
+ * Alignment mask for cache aliasing test is stored in machCacheAliasMask.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(MachConfigCache)
+ mfc0 v0, COP_0_CONFIG # Get configuration register
+ nop
+ srl t1, v0, 9 # Get I cache size.
+ and t1, 3
+ li t2, 4096
+ sllv t2, t2, t1
+ sw t2, machPrimaryDataCacheSize
+ addiu t2, -1
+ and t2, ~(NBPG - 1)
+ sw t2, machCacheAliasMask
+
+ and t2, v0, 0x20
+ srl t2, t2, 1
+ addu t2, t2, 16
+ sw t2, machPrimaryDataCacheLSize
+
+ srl t1, v0, 6 # Get I cache size.
+ and t1, 3
+ li t2, 4096
+ sllv t2, t2, t1
+ sw t2, machPrimaryInstCacheSize
+
+ and t2, v0, 0x10
+ addu t2, t2, 16
+ sw t2, machPrimaryInstCacheLSize
+ j ra
+ nop
+END(MachConfigCache)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachFlushCache --
+ *
+ * Flush the caches. Assumes a line size of 16 bytes for speed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The contents of the caches is flushed.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(MachFlushCache)
+ lw t1, machPrimaryInstCacheSize
+ lw t2, machPrimaryDataCacheSize
+ # lw t3, machPrimaryInstCacheLSize
+ # lw t4, machPrimaryDataCacheLSize
+/*
+ * Flush the instruction cache.
+ */
+ li t0, CACHED_MEMORY_ADDR
+ addu t1, t0, t1 # End address
+ subu t1, t1, 128
+1:
+ cache 0, 0(t0)
+ cache 0, 16(t0)
+ cache 0, 32(t0)
+ cache 0, 48(t0)
+ cache 0, 64(t0)
+ cache 0, 80(t0)
+ cache 0, 96(t0)
+ cache 0, 112(t0)
+ bne t0, t1, 1b
+ addu t0, t0, 128
+
+/*
+ * Flush the data cache.
+ */
+ li t0, CACHED_MEMORY_ADDR
+ addu t1, t0, t2 # End address
+ subu t1, t1, 128
+1:
+ cache 1, 0(t0)
+ cache 1, 16(t0)
+ cache 1, 32(t0)
+ cache 1, 48(t0)
+ cache 1, 64(t0)
+ cache 1, 80(t0)
+ cache 1, 96(t0)
+ cache 1, 112(t0)
+ bne t0, t1, 1b
+ addu t0, t0, 128
+
+ j ra
+ nop
+END(MachFlushCache)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachFlushICache --
+ *
+ * void MachFlushICache(addr, len)
+ * vm_offset_t addr, len;
+ *
+ * Flush instruction cache for range of addr to addr + len - 1.
+ * The address can be any valid address so long as no TLB misses occur.
+ * Assumes a cache line size of 16 bytes for speed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The contents of the cache is flushed.
+ * Must not touch v0.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(MachFlushICache)
+ addu a1, 127 # Align
+ srl a1, a1, 7 # Number of unrolled loops
+1:
+ cache 0, 0(a0)
+ cache 0, 16(a0)
+ cache 0, 32(a0)
+ cache 0, 48(a0)
+ cache 0, 64(a0)
+ cache 0, 80(a0)
+ cache 0, 96(a0)
+ cache 0, 112(a0)
+ addu a1, -1
+ bne a1, zero, 1b
+ addu a0, 128
+
+ j ra
+ nop
+END(MachFlushICache)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachFlushDCache --
+ *
+ * void MachFlushDCache(addr, len)
+ * vm_offset_t addr, len;
+ *
+ * Flush data cache for index range of addr to addr + len - 1.
+ * The address is reduced to a kseg0 index.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The contents of the cache is written back to primary memory.
+ * The cache line is invalidated.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(MachFlushDCache)
+ lw a2, machPrimaryDataCacheSize
+ addiu a2, -1
+ and a0, a0, a2
+ addu a1, 127 # Align
+ li a2, 0x80000000
+ addu a0, a0, a2
+ addu a1, a1, a0
+ and a0, a0, -128
+ subu a1, a1, a0
+ srl a1, a1, 7 # Compute number of cache lines
+1:
+ cache 1, 0(a0)
+ cache 1, 16(a0)
+ cache 1, 32(a0)
+ cache 1, 48(a0)
+ cache 1, 64(a0)
+ cache 1, 80(a0)
+ cache 1, 96(a0)
+ cache 1, 112(a0)
+ addu a1, -1
+ bne a1, zero, 1b
+ addu a0, 128
+
+ j ra
+ nop
+END(MachFlushDCache)
+
+/*----------------------------------------------------------------------------
+ *
+ * MachHitFlushDCache --
+ *
+ * void MachHitFlushDCache(addr, len)
+ * vm_offset_t addr, len;
+ *
+ * Flush data cache for range of addr to addr + len - 1.
+ * The address can be any valid viritual address as long
+ * as no TLB invalid traps occur. Only lines with matching
+ * addr is flushed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The contents of the cache is written back to primary memory.
+ * The cache line is invalidated.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(MachHitFlushDCache)
+ beq a1, zero, 2f
+ addu a1, 127 # Align
+ addu a1, a1, a0
+ and a0, a0, -128
+ subu a1, a1, a0
+ srl a1, a1, 7 # Compute number of cache lines
+1:
+ cache 0x15, 0(a0)
+ cache 0x15, 16(a0)
+ cache 0x15, 32(a0)
+ cache 0x15, 48(a0)
+ cache 0x15, 64(a0)
+ cache 0x15, 80(a0)
+ cache 0x15, 96(a0)
+ cache 0x15, 112(a0)
+ addu a1, -1
+ bne a1, zero, 1b
+ addu a0, 128
+
+2:
+ j ra
+ nop
+END(MachHitFlushDCache)
+/*----------------------------------------------------------------------------
+ *
+ * MachInvalidateDCache --
+ *
+ * void MachFlushDCache(addr, len)
+ * vm_offset_t addr, len;
+ *
+ * Flush data cache for range of addr to addr + len - 1.
+ * The address can be any valid address as long as no TLB misses occur.
+ * (Be sure to use cached K0SEG kernel addresses or mapped addresses)
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cache line is invalidated.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(MachInvalidateDCache)
+ addu a1, a1, a0 # compute ending address
+1:
+ addu a0, a0, 4
+ bne a0, a1, 1b
+ cache 0x11,-4(a0)
+
+ j ra
+ nop
+END(MachInvalidateDCache)
+
+#ifdef DEBUG
+/*
+ * Read a long and return it.
+ * Note: addresses can be unaligned!
+ *
+ * long
+L* mdbpeek(addr)
+L* caddt_t addr;
+L* {
+L* return (*(long *)addr);
+L* }
+ */
+LEAF(mdbpeek)
+ li v0, MDBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ and v0, a0, 3 # unaligned address?
+ bne v0, zero, 1f
+ nop
+ b 2f
+ lw v0, (a0) # aligned access
+1:
+ lwr v0, 0(a0) # get next 4 bytes (unaligned)
+ lwl v0, 3(a0)
+2:
+ j ra # made it w/o errors
+ sw zero, UADDR+U_PCB_ONFAULT
+mdberr:
+ li v0, 1 # trap sends us here
+ sw v0, mdbmkfault
+ j ra
+ nop
+END(mdbpeek)
+
+/*
+ * Write a long to 'addr'.
+ * Note: addresses can be unaligned!
+ *
+L* void
+L* mdbpoke(addr, value)
+L* caddt_t addr;
+L* long value;
+L* {
+L* *(long *)addr = value;
+L* }
+ */
+LEAF(mdbpoke)
+ li v0, MDBERR
+ sw v0, UADDR+U_PCB_ONFAULT
+ and v0, a0, 3 # unaligned address?
+ bne v0, zero, 1f
+ nop
+ b 2f
+ sw a1, (a0) # aligned access
+1:
+ swr a1, 0(a0) # store next 4 bytes (unaligned)
+ swl a1, 3(a0)
+ and a0, a0, ~3 # align address for cache flush
+2:
+ sw zero, UADDR+U_PCB_ONFAULT
+ b MachFlushICache # flush instruction cache
+ li a1, 8
+END(mdbpoke)
+
+/*
+ * Save registers and state so we can do a 'mdbreset' (like longjmp) later.
+ * Always returns zero.
+ *
+L* int mdb_savearea[11];
+L*
+L* int
+L* mdbsetexit()
+L* {
+L* mdb_savearea[0] = 0;
+L* return (0);
+L* }
+ */
+ .comm mdb_savearea, (11 * 4)
+
+LEAF(mdbsetexit)
+ la a0, mdb_savearea
+ sw s0, 0(a0)
+ sw s1, 4(a0)
+ sw s2, 8(a0)
+ sw s3, 12(a0)
+ sw s4, 16(a0)
+ sw s5, 20(a0)
+ sw s6, 24(a0)
+ sw s7, 28(a0)
+ sw sp, 32(a0)
+ sw s8, 36(a0)
+ sw ra, 40(a0)
+ j ra
+ move v0, zero
+END(mdbsetexit)
+
+/*
+ * Restore registers and state (like longjmp) and return x.
+ *
+L* int
+L* mdbreset(x)
+L* {
+L* return (x);
+L* }
+ */
+LEAF(mdbreset)
+ la v0, mdb_savearea
+ lw ra, 40(v0)
+ lw s0, 0(v0)
+ lw s1, 4(v0)
+ lw s2, 8(v0)
+ lw s3, 12(v0)
+ lw s4, 16(v0)
+ lw s5, 20(v0)
+ lw s6, 24(v0)
+ lw s7, 28(v0)
+ lw sp, 32(v0)
+ lw s8, 36(v0)
+ j ra
+ move v0, a0
+END(mdbreset)
+
+/*
+ * Trap into the debugger.
+ *
+L* void
+L* mdbpanic()
+L* {
+L* }
+ */
+LEAF(mdbpanic)
+ break BREAK_SOVER_VAL
+ j ra
+ nop
+END(mdbpanic)
+#endif /* DEBUG */
+
+#ifdef DEBUG
+LEAF(cpu_getregs)
+ sw sp, 0(a0)
+ sw ra, 4(a0)
+ j ra
+ sw s8, 8(a0)
+END(cpu_getregs)
+#endif /* DEBUG */
+
+/*
+ * Interrupt counters for vmstat.
+ */
+ .data
+ .globl intrcnt
+ .globl eintrcnt
+ .globl intrnames
+ .globl eintrnames
+intrnames:
+ .asciiz "softclock"
+ .asciiz "softnet"
+ .asciiz "local_dma"
+ .asciiz "local_dev"
+ .asciiz "isa_dev"
+ .asciiz "isa_nmi"
+ .asciiz "clock"
+ .asciiz "statclock"
+eintrnames:
+ .align 2
+intrcnt:
+ .word 0,0,0,0,0,0,0,0
+eintrcnt:
diff --git a/sys/arch/arc/arc/machdep.c b/sys/arch/arc/arc/machdep.c
new file mode 100644
index 00000000000..3ad8d5e1f7b
--- /dev/null
+++ b/sys/arch/arc/arc/machdep.c
@@ -0,0 +1,1165 @@
+/* $OpenBSD: machdep.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department, The Mach Operating System project at
+ * Carnegie-Mellon University and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)machdep.c 8.3 (Berkeley) 1/12/94
+ * $Id: machdep.c,v 1.1 1996/06/24 09:07:21 pefo Exp $
+ */
+
+/* from: Utah Hdr: machdep.c 1.63 91/04/24 */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/kernel.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/clist.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/user.h>
+#include <sys/exec.h>
+#include <sys/sysctl.h>
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+#ifdef SYSVSEM
+#include <sys/sem.h>
+#endif
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+
+#include <vm/vm_kern.h>
+
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/pio.h>
+#include <machine/psl.h>
+#include <machine/pte.h>
+#include <machine/autoconf.h>
+
+#include <sys/exec_ecoff.h>
+
+#include <dev/cons.h>
+
+#include <arc/pica/pica.h>
+#include <arc/arc/arctype.h>
+
+#include <asc.h>
+
+#if NASC > 0
+#include <arc/dev/ascreg.h>
+#endif
+
+extern struct consdev *cn_tab;
+
+/* the following is used externally (sysctl_hw) */
+char machine[] = "arc"; /* cpu "architecture" */
+char cpu_model[30];
+
+vm_map_t buffer_map;
+
+/*
+ * Declare these as initialized data so we can patch them.
+ */
+int nswbuf = 0;
+#ifdef NBUF
+int nbuf = NBUF;
+#else
+int nbuf = 0;
+#endif
+#ifdef BUFPAGES
+int bufpages = BUFPAGES;
+#else
+int bufpages = 0;
+#endif
+int msgbufmapped = 0; /* set when safe to use msgbuf */
+int maxmem; /* max memory per process */
+int physmem; /* max supported memory, changes to actual */
+int memcfg; /* memory config register */
+int brdcfg; /* motherboard config register */
+int cpucfg; /* Value of processor config register */
+int cputype; /* Mother board type */
+int ncpu = 1; /* At least one cpu in the system */
+int isa_io_base; /* Base address of ISA io port space */
+int isa_mem_base; /* Base address of ISA memory space */
+
+extern int Mach_spl0(), Mach_spl1(), Mach_spl2(), Mach_spl3();
+extern int Mach_spl4(), Mach_spl5(), splhigh();
+int (*Mach_splnet)() = splhigh;
+int (*Mach_splbio)() = splhigh;
+int (*Mach_splimp)() = splhigh;
+int (*Mach_spltty)() = splhigh;
+int (*Mach_splclock)() = splhigh;
+int (*Mach_splstatclock)() = splhigh;
+
+void vid_print_string(const char *str);
+void vid_putchar(dev_t dev, char c);
+
+
+/*
+ * safepri is a safe priority for sleep to set for a spin-wait
+ * during autoconfiguration or after a panic.
+ */
+int safepri = PSL_LOWIPL;
+
+struct user *proc0paddr;
+struct proc nullproc; /* for use by swtch_exit() */
+
+/*
+ * Do all the stuff that locore normally does before calling main().
+ * Process arguments passed to us by the BIOS.
+ * Reset mapping and set up mapping to hardware and init "wired" reg.
+ * Return the first page address following the system.
+ */
+mips_init(argc, argv, code)
+ int argc;
+ char *argv[];
+ u_int code;
+{
+ register char *cp;
+ register int i;
+ register unsigned firstaddr;
+ register caddr_t v;
+ caddr_t start;
+ struct tlb tlb;
+ extern char edata[], end[];
+ extern char MachTLBMiss[], MachTLBMissEnd[];
+ extern char MachException[], MachExceptionEnd[];
+
+vid_print_string("Starting\n");
+ /* clear the BSS segment in NetBSD code */
+ v = (caddr_t)pica_round_page(end);
+ bzero(edata, v - edata);
+
+ /* check what model platform we are running on */
+ cputype = ACER_PICA_61; /* FIXME find systemtype */
+
+ /*
+ * Get config register now as mapped from BIOS since we are
+ * going to demap these addresses later. We want as may TLB
+ * entries as possible to do something useful :-).
+ */
+
+ switch (cputype) {
+ case ACER_PICA_61: /* ALI PICA 61 */
+ memcfg = in32(PICA_MEMORY_SIZE_REG);
+ brdcfg = in32(PICA_CONFIG_REG);
+ isa_io_base = PICA_V_ISA_IO;
+ isa_mem_base = PICA_V_ISA_MEM;
+ break;
+ default:
+ memcfg = -1;
+ break;
+ }
+
+ /* look at argv[0] and compute bootdev */
+ makebootdev(argv[0]);
+
+ /*
+ * Look at arguments passed to us and compute boothowto.
+ */
+#ifdef GENERIC
+ boothowto = RB_SINGLE | RB_ASKNAME;
+#else
+ boothowto = RB_SINGLE;
+#endif
+#ifdef KADB
+ boothowto |= RB_KDB;
+#endif
+ if (argc > 1) {
+ for (i = 1; i < argc; i++) {
+ if(strncmp("OSLOADOPTIONS=",argv[i],14) == 0) {
+ for (cp = argv[i]+14; *cp; cp++) {
+ switch (*cp) {
+ case 'a': /* autoboot */
+ boothowto &= ~RB_SINGLE;
+ break;
+
+ case 'd': /* use compiled in default root */
+ boothowto |= RB_DFLTROOT;
+ break;
+
+ case 'm': /* mini root present in memory */
+ boothowto |= RB_MINIROOT;
+ break;
+
+ case 'n': /* ask for names */
+ boothowto |= RB_ASKNAME;
+ break;
+
+ case 'N': /* don't ask for names */
+ boothowto &= ~RB_ASKNAME;
+ break;
+ }
+
+ }
+ }
+ }
+ }
+
+#ifdef MFS
+ /*
+ * Check to see if a mini-root was loaded into memory. It resides
+ * at the start of the next page just after the end of BSS.
+ */
+ if (boothowto & RB_MINIROOT) {
+ boothowto |= RB_DFLTROOT;
+ v += mfs_initminiroot(v);
+ }
+#endif
+
+ /*
+ * Now its time to abandon the BIOS and be self supplying.
+ * Start with cleaning out the TLB. Bye bye Microsoft....
+ */
+ MachSetWIRED(0);
+ MachTLBFlush();
+ MachSetWIRED(VMWIRED_ENTRIES);
+
+ /*
+ * Set up mapping for hardware the way we want it!
+ */
+
+ tlb.tlb_mask = PG_SIZE_256K;
+ tlb.tlb_hi = vad_to_vpn(PICA_V_LOCAL_IO_BASE);
+ tlb.tlb_lo0 = vad_to_pfn(PICA_P_LOCAL_IO_BASE) | PG_IOPAGE;
+ tlb.tlb_lo1 = vad_to_pfn(PICA_P_INT_SOURCE) | PG_IOPAGE;
+ MachTLBWriteIndexed(1, &tlb);
+
+ tlb.tlb_mask = PG_SIZE_1M;
+ tlb.tlb_hi = vad_to_vpn(PICA_V_LOCAL_VIDEO_CTRL);
+ tlb.tlb_lo0 = vad_to_pfn(PICA_P_LOCAL_VIDEO_CTRL) | PG_IOPAGE;
+ tlb.tlb_lo1 = vad_to_pfn(PICA_P_LOCAL_VIDEO_CTRL + PICA_S_LOCAL_VIDEO_CTRL/2) | PG_IOPAGE;
+ MachTLBWriteIndexed(2, &tlb);
+
+ tlb.tlb_mask = PG_SIZE_1M;
+ tlb.tlb_hi = vad_to_vpn(PICA_V_EXTND_VIDEO_CTRL);
+ tlb.tlb_lo0 = vad_to_pfn(PICA_P_EXTND_VIDEO_CTRL) | PG_IOPAGE;
+ tlb.tlb_lo1 = vad_to_pfn(PICA_P_EXTND_VIDEO_CTRL + PICA_S_EXTND_VIDEO_CTRL/2) | PG_IOPAGE;
+ MachTLBWriteIndexed(3, &tlb);
+
+ tlb.tlb_mask = PG_SIZE_4M;
+ tlb.tlb_hi = vad_to_vpn(PICA_V_LOCAL_VIDEO);
+ tlb.tlb_lo0 = vad_to_pfn(PICA_P_LOCAL_VIDEO) | PG_IOPAGE;
+ tlb.tlb_lo1 = vad_to_pfn(PICA_P_LOCAL_VIDEO + PICA_S_LOCAL_VIDEO/2) | PG_IOPAGE;
+ MachTLBWriteIndexed(4, &tlb);
+
+ tlb.tlb_mask = PG_SIZE_16M;
+ tlb.tlb_hi = vad_to_vpn(PICA_V_ISA_IO);
+ tlb.tlb_lo0 = vad_to_pfn(PICA_P_ISA_IO) | PG_IOPAGE;
+ tlb.tlb_lo1 = vad_to_pfn(PICA_P_ISA_MEM) | PG_IOPAGE;
+ MachTLBWriteIndexed(5, &tlb);
+
+ /*
+ * Init mapping for u page(s) for proc[0], pm_tlbpid 1.
+ */
+ v = (caddr_t)((int)v+3 & -4);
+ start = v;
+ curproc->p_addr = proc0paddr = (struct user *)v;
+ curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs;
+ firstaddr = CACHED_TO_PHYS(v);
+ for (i = 0; i < UPAGES; i+=2) {
+ tlb.tlb_mask = PG_SIZE_4K;
+ tlb.tlb_hi = vad_to_vpn((UADDR + (i << PGSHIFT))) | 1;
+ tlb.tlb_lo0 = vad_to_pfn(firstaddr) | PG_V | PG_M | PG_CACHED;
+ tlb.tlb_lo1 = vad_to_pfn(firstaddr + NBPG) | PG_V | PG_M | PG_CACHED;
+ curproc->p_md.md_upte[i] = tlb.tlb_lo0;
+ curproc->p_md.md_upte[i+1] = tlb.tlb_lo1;
+ MachTLBWriteIndexed(i,&tlb);
+ firstaddr += NBPG * 2;
+ }
+ v += UPAGES * NBPG;
+ v = (caddr_t)((int)v+3 & -4);
+ MachSetPID(1);
+
+ /*
+ * init nullproc for swtch_exit().
+ * init mapping for u page(s), pm_tlbpid 0
+ * This could be used for an idle process.
+ */
+ nullproc.p_addr = (struct user *)v;
+ nullproc.p_md.md_regs = nullproc.p_addr->u_pcb.pcb_regs;
+ bcopy("nullproc", nullproc.p_comm, sizeof("nullproc"));
+ firstaddr = CACHED_TO_PHYS(v);
+ for (i = 0; i < UPAGES; i+=2) {
+ nullproc.p_md.md_upte[i] = vad_to_pfn(firstaddr) | PG_V | PG_M | PG_CACHED;
+ nullproc.p_md.md_upte[i+1] = vad_to_pfn(firstaddr + NBPG) | PG_V | PG_M | PG_CACHED;
+ firstaddr += NBPG * 2;
+ }
+ v += UPAGES * NBPG;
+
+ /* clear pages for u areas */
+ bzero(start, v - start);
+
+ /*
+ * Copy down exception vector code.
+ */
+ if (MachTLBMissEnd - MachTLBMiss > 0x80)
+ panic("startup: TLB code too large");
+ bcopy(MachTLBMiss, (char *)TLB_MISS_EXC_VEC,
+ MachTLBMissEnd - MachTLBMiss);
+ bcopy(MachException, (char *)GEN_EXC_VEC,
+ MachExceptionEnd - MachException);
+
+ /*
+ * Clear out the I and D caches.
+ */
+ cpucfg = MachConfigCache();
+ MachFlushCache();
+
+ /* check what model platform we are running on */
+ switch (cputype) {
+ case ACER_PICA_61: /* ALI PICA 61 */
+ /*
+ * Set up interrupt handling and I/O addresses.
+ */
+#if 0 /* XXX FIXME */
+ Mach_splnet = Mach_spl1;
+ Mach_splbio = Mach_spl0;
+ Mach_splimp = Mach_spl1;
+ Mach_spltty = Mach_spl2;
+ Mach_splstatclock = Mach_spl3;
+#endif
+ strcpy(cpu_model, "PICA_61");
+ break;
+
+ default:
+ printf("kernel not configured for systype 0x%x\n", i);
+ boot(RB_HALT | RB_NOSYNC);
+ }
+
+ /*
+ * Find out how much memory is available.
+ */
+
+ switch (cputype) {
+ case ACER_PICA_61: /* ALI PICA 61 */
+ /*
+ * Size is determined from the memory config register.
+ * d0-d2 = bank 0 size (sim id)
+ * d3-d5 = bank 1 size
+ * d6 = bus width. (doubels memory size)
+ */
+ if((memcfg & 7) <= 5)
+ physmem = 2097152 << (memcfg & 7);
+ if(((memcfg >> 3) & 7) <= 5)
+ physmem += 2097152 << ((memcfg >> 3) & 7);
+
+ if((memcfg & 0x40) == 0)
+ physmem += physmem; /* 128 bit config */
+
+ physmem = btoc(physmem);
+ break;
+
+ default:
+ physmem = btoc((u_int)v - KERNBASE);
+ cp = (char *)PHYS_TO_UNCACHED(physmem << PGSHIFT);
+ while (cp < (char *)MAX_MEM_ADDR) {
+ if (badaddr(cp, 4))
+ break;
+ i = *(int *)cp;
+ *(int *)cp = 0xa5a5a5a5;
+ /*
+ * Data will persist on the bus if we read it right away
+ * Have to be tricky here.
+ */
+ ((int *)cp)[4] = 0x5a5a5a5a;
+ wbflush();
+ if (*(int *)cp != 0xa5a5a5a5)
+ break;
+ *(int *)cp = i;
+ cp += NBPG;
+ physmem++;
+ }
+ break;
+ }
+
+ maxmem = physmem;
+
+ /*
+ * Initialize error message buffer (at end of core).
+ */
+ maxmem -= btoc(sizeof (struct msgbuf));
+ msgbufp = (struct msgbuf *)(PHYS_TO_CACHED(maxmem << PGSHIFT));
+ msgbufmapped = 1;
+
+ /*
+ * Allocate space for system data structures.
+ * The first available kernel virtual address is in "v".
+ * As pages of kernel virtual memory are allocated, "v" is incremented.
+ *
+ * These data structures are allocated here instead of cpu_startup()
+ * because physical memory is directly addressable. We don't have
+ * to map these into virtual address space.
+ */
+ start = v;
+
+#define valloc(name, type, num) \
+ (name) = (type *)v; v = (caddr_t)((name)+(num))
+#define valloclim(name, type, num, lim) \
+ (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
+#ifdef REAL_CLISTS
+ valloc(cfree, struct cblock, nclist);
+#endif
+ valloc(callout, struct callout, ncallout);
+ valloc(swapmap, struct map, nswapmap = maxproc * 2);
+#ifdef SYSVSHM
+ valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
+#endif
+#ifdef SYSVSEM
+ valloc(sema, struct semid_ds, seminfo.semmni);
+ valloc(sem, struct sem, seminfo.semmns);
+ /* This is pretty disgusting! */
+ valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
+#endif
+#ifdef SYSVMSG
+ valloc(msgpool, char, msginfo.msgmax);
+ valloc(msgmaps, struct msgmap, msginfo.msgseg);
+ valloc(msghdrs, struct msg, msginfo.msgtql);
+ valloc(msqids, struct msqid_ds, msginfo.msgmni);
+#endif
+
+ /*
+ * Determine how many buffers to allocate.
+ * We allocate more buffer space than the BSD standard of
+ * using 10% of memory for the first 2 Meg, 5% of remaining.
+ * We just allocate a flat 10%. Ensure a minimum of 16 buffers.
+ * We allocate 1/2 as many swap buffer headers as file i/o buffers.
+ */
+ if (bufpages == 0)
+ bufpages = physmem / 10 / CLSIZE;
+ if (nbuf == 0) {
+ nbuf = bufpages;
+ if (nbuf < 16)
+ nbuf = 16;
+ }
+ if (nswbuf == 0) {
+ nswbuf = (nbuf / 2) &~ 1; /* force even */
+ if (nswbuf > 256)
+ nswbuf = 256; /* sanity */
+ }
+ valloc(swbuf, struct buf, nswbuf);
+ valloc(buf, struct buf, nbuf);
+
+ /*
+ * Clear allocated memory.
+ */
+ bzero(start, v - start);
+
+ /*
+ * Initialize the virtual memory system.
+ */
+ pmap_bootstrap((vm_offset_t)v);
+}
+
+/*
+ * Console initialization: called early on from main,
+ * before vm init or startup. Do enough configuration
+ * to choose and initialize a console.
+ */
+void
+consinit()
+{
+ static int initted;
+
+ if (initted)
+ return;
+ initted = 1;
+ cninit();
+}
+
+/*
+ * cpu_startup: allocate memory for variable-sized tables,
+ * initialize cpu, and do autoconfiguration.
+ */
+void
+cpu_startup()
+{
+ register unsigned i;
+ register caddr_t v;
+ int base, residual;
+ vm_offset_t minaddr, maxaddr;
+ vm_size_t size;
+#ifdef DEBUG
+ extern int pmapdebug;
+ int opmapdebug = pmapdebug;
+
+ pmapdebug = 0; /* Shut up pmap debug during bootstrap */
+#endif
+
+ /*
+ * Good {morning,afternoon,evening,night}.
+ */
+ printf(version);
+ printf("real mem = %d\n", ctob(physmem));
+
+ /*
+ * Allocate virtual address space for file I/O buffers.
+ * Note they are different than the array of headers, 'buf',
+ * and usually occupy more virtual memory than physical.
+ */
+ size = MAXBSIZE * nbuf;
+ buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
+ &maxaddr, size, TRUE);
+ minaddr = (vm_offset_t)buffers;
+ if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
+ &minaddr, size, FALSE) != KERN_SUCCESS)
+ panic("startup: cannot allocate buffers");
+ base = bufpages / nbuf;
+ residual = bufpages % nbuf;
+ for (i = 0; i < nbuf; i++) {
+ vm_size_t curbufsize;
+ vm_offset_t curbuf;
+
+ /*
+ * First <residual> buffers get (base+1) physical pages
+ * allocated for them. The rest get (base) physical pages.
+ *
+ * The rest of each buffer occupies virtual space,
+ * but has no physical memory allocated for it.
+ */
+ curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
+ curbufsize = CLBYTES * (i < residual ? base+1 : base);
+ vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
+ vm_map_simplify(buffer_map, curbuf);
+ }
+ /*
+ * Allocate a submap for exec arguments. This map effectively
+ * limits the number of processes exec'ing at any time.
+ */
+ exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
+ 16 * NCARGS, TRUE);
+ /*
+ * Allocate a submap for physio
+ */
+ phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
+ VM_PHYS_SIZE, TRUE);
+
+ /*
+ * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
+ * we use the more space efficient malloc in place of kmem_alloc.
+ */
+ mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
+ M_MBUF, M_NOWAIT);
+ bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
+ mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
+ VM_MBUF_SIZE, FALSE);
+ /*
+ * Initialize callouts
+ */
+ callfree = callout;
+ for (i = 1; i < ncallout; i++)
+ callout[i-1].c_next = &callout[i];
+ callout[i-1].c_next = NULL;
+
+#ifdef DEBUG
+ pmapdebug = opmapdebug;
+#endif
+ printf("avail mem = %d\n", ptoa(cnt.v_free_count));
+ printf("using %d buffers containing %d bytes of memory\n",
+ nbuf, bufpages * CLBYTES);
+ /*
+ * Set up CPU-specific registers, cache, etc.
+ */
+ initcpu();
+
+ /*
+ * Set up buffers, so they can be used to read disk labels.
+ */
+ bufinit();
+
+ /*
+ * Configure the system.
+ */
+ configure();
+}
+
+/*
+ * machine dependent system variables.
+ */
+cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+ int *name;
+ u_int namelen;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+ struct proc *p;
+{
+ dev_t consdev;
+
+ /* all sysctl names at this level are terminal */
+ if (namelen != 1)
+ return (ENOTDIR); /* overloaded */
+
+ switch (name[0]) {
+ case CPU_CONSDEV:
+ if (cn_tab != NULL)
+ consdev = cn_tab->cn_dev;
+ else
+ consdev = NODEV;
+ return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
+ sizeof consdev));
+ default:
+ return (EOPNOTSUPP);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Set registers on exec.
+ * Clear all registers except sp, pc.
+ */
+void
+setregs(p, pack, stack, retval)
+ register struct proc *p;
+ struct exec_package *pack;
+ u_long stack;
+ register_t *retval;
+{
+ extern struct proc *machFPCurProcPtr;
+
+ bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int));
+ p->p_md.md_regs[SP] = stack;
+ p->p_md.md_regs[PC] = pack->ep_entry & ~3;
+ p->p_md.md_regs[T9] = pack->ep_entry & ~3; /* abicall req */
+ p->p_md.md_regs[PS] = PSL_USERSET;
+ p->p_md.md_flags & ~MDP_FPUSED;
+ if (machFPCurProcPtr == p)
+ machFPCurProcPtr = (struct proc *)0;
+ p->p_md.md_ss_addr = 0;
+}
+
+/*
+ * WARNING: code in locore.s assumes the layout shown for sf_signum
+ * thru sf_handler so... don't screw with them!
+ */
+struct sigframe {
+ int sf_signum; /* signo for handler */
+ int sf_code; /* additional info for handler */
+ struct sigcontext *sf_scp; /* context ptr for handler */
+ sig_t sf_handler; /* handler addr for u_sigc */
+ struct sigcontext sf_sc; /* actual context */
+};
+
+#ifdef DEBUG
+int sigdebug = 0;
+int sigpid = 0;
+#define SDB_FOLLOW 0x01
+#define SDB_KSTACK 0x02
+#define SDB_FPSTATE 0x04
+#endif
+
+/*
+ * Send an interrupt to process.
+ */
+void
+sendsig(catcher, sig, mask, code)
+ sig_t catcher;
+ int sig, mask;
+ u_long code;
+{
+ register struct proc *p = curproc;
+ register struct sigframe *fp;
+ register int *regs;
+ register struct sigacts *psp = p->p_sigacts;
+ int oonstack, fsize;
+ struct sigcontext ksc;
+ extern char sigcode[], esigcode[];
+
+ regs = p->p_md.md_regs;
+ oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+ /*
+ * Allocate and validate space for the signal handler
+ * context. Note that if the stack is in data space, the
+ * call to grow() is a nop, and the copyout()
+ * will fail if the process has not already allocated
+ * the space with a `brk'.
+ */
+ fsize = sizeof(struct sigframe);
+ if ((psp->ps_flags & SAS_ALTSTACK) &&
+ (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
+ (psp->ps_sigonstack & sigmask(sig))) {
+ fp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
+ psp->ps_sigstk.ss_size - fsize);
+ psp->ps_sigstk.ss_flags |= SA_ONSTACK;
+ } else
+ fp = (struct sigframe *)(regs[SP] - fsize);
+ if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
+ (void)grow(p, (unsigned)fp);
+#ifdef DEBUG
+ if ((sigdebug & SDB_FOLLOW) ||
+ (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
+ p->p_pid, sig, &oonstack, fp, &fp->sf_sc);
+#endif
+ /*
+ * Build the signal context to be used by sigreturn.
+ */
+ ksc.sc_onstack = oonstack;
+ ksc.sc_mask = mask;
+ ksc.sc_pc = regs[PC];
+ ksc.mullo = regs[MULLO];
+ ksc.mulhi = regs[MULHI];
+ ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */
+ bcopy((caddr_t)&regs[1], (caddr_t)&ksc.sc_regs[1],
+ sizeof(ksc.sc_regs) - sizeof(int));
+ ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
+ if (ksc.sc_fpused) {
+ extern struct proc *machFPCurProcPtr;
+
+ /* if FPU has current state, save it first */
+ if (p == machFPCurProcPtr)
+ MachSaveCurFPState(p);
+ bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs,
+ sizeof(ksc.sc_fpregs));
+ }
+ if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) {
+ /*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+ SIGACTION(p, SIGILL) = SIG_DFL;
+ sig = sigmask(SIGILL);
+ p->p_sigignore &= ~sig;
+ p->p_sigcatch &= ~sig;
+ p->p_sigmask &= ~sig;
+ psignal(p, SIGILL);
+ return;
+ }
+ /*
+ * Build the argument list for the signal handler.
+ */
+ regs[A0] = sig;
+ regs[A1] = code;
+ regs[A2] = (int)&fp->sf_sc;
+ regs[A3] = (int)catcher;
+
+ regs[PC] = (int)catcher;
+ regs[T9] = (int)catcher;
+ regs[SP] = (int)fp;
+ /*
+ * Signal trampoline code is at base of user stack.
+ */
+ regs[RA] = (int)PS_STRINGS - (esigcode - sigcode);
+#ifdef DEBUG
+ if ((sigdebug & SDB_FOLLOW) ||
+ (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): sig %d returns\n",
+ p->p_pid, sig);
+#endif
+}
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken. Reset signal mask and
+ * stack state from context left by sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * psl to gain improper priviledges or to cause
+ * a machine fault.
+ */
+/* ARGSUSED */
+sys_sigreturn(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_sigreturn_args /* {
+ syscallarg(struct sigcontext *) sigcntxp;
+ } */ *uap = v;
+ register struct sigcontext *scp;
+ register int *regs;
+ struct sigcontext ksc;
+ int error;
+
+ scp = SCARG(uap, sigcntxp);
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
+#endif
+ regs = p->p_md.md_regs;
+ /*
+ * Test and fetch the context structure.
+ * We grab it all at once for speed.
+ */
+ error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
+ if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) {
+#ifdef DEBUG
+ if (!(sigdebug & SDB_FOLLOW))
+ printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
+ printf(" old sp %x ra %x pc %x\n",
+ regs[SP], regs[RA], regs[PC]);
+ printf(" new sp %x ra %x pc %x err %d z %x\n",
+ ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC],
+ error, ksc.sc_regs[ZERO]);
+#endif
+ return (EINVAL);
+ }
+ scp = &ksc;
+ /*
+ * Restore the user supplied information
+ */
+ if (scp->sc_onstack & 01)
+ p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+ p->p_sigmask = scp->sc_mask &~ sigcantmask;
+ regs[PC] = scp->sc_pc;
+ regs[MULLO] = scp->mullo;
+ regs[MULHI] = scp->mulhi;
+ bcopy((caddr_t)&scp->sc_regs[1], (caddr_t)&regs[1],
+ sizeof(scp->sc_regs) - sizeof(int));
+ if (scp->sc_fpused)
+ bcopy((caddr_t)scp->sc_fpregs, (caddr_t)&p->p_md.md_regs[F0],
+ sizeof(scp->sc_fpregs));
+ return (EJUSTRETURN);
+}
+
+int waittime = -1;
+
+void
+boot(howto)
+ register int howto;
+{
+
+ /* take a snap shot before clobbering any registers */
+ if (curproc)
+ savectx(curproc->p_addr, 0);
+
+#ifdef DEBUG
+ if (panicstr)
+ stacktrace();
+#endif
+
+ boothowto = howto;
+ if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
+ extern struct proc proc0;
+ /* fill curproc with live object */
+ if (curproc == NULL)
+ curproc = &proc0;
+ /*
+ * Synchronize the disks....
+ */
+ waittime = 0;
+ vfs_shutdown();
+
+ /*
+ * If we've been adjusting the clock, the todr
+ * will be out of synch; adjust it now.
+ */
+ resettodr();
+ }
+ (void) splhigh(); /* extreme priority */
+ if (howto & RB_HALT)
+ printf("System halted.\n");
+ else {
+ if (howto & RB_DUMP)
+ dumpsys();
+ printf("System restart.\n");
+ }
+ while(1); /* Forever */
+ /*NOTREACHED*/
+}
+
+int dumpmag = (int)0x8fca0101; /* magic number for savecore */
+int dumpsize = 0; /* also for savecore */
+long dumplo = 0;
+
+dumpconf()
+{
+ int nblks;
+
+ dumpsize = physmem;
+ if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
+ nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
+ if (dumpsize > btoc(dbtob(nblks - dumplo)))
+ dumpsize = btoc(dbtob(nblks - dumplo));
+ else if (dumplo == 0)
+ dumplo = nblks - btodb(ctob(physmem));
+ }
+ /*
+ * Don't dump on the first CLBYTES (why CLBYTES?)
+ * in case the dump device includes a disk label.
+ */
+ if (dumplo < btodb(CLBYTES))
+ dumplo = btodb(CLBYTES);
+}
+
+/*
+ * Doadump comes here after turning off memory management and
+ * getting on the dump stack, either when called above, or by
+ * the auto-restart code.
+ */
+dumpsys()
+{
+ int error;
+
+ msgbufmapped = 0;
+ if (dumpdev == NODEV)
+ return;
+ /*
+ * For dumps during autoconfiguration,
+ * if dump device has already configured...
+ */
+ if (dumpsize == 0)
+ dumpconf();
+ if (dumplo < 0)
+ return;
+ printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
+ printf("dump ");
+ switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
+
+ case ENXIO:
+ printf("device bad\n");
+ break;
+
+ case EFAULT:
+ printf("device not ready\n");
+ break;
+
+ case EINVAL:
+ printf("area improper\n");
+ break;
+
+ case EIO:
+ printf("i/o error\n");
+ break;
+
+ default:
+ printf("error %d\n", error);
+ break;
+
+ case 0:
+ printf("succeeded\n");
+ }
+}
+
+/*
+ * Return the best possible estimate of the time in the timeval
+ * to which tvp points. Unfortunately, we can't read the hardware registers.
+ * We guarantee that the time will be greater than the value obtained by a
+ * previous call.
+ */
+void
+microtime(tvp)
+ register struct timeval *tvp;
+{
+ int s = splclock();
+ static struct timeval lasttime;
+
+ *tvp = time;
+#ifdef notdef
+ tvp->tv_usec += clkread();
+ while (tvp->tv_usec > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+#endif
+ if (tvp->tv_sec == lasttime.tv_sec &&
+ tvp->tv_usec <= lasttime.tv_usec &&
+ (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ lasttime = *tvp;
+ splx(s);
+}
+
+initcpu()
+{
+
+ /*
+ * Disable all interrupts. New masks will be set up
+ * during system configuration
+ */
+ out16(PICA_SYS_LB_IE,0x000);
+ out32(PICA_SYS_EXT_IMASK, 0x00);
+
+ spl0(); /* safe to turn interrupts on now */
+}
+
+/*
+ * Convert an ASCII string into an integer.
+ */
+int
+atoi(s)
+ char *s;
+{
+ int c;
+ unsigned base = 10, d;
+ int neg = 0, val = 0;
+
+ if (s == 0 || (c = *s++) == 0)
+ goto out;
+
+ /* skip spaces if any */
+ while (c == ' ' || c == '\t')
+ c = *s++;
+
+ /* parse sign, allow more than one (compat) */
+ while (c == '-') {
+ neg = !neg;
+ c = *s++;
+ }
+
+ /* parse base specification, if any */
+ if (c == '0') {
+ c = *s++;
+ switch (c) {
+ case 'X':
+ case 'x':
+ base = 16;
+ c = *s++;
+ break;
+ case 'B':
+ case 'b':
+ base = 2;
+ c = *s++;
+ break;
+ default:
+ base = 8;
+ }
+ }
+
+ /* parse number proper */
+ for (;;) {
+ if (c >= '0' && c <= '9')
+ d = c - '0';
+ else if (c >= 'a' && c <= 'z')
+ d = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'Z')
+ d = c - 'A' + 10;
+ else
+ break;
+ val *= base;
+ val += d;
+ c = *s++;
+ }
+ if (neg)
+ val = -val;
+out:
+ return val;
+}
+
+/*
+ * This code is temporary for debugging at startup
+ */
+
+static int vid_xpos=0, vid_ypos=0;
+
+static void
+vid_wrchar(char c)
+{
+ volatile unsigned short *video;
+
+ video = (unsigned short *)(0xe08b8000) + vid_ypos * 80 + vid_xpos;
+ *video = (*video & 0xff00) | 0x0f00 | (unsigned short)c;
+}
+
+static void
+vid_scroll()
+{
+ volatile unsigned short *video;
+ int i;
+
+ video = (unsigned short *)(0xe08b8000);
+ for(i = 0; i < 80 * 24; i++) {
+ *video = *(video + 80);
+ video++;
+ }
+ for(i = 0; i < 80; i++) {
+ *video = *video & 0xff00 | ' ';
+ video++;
+ }
+}
+void
+vid_print_string(const char *str)
+{
+ unsigned char c;
+
+ while(c = *str++) {
+ vid_putchar((dev_t)0, c);
+ }
+}
+
+void
+vid_putchar(dev_t dev, char c)
+{
+ switch(c) {
+ case '\n':
+ vid_xpos = 0;
+ if(vid_ypos == 24)
+ vid_scroll();
+ else
+ vid_ypos++;
+ DELAY(500000);
+ break;
+
+ case '\r':
+ vid_xpos = 0;
+ break;
+
+ case '\t':
+ do {
+ vid_putchar(dev, ' ');
+ } while(vid_xpos & 7);
+ break;
+
+ default:
+ vid_wrchar(c);
+ vid_xpos++;
+ if(vid_xpos == 80) {
+ vid_xpos = 0;
+ vid_putchar(dev, '\n');
+ }
+ }
+}
diff --git a/sys/arch/arc/arc/mainbus.c b/sys/arch/arc/arc/mainbus.c
new file mode 100644
index 00000000000..9c73222cd1e
--- /dev/null
+++ b/sys/arch/arc/arc/mainbus.c
@@ -0,0 +1,173 @@
+/* $OpenBSD: mainbus.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/* $NetBSD: mainbus.c,v 1.3 1995/06/28 02:45:10 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/reboot.h>
+
+#include <arc/arc/arctype.h>
+#include <machine/autoconf.h>
+
+struct mainbus_softc {
+ struct device sc_dv;
+ struct abus sc_bus;
+};
+
+/* Definition of the mainbus driver. */
+static int mbmatch __P((struct device *, void *, void *));
+static void mbattach __P((struct device *, struct device *, void *));
+static int mbprint __P((void *, char *));
+
+struct cfattach mainbus_ca = {
+ sizeof(struct device), mbmatch, mbattach
+};
+struct cfdriver mainbus_cd = {
+ NULL, "mainbus", DV_DULL, NULL, 0
+};
+
+void mb_intr_establish __P((struct confargs *, int (*)(void *), void *));
+void mb_intr_disestablish __P((struct confargs *));
+caddr_t mb_cvtaddr __P((struct confargs *));
+int mb_matchname __P((struct confargs *, char *));
+
+static int
+mbmatch(parent, cfdata, aux)
+ struct device *parent;
+ void *cfdata;
+ void *aux;
+{
+ struct cfdata *cf = cfdata;
+
+ /*
+ * Only one mainbus, but some people are stupid...
+ */
+ if (cf->cf_unit > 0)
+ return(0);
+
+ /*
+ * That one mainbus is always here.
+ */
+ return(1);
+}
+
+static void
+mbattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct mainbus_softc *sc = (struct mainbus_softc *)self;
+ struct confargs nca;
+ extern int cputype, ncpus;
+
+ printf("\n");
+
+ sc->sc_bus.ab_dv = (struct device *)sc;
+ sc->sc_bus.ab_type = BUS_MAIN;
+ sc->sc_bus.ab_intr_establish = mb_intr_establish;
+ sc->sc_bus.ab_intr_disestablish = mb_intr_disestablish;
+ sc->sc_bus.ab_cvtaddr = mb_cvtaddr;
+ sc->sc_bus.ab_matchname = mb_matchname;
+
+ /*
+ * Try to find and attach all of the CPUs in the machine.
+ * ( Right now only one CPU so code is simple )
+ */
+
+ nca.ca_name = "cpu";
+ nca.ca_slot = 0;
+ nca.ca_offset = 0;
+ nca.ca_bus = &sc->sc_bus;
+ config_found(self, &nca, mbprint);
+
+ if (cputype == ACER_PICA_61) {
+ /* we have a PICA bus! */
+ nca.ca_name = "pica";
+ nca.ca_slot = 0;
+ nca.ca_offset = 0;
+ nca.ca_bus = &sc->sc_bus;
+ config_found(self, &nca, mbprint);
+ }
+ if (cputype == ACER_PICA_61) {
+ /* we have an ISA bus! */
+ nca.ca_name = "isabr";
+ nca.ca_slot = 0;
+ nca.ca_offset = 0;
+ nca.ca_bus = &sc->sc_bus;
+ config_found(self, &nca, mbprint);
+ }
+}
+
+static int
+mbprint(aux, pnp)
+ void *aux;
+ char *pnp;
+{
+
+ if (pnp)
+ return (QUIET);
+ return (UNCONF);
+}
+
+void
+mb_intr_establish(ca, handler, val)
+ struct confargs *ca;
+ int (*handler) __P((void *));
+ void *val;
+{
+
+ panic("can never mb_intr_establish");
+}
+
+void
+mb_intr_disestablish(ca)
+ struct confargs *ca;
+{
+
+ panic("can never mb_intr_disestablish");
+}
+
+caddr_t
+mb_cvtaddr(ca)
+ struct confargs *ca;
+{
+
+ return (NULL);
+}
+
+int
+mb_matchname(ca, name)
+ struct confargs *ca;
+ char *name;
+{
+
+ return (strcmp(name, ca->ca_name) == 0);
+}
diff --git a/sys/arch/arc/arc/mem.c b/sys/arch/arc/arc/mem.c
new file mode 100644
index 00000000000..061291fa8bc
--- /dev/null
+++ b/sys/arch/arc/arc/mem.c
@@ -0,0 +1,173 @@
+/* $OpenBSD: mem.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/* $NetBSD: mem.c,v 1.6 1995/04/10 11:55:03 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)mem.c 8.3 (Berkeley) 1/12/94
+ */
+
+/*
+ * Memory special file
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/msgbuf.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+
+extern vm_offset_t avail_end;
+caddr_t zeropage;
+
+/*ARGSUSED*/
+int
+mmopen(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmclose(dev, flag, mode)
+ dev_t dev;
+ int flag, mode;
+{
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmrw(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ register vm_offset_t o, v;
+ register int c;
+ register struct iovec *iov;
+ int error = 0;
+
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("mmrw");
+ continue;
+ }
+ switch (minor(dev)) {
+
+/* minor device 0 is physical memory */
+ case 0:
+ v = uio->uio_offset;
+ c = iov->iov_len;
+ if (v + c > ctob(physmem))
+ return (EFAULT);
+ v += CACHED_MEMORY_ADDR;
+ error = uiomove((caddr_t)v, c, uio);
+ continue;
+
+/* minor device 1 is kernel memory */
+ case 1:
+ v = uio->uio_offset;
+ c = min(iov->iov_len, MAXPHYS);
+ if (v < CACHED_MEMORY_ADDR)
+ return (EFAULT);
+ if (v + c > PHYS_TO_CACHED(avail_end +
+ sizeof (struct msgbuf)) &&
+ (v < KSEG2_ADDR ||
+ !kernacc((caddr_t)v, c,
+ uio->uio_rw == UIO_READ ? B_READ : B_WRITE)))
+ return (EFAULT);
+
+ error = uiomove((caddr_t)v, c, uio);
+ continue;
+
+/* minor device 2 is EOF/RATHOLE */
+ case 2:
+ if (uio->uio_rw == UIO_WRITE)
+ uio->uio_resid = 0;
+ return (0);
+
+/* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
+ case 12:
+ if (uio->uio_rw == UIO_WRITE) {
+ c = iov->iov_len;
+ break;
+ }
+ if (zeropage == NULL) {
+ zeropage = (caddr_t)
+ malloc(CLBYTES, M_TEMP, M_WAITOK);
+ bzero(zeropage, CLBYTES);
+ }
+ c = min(iov->iov_len, CLBYTES);
+ error = uiomove(zeropage, c, uio);
+ continue;
+
+ default:
+ return (ENXIO);
+ }
+ if (error)
+ break;
+ iov->iov_base += c;
+ iov->iov_len -= c;
+ uio->uio_offset += c;
+ uio->uio_resid -= c;
+ }
+ return (error);
+}
+
+int
+mmmmap(dev, off, prot)
+ dev_t dev;
+ int off, prot;
+{
+
+ return (EOPNOTSUPP);
+}
diff --git a/sys/arch/arc/arc/minidebug.c b/sys/arch/arc/arc/minidebug.c
new file mode 100644
index 00000000000..dae2760638b
--- /dev/null
+++ b/sys/arch/arc/arc/minidebug.c
@@ -0,0 +1,1111 @@
+/* $OpenBSD: minidebug.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
+ * $Id: minidebug.c,v 1.1 1996/06/24 09:07:21 pefo Exp $
+ */
+
+/*
+ * Define machine dependent primitives for mdb.
+ */
+
+#include <sys/types.h>
+#include <machine/pte.h>
+#include <vm/vm_prot.h>
+#undef SP
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/pcb.h>
+#include <machine/trap.h>
+#include <machine/mips_opcode.h>
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+void arc_dump_tlb(int, int);
+
+static char *op_name[64] = {
+/* 0 */ "spec", "bcond","j", "jal", "beq", "bne", "blez", "bgtz",
+/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
+/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
+/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37",
+/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu",
+/*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache",
+/*48 */ "ll", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld",
+/*56 */ "sc", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd"
+};
+
+static char *spec_name[64] = {
+/* 0 */ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav",
+/* 8 */ "jr", "jalr", "spec12","spec13","syscall","break","spec16","sync",
+/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
+/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu",
+/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
+/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
+/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
+/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
+};
+
+static char *bcond_name[32] = {
+/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
+/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
+/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
+/*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
+};
+
+static char *cop1_name[64] = {
+/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
+/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
+/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
+/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
+/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
+/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
+/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
+ "fcmp.ole","fcmp.ule",
+/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
+ "fcmp.le","fcmp.ngt"
+};
+
+static char *fmt_name[16] = {
+ "s", "d", "e", "fmt3",
+ "w", "fmt5", "fmt6", "fmt7",
+ "fmt8", "fmt9", "fmta", "fmtb",
+ "fmtc", "fmtd", "fmte", "fmtf"
+};
+
+static char *reg_name[32] = {
+ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
+};
+
+static char *c0_opname[64] = {
+ "c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
+ "tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
+ "rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
+ "eret","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
+ "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
+ "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
+ "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
+ "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
+};
+
+static char *c0_reg[32] = {
+ "index","random","tlblo0","tlblo1","context","tlbmask","wired","c0r7",
+ "badvaddr","count","tlbhi","c0r11","sr","cause","epc", "prid",
+ "config","lladr","watchlo","watchhi","xcontext","c0r21","c0r22","c0r23",
+ "c0r24","c0r25","ecc","cacheerr","taglo","taghi","errepc","c0r31"
+};
+
+extern char *trap_type[];
+
+struct pcb mdbpcb;
+int mdbmkfault;
+
+#define MAXBRK 10
+struct brk {
+ int inst;
+ int addr;
+} brk_tab[MAXBRK];
+
+/*
+ * Mini debugger for kernel.
+ */
+int gethex(u_int *val, u_int dotval)
+{
+ u_int c;
+
+ *val = 0;
+ while((c = cngetc()) != '\e' && c != '\n') {
+ if(c >= '0' && c <= '9') {
+ *val = (*val << 4) + c - '0';
+ cnputc(c);
+ }
+ else if(c >= 'a' && c <= 'f') {
+ *val = (*val << 4) + c - 'a' + 10;
+ cnputc(c);
+ }
+ else if(c == '\b') {
+ *val = *val >> 4;
+ printf("\b \b");
+ }
+ else if(c == ',') {
+ cnputc(c);
+ return(c);
+ }
+ else if(c == '.') {
+ *val = dotval;;
+ cnputc(c);
+ }
+ }
+ return(c);
+}
+
+void dump(u_int *addr, u_int size)
+{
+ int cnt;
+
+ cnt = 0;
+
+ size = (size + 3) / 4;
+ while(size--) {
+ if((cnt++ & 3) == 0)
+ printf("\n%08x: ",(int)addr);
+ printf("%08x ",*addr++);
+ }
+}
+
+void print_regs()
+{
+ printf("\n");
+ printf("T0-7 %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ mdbpcb.pcb_regs[T0],mdbpcb.pcb_regs[T1],
+ mdbpcb.pcb_regs[T2],mdbpcb.pcb_regs[T3],
+ mdbpcb.pcb_regs[T4],mdbpcb.pcb_regs[T5],
+ mdbpcb.pcb_regs[T6],mdbpcb.pcb_regs[T7]);
+ printf("T8-9 %08x %08x A0-4 %08x %08x %08x %08x\n",
+ mdbpcb.pcb_regs[T8],mdbpcb.pcb_regs[T9],
+ mdbpcb.pcb_regs[A0],mdbpcb.pcb_regs[A1],
+ mdbpcb.pcb_regs[A2],mdbpcb.pcb_regs[A3]);
+ printf("S0-7 %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ mdbpcb.pcb_regs[S0],mdbpcb.pcb_regs[S1],
+ mdbpcb.pcb_regs[S2],mdbpcb.pcb_regs[S3],
+ mdbpcb.pcb_regs[S4],mdbpcb.pcb_regs[S5],
+ mdbpcb.pcb_regs[S6],mdbpcb.pcb_regs[S7]);
+ printf(" S8 %08x V0-1 %08x %08x GP %08x SP %08x\n",
+ mdbpcb.pcb_regs[S8],mdbpcb.pcb_regs[V0],
+ mdbpcb.pcb_regs[V1],mdbpcb.pcb_regs[GP],
+ mdbpcb.pcb_regs[SP]);
+ printf(" AT %08x PC %08x RA %08x SR %08x",
+ mdbpcb.pcb_regs[AST],mdbpcb.pcb_regs[PC],
+ mdbpcb.pcb_regs[RA],mdbpcb.pcb_regs[SR]);
+}
+
+set_break(va)
+{
+ int i;
+
+ va = va & ~3;
+ for(i = 0; i < MAXBRK; i++) {
+ if(brk_tab[i].addr == 0) {
+ brk_tab[i].addr = va;
+ brk_tab[i].inst = *(u_int *)va;
+ return;
+ }
+ }
+ printf(" Break table full!!");
+}
+
+del_break(va)
+{
+ int i;
+
+ va = va & ~3;
+ for(i = 0; i < MAXBRK; i++) {
+ if(brk_tab[i].addr == va) {
+ brk_tab[i].addr = 0;
+ return;
+ }
+ }
+ printf(" Break to remove not found!!");
+}
+
+break_insert()
+{
+ int i;
+
+ for(i = 0; i < MAXBRK; i++) {
+ if(brk_tab[i].addr != 0) {
+ brk_tab[i].inst = *(u_int *)brk_tab[i].addr;
+ *(u_int *)brk_tab[i].addr = BREAK_BRKPT;
+ MachFlushDCache(brk_tab[i].addr,4);
+ MachFlushICache(brk_tab[i].addr,4);
+ }
+ }
+}
+
+break_restore()
+{
+ int i;
+
+ for(i = 0; i < MAXBRK; i++) {
+ if(brk_tab[i].addr != 0) {
+ *(u_int *)brk_tab[i].addr = brk_tab[i].inst;
+ MachFlushDCache(brk_tab[i].addr,4);
+ MachFlushICache(brk_tab[i].addr,4);
+ }
+ }
+}
+
+break_find(va)
+{
+ int i;
+
+ for(i = 0; i < MAXBRK; i++) {
+ if(brk_tab[i].addr == va) {
+ return(i);
+ }
+ }
+ return(-1);
+}
+
+prt_break()
+{
+ int i;
+
+ for(i = 0; i < MAXBRK; i++) {
+ if(brk_tab[i].addr != 0) {
+ printf("\n %08x\t", brk_tab[i].addr);
+ mdbprintins(brk_tab[i].inst, brk_tab[i].addr);
+ }
+ }
+}
+mdb(causeReg, vadr, p, kernelmode)
+{
+ int c;
+ int newaddr;
+ int size;
+ int cause;
+static int ssandrun; /* Single step and run flag (when cont at brk) */
+
+ splhigh();
+ cause = (causeReg & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
+ newaddr = (int)(mdbpcb.pcb_regs[PC]);
+ switch(cause) {
+ case T_BREAK:
+ if(*(int *)newaddr == BREAK_SOVER) {
+ break_restore();
+ mdbpcb.pcb_regs[PC] += 4;
+ printf("\nStop break (panic)\n# ");
+ printf(" %08x\t",newaddr);
+ mdbprintins(*(int *)newaddr, newaddr);
+ printf("\n# ");
+ break;
+ }
+ if(*(int *)newaddr == BREAK_BRKPT) {
+ break_restore();
+ printf("\rBRK %08x\t",newaddr);
+ if(mdbprintins(*(int *)newaddr, newaddr)) {
+ newaddr += 4;
+ printf("\n %08x\t",newaddr);
+ mdbprintins(*(int *)newaddr, newaddr);
+ }
+ printf("\n# ");
+ break;
+ }
+ if(mdbclrsstep(causeReg)) {
+ if(ssandrun) { /* Step over bp before free run */
+ ssandrun = 0;
+ break_insert();
+ return(TRUE);
+ }
+ printf("\r %08x\t",newaddr);
+ if(mdbprintins(*(int *)newaddr, newaddr)) {
+ newaddr += 4;
+ printf("\n %08x\t",newaddr);
+ mdbprintins(*(int *)newaddr, newaddr);
+ }
+ printf("\n# ");
+ }
+ break;
+
+ default:
+ printf("\n-- %s --\n# ",trap_type[cause]);
+ }
+ ssandrun = 0;
+ break_restore();
+
+ while(c = cngetc()) {
+ switch(c) {
+ case 'T':
+ trapDump("Debugger");
+ break;
+ case 'b':
+ printf("break-");
+ c = cngetc();
+ switch(c) {
+ case 's':
+ printf("set at ");
+ c = gethex(&newaddr, newaddr);
+ if(c != '\e') {
+ set_break(newaddr);
+ }
+ break;
+
+ case 'd':
+ printf("delete at ");
+ c = gethex(&newaddr, newaddr);
+ if(c != '\e') {
+ del_break(newaddr);
+ }
+ break;
+
+ case 'p':
+ printf("print");
+ prt_break();
+ break;
+ }
+ break;
+
+ case 'r':
+ print_regs();
+ break;
+
+ case 'I':
+ printf("Instruction at ");
+ c = gethex(&newaddr, newaddr);
+ while(c != '\e') {
+ printf("\n %08x\t",newaddr);
+ mdbprintins(*(int *)newaddr, newaddr);
+ newaddr += 4;
+ c = cngetc();
+ }
+ break;
+
+ case 'c':
+ printf("continue");
+ if(break_find((int)(mdbpcb.pcb_regs[PC])) >= 0) {
+ ssandrun = 1;
+ mdbsetsstep();
+ }
+ else {
+ break_insert();
+ }
+ return(TRUE);
+
+ case 's':
+ set_break(mdbpcb.pcb_regs[PC] + 8);
+ return(TRUE);
+ case ' ':
+ mdbsetsstep();
+ return(TRUE);
+
+ case 'd':
+ printf("dump ");
+ c = gethex(&newaddr, newaddr);
+ if(c == ',') {
+ c = gethex(&size,256);
+ }
+ else {
+ size = 16;
+ }
+ if(c == '\n' && newaddr != 0) {
+ dump((u_int *)newaddr, size);
+ newaddr += size;
+ }
+ break;
+
+ case 'm':
+ printf("mod ");
+ c = gethex(&newaddr, newaddr);
+ while(c == ',') {
+ c = gethex(&size, 0);
+ if(c != '\e')
+ *((u_int *)newaddr)++ = size;
+ }
+ break;
+
+ case 'i':
+ printf("in-");
+ c = cngetc();
+ switch(c) {
+ case 'b':
+ printf("byte ");
+ c = gethex(&newaddr, newaddr);
+ if(c == '\n') {
+ printf("= %02x",
+ *(u_char *)newaddr);
+ }
+ break;
+ case 'h':
+ printf("halfword ");
+ c = gethex(&newaddr, newaddr);
+ if(c == '\n') {
+ printf("= %04x",
+ *(u_short *)newaddr);
+ }
+ break;
+ case 'w':
+ printf("word ");
+ c = gethex(&newaddr, newaddr);
+ if(c == '\n') {
+ printf("= %08x",
+ *(u_int *)newaddr);
+ }
+ break;
+ }
+ break;
+
+ case 'o':
+ printf("out-");
+ c = cngetc();
+ switch(c) {
+ case 'b':
+ printf("byte ");
+ c = gethex(&newaddr, newaddr);
+ if(c == ',') {
+ c = gethex(&size, 0);
+ if(c == '\n') {
+ *(u_char *)newaddr = size;
+ }
+ }
+ break;
+ case 'h':
+ printf("halfword ");
+ c = gethex(&newaddr, newaddr);
+ if(c == ',') {
+ c = gethex(&size, 0);
+ if(c == '\n') {
+ *(u_short *)newaddr = size;
+ }
+ }
+ break;
+ case 'w':
+ printf("word ");
+ c = gethex(&newaddr, newaddr);
+ if(c == ',') {
+ c = gethex(&size, 0);
+ if(c == '\n') {
+ *(u_int *)newaddr = size;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 't':
+ printf("tlb-dump\n");
+ arc_dump_tlb(0,23);
+ (void)cngetc();
+ arc_dump_tlb(24,47);
+ break;
+
+ case 'f':
+ printf("flush-");
+ c = cngetc();
+ switch(c) {
+ case 't':
+ printf("tlb");
+ MachTLBFlush();
+ break;
+
+ case 'c':
+ printf("cache");
+ MachFlushCache();
+ break;
+ }
+ break;
+
+ default:
+ cnputc('\a');
+ break;
+ }
+ printf("\n# ");
+ }
+}
+
+u_int mdb_ss_addr;
+u_int mdb_ss_instr;
+
+mdbsetsstep()
+{
+ register u_int va;
+ register int *locr0 = mdbpcb.pcb_regs;
+ int i;
+
+ /* compute next address after current location */
+ if(mdbpeek(locr0[PC]) != 0) {
+ va = MachEmulateBranch(locr0, locr0[PC], 0, mdbpeek(locr0[PC]));
+ }
+ else {
+ va = locr0[PC] + 4;
+ }
+ if (mdb_ss_addr) {
+ printf("mdbsetsstep: breakpoint already set at %x (va %x)\n",
+ mdb_ss_addr, va);
+ return;
+ }
+ mdb_ss_addr = va;
+
+ if ((int)va < 0) {
+ /* kernel address */
+ mdb_ss_instr = mdbpeek(va);
+ mdbpoke((caddr_t)va, BREAK_SSTEP);
+ MachFlushDCache(va,4);
+ MachFlushICache(va,4);
+ return;
+ }
+}
+
+mdbclrsstep(cr)
+ int cr;
+{
+ register u_int pc, va;
+ u_int instr;
+
+ /* fix pc if break instruction is in the delay slot */
+ pc = mdbpcb.pcb_regs[PC];
+ if (cr < 0)
+ pc += 4;
+
+ /* check to be sure its the one we are expecting */
+ va = mdb_ss_addr;
+ if (!va || va != pc)
+ return(FALSE);
+
+ /* read break instruction */
+ instr = mdbpeek(va);
+ if (instr != BREAK_SSTEP)
+ return(FALSE);
+
+ if ((int)va < 0) {
+ /* kernel address */
+ mdbpoke((caddr_t)va, mdb_ss_instr);
+ MachFlushDCache(va,4);
+ MachFlushICache(va,4);
+ mdb_ss_addr = 0;
+ return(TRUE);
+ }
+
+ printf("can't clear break at %x\n", va);
+ mdb_ss_addr = 0;
+ return(FALSE);
+}
+
+void
+mdbreadc(lp)
+ char *lp;
+{
+ int c;
+
+ c = cngetc();
+ if (c == '\r')
+ c = '\n';
+ *lp = c;
+}
+
+void
+mdbwrite(lp, len)
+ char *lp;
+ int len;
+{
+ while (len-- > 0)
+ cnputc(*lp++);
+}
+
+/* ARGSUSED */
+mdbprintins(ins, mdbdot)
+{
+ InstFmt i;
+ int delay = 0;
+
+ i.word = ins;
+
+ switch (i.JType.op) {
+ case OP_SPECIAL:
+ if (i.word == 0) {
+ printf("nop");
+ break;
+ }
+ if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
+ printf("move\t%s,%s",
+ reg_name[i.RType.rd],
+ reg_name[i.RType.rs]);
+ break;
+ }
+ printf("%s", spec_name[i.RType.func]);
+ switch (i.RType.func) {
+ case OP_SLL:
+ case OP_SRL:
+ case OP_SRA:
+ case OP_DSLL:
+ case OP_DSRL:
+ case OP_DSRA:
+ case OP_DSLL32:
+ case OP_DSRL32:
+ case OP_DSRA32:
+ printf("\t%s,%s,%d",
+ reg_name[i.RType.rd],
+ reg_name[i.RType.rt],
+ i.RType.shamt);
+ break;
+
+ case OP_SLLV:
+ case OP_SRLV:
+ case OP_SRAV:
+ case OP_DSLLV:
+ case OP_DSRLV:
+ case OP_DSRAV:
+ printf("\t%s,%s,%s",
+ reg_name[i.RType.rd],
+ reg_name[i.RType.rt],
+ reg_name[i.RType.rs]);
+ break;
+
+ case OP_MFHI:
+ case OP_MFLO:
+ printf("\t%s", reg_name[i.RType.rd]);
+ break;
+
+ case OP_JR:
+ case OP_JALR:
+ delay = 1;
+ /* FALLTHROUGH */
+ case OP_MTLO:
+ case OP_MTHI:
+ printf("\t%s", reg_name[i.RType.rs]);
+ break;
+
+ case OP_MULT:
+ case OP_MULTU:
+ case OP_DMULT:
+ case OP_DMULTU:
+ case OP_DIV:
+ case OP_DIVU:
+ case OP_DDIV:
+ case OP_DDIVU:
+ printf("\t%s,%s",
+ reg_name[i.RType.rs],
+ reg_name[i.RType.rt]);
+ break;
+
+ case OP_SYSCALL:
+ case OP_SYNC:
+ break;
+
+ case OP_BREAK:
+ printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
+ break;
+
+ default:
+ printf("\t%s,%s,%s",
+ reg_name[i.RType.rd],
+ reg_name[i.RType.rs],
+ reg_name[i.RType.rt]);
+ };
+ break;
+
+ case OP_BCOND:
+ printf("%s\t%s,", bcond_name[i.IType.rt],
+ reg_name[i.IType.rs]);
+ goto pr_displ;
+
+ case OP_BLEZ:
+ case OP_BLEZL:
+ case OP_BGTZ:
+ case OP_BGTZL:
+ printf("%s\t%s,", op_name[i.IType.op],
+ reg_name[i.IType.rs]);
+ goto pr_displ;
+
+ case OP_BEQ:
+ case OP_BEQL:
+ if (i.IType.rs == 0 && i.IType.rt == 0) {
+ printf("b\t");
+ goto pr_displ;
+ }
+ /* FALLTHROUGH */
+ case OP_BNE:
+ case OP_BNEL:
+ printf("%s\t%s,%s,", op_name[i.IType.op],
+ reg_name[i.IType.rs],
+ reg_name[i.IType.rt]);
+ pr_displ:
+ delay = 1;
+ printf("0x%08x", mdbdot + 4 + ((short)i.IType.imm << 2));
+ break;
+
+ case OP_COP0:
+ switch (i.RType.rs) {
+ case OP_BCx:
+ case OP_BCy:
+ printf("bc0%c\t",
+ "ft"[i.RType.rt & COPz_BC_TF_MASK]);
+ goto pr_displ;
+
+ case OP_MT:
+ printf("mtc0\t%s,%s",
+ reg_name[i.RType.rt],
+ c0_reg[i.RType.rd]);
+ break;
+
+ case OP_DMT:
+ printf("dmtc0\t%s,%s",
+ reg_name[i.RType.rt],
+ c0_reg[i.RType.rd]);
+ break;
+
+ case OP_MF:
+ printf("mfc0\t%s,%s",
+ reg_name[i.RType.rt],
+ c0_reg[i.RType.rd]);
+ break;
+
+ case OP_DMF:
+ printf("dmfc0\t%s,%s",
+ reg_name[i.RType.rt],
+ c0_reg[i.RType.rd]);
+ break;
+
+ default:
+ printf("%s", c0_opname[i.FRType.func]);
+ };
+ break;
+
+ case OP_COP1:
+ switch (i.RType.rs) {
+ case OP_BCx:
+ case OP_BCy:
+ printf("bc1%c\t",
+ "ft"[i.RType.rt & COPz_BC_TF_MASK]);
+ goto pr_displ;
+
+ case OP_MT:
+ printf("mtc1\t%s,f%d",
+ reg_name[i.RType.rt],
+ i.RType.rd);
+ break;
+
+ case OP_MF:
+ printf("mfc1\t%s,f%d",
+ reg_name[i.RType.rt],
+ i.RType.rd);
+ break;
+
+ case OP_CT:
+ printf("ctc1\t%s,f%d",
+ reg_name[i.RType.rt],
+ i.RType.rd);
+ break;
+
+ case OP_CF:
+ printf("cfc1\t%s,f%d",
+ reg_name[i.RType.rt],
+ i.RType.rd);
+ break;
+
+ default:
+ printf("%s.%s\tf%d,f%d,f%d",
+ cop1_name[i.FRType.func],
+ fmt_name[i.FRType.fmt],
+ i.FRType.fd, i.FRType.fs, i.FRType.ft);
+ };
+ break;
+
+ case OP_J:
+ case OP_JAL:
+ printf("%s\t", op_name[i.JType.op]);
+ printf("0x%8x",(mdbdot & 0xF0000000) | (i.JType.target << 2));
+ delay = 1;
+ break;
+
+ case OP_LWC1:
+ case OP_SWC1:
+ printf("%s\tf%d,", op_name[i.IType.op],
+ i.IType.rt);
+ goto loadstore;
+
+ case OP_LB:
+ case OP_LH:
+ case OP_LW:
+ case OP_LD:
+ case OP_LBU:
+ case OP_LHU:
+ case OP_LWU:
+ case OP_SB:
+ case OP_SH:
+ case OP_SW:
+ case OP_SD:
+ printf("%s\t%s,", op_name[i.IType.op],
+ reg_name[i.IType.rt]);
+ loadstore:
+ printf("%d(%s)", (short)i.IType.imm,
+ reg_name[i.IType.rs]);
+ break;
+
+ case OP_ORI:
+ case OP_XORI:
+ if (i.IType.rs == 0) {
+ printf("li\t%s,0x%x",
+ reg_name[i.IType.rt],
+ i.IType.imm);
+ break;
+ }
+ /* FALLTHROUGH */
+ case OP_ANDI:
+ printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
+ reg_name[i.IType.rt],
+ reg_name[i.IType.rs],
+ i.IType.imm);
+ break;
+
+ case OP_LUI:
+ printf("%s\t%s,0x%x", op_name[i.IType.op],
+ reg_name[i.IType.rt],
+ i.IType.imm);
+ break;
+
+ case OP_ADDI:
+ case OP_DADDI:
+ case OP_ADDIU:
+ case OP_DADDIU:
+ if (i.IType.rs == 0) {
+ printf("li\t%s,%d",
+ reg_name[i.IType.rt],
+ (short)i.IType.imm);
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ printf("%s\t%s,%s,%d", op_name[i.IType.op],
+ reg_name[i.IType.rt],
+ reg_name[i.IType.rs],
+ (short)i.IType.imm);
+ }
+ return(delay);
+}
+
+#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
+
+#if 0
+/*
+ * Print a stack backtrace.
+ */
+void
+mdbstacktrace(printlocals)
+ int printlocals;
+{
+ u_int pc, sp, ra, va, subr;
+ int a0, a1, a2, a3;
+ u_int instr, mask;
+ InstFmt i;
+ int more, stksize;
+ extern MachKernGenException();
+ extern MachUserGenException();
+ extern MachKernIntr();
+ extern MachUserIntr();
+ extern setsoftclock();
+
+ /* get initial values from the exception frame */
+ sp = mdbpcb.pcb_regs[SP];
+ pc = mdbpcb.pcb_regs[PC];
+ ra = mdbpcb.pcb_regs[RA];
+ a0 = mdbpcb.pcb_regs[A0];
+ a1 = mdbpcb.pcb_regs[A1];
+ a2 = mdbpcb.pcb_regs[A2];
+ a3 = mdbpcb.pcb_regs[A3];
+
+loop:
+ /* check for current PC in the kernel interrupt handler code */
+ if (pc >= (u_int)MachKernIntr && pc < (u_int)MachUserIntr) {
+ /* NOTE: the offsets depend on the code in locore.s */
+ printf("interupt\n");
+ a0 = mdbchkget(sp + 36, DSP);
+ a1 = mdbchkget(sp + 40, DSP);
+ a2 = mdbchkget(sp + 44, DSP);
+ a3 = mdbchkget(sp + 48, DSP);
+ pc = mdbchkget(sp + 20, DSP);
+ ra = mdbchkget(sp + 92, DSP);
+ sp = mdbchkget(sp + 100, DSP);
+ }
+
+ /* check for current PC in the exception handler code */
+ if (pc >= 0x80000000 && pc < (u_int)setsoftclock) {
+ ra = 0;
+ subr = 0;
+ goto done;
+ }
+ /*
+ * Find the beginning of the current subroutine by scanning backwards
+ * from the current PC for the end of the previous subroutine.
+ */
+ va = pc - sizeof(int);
+ while ((instr = mdbchkget(va, ISP)) != MIPS_JR_RA)
+ va -= sizeof(int);
+ va += 2 * sizeof(int); /* skip back over branch & delay slot */
+ /* skip over nulls which might separate .o files */
+ while ((instr = mdbchkget(va, ISP)) == 0)
+ va += sizeof(int);
+ subr = va;
+
+ /* scan forwards to find stack size and any saved registers */
+ stksize = 0;
+ more = 3;
+ mask = 0;
+ for (; more; va += sizeof(int), more = (more == 3) ? 3 : more - 1) {
+ /* stop if hit our current position */
+ if (va >= pc)
+ break;
+ instr = mdbchkget(va, ISP);
+ i.word = instr;
+ switch (i.JType.op) {
+ case OP_SPECIAL:
+ switch (i.RType.func) {
+ case OP_JR:
+ case OP_JALR:
+ more = 2; /* stop after next instruction */
+ break;
+
+ case OP_SYSCALL:
+ case OP_BREAK:
+ more = 1; /* stop now */
+ };
+ break;
+
+ case OP_BCOND:
+ case OP_J:
+ case OP_JAL:
+ case OP_BEQ:
+ case OP_BNE:
+ case OP_BLEZ:
+ case OP_BGTZ:
+ more = 2; /* stop after next instruction */
+ break;
+
+ case OP_COP0:
+ case OP_COP1:
+ case OP_COP2:
+ case OP_COP3:
+ switch (i.RType.rs) {
+ case OP_BCx:
+ case OP_BCy:
+ more = 2; /* stop after next instruction */
+ };
+ break;
+
+ case OP_SW:
+ /* look for saved registers on the stack */
+ if (i.IType.rs != 29)
+ break;
+ /* only restore the first one */
+ if (mask & (1 << i.IType.rt))
+ break;
+ mask |= 1 << i.IType.rt;
+ switch (i.IType.rt) {
+ case 4: /* a0 */
+ a0 = mdbchkget(sp + (short)i.IType.imm, DSP);
+ break;
+
+ case 5: /* a1 */
+ a1 = mdbchkget(sp + (short)i.IType.imm, DSP);
+ break;
+
+ case 6: /* a2 */
+ a2 = mdbchkget(sp + (short)i.IType.imm, DSP);
+ break;
+
+ case 7: /* a3 */
+ a3 = mdbchkget(sp + (short)i.IType.imm, DSP);
+ break;
+
+ case 31: /* ra */
+ ra = mdbchkget(sp + (short)i.IType.imm, DSP);
+ }
+ break;
+
+ case OP_ADDI:
+ case OP_ADDIU:
+ /* look for stack pointer adjustment */
+ if (i.IType.rs != 29 && i.IType.rt != 29)
+ break;
+ stksize = (short)i.IType.imm;
+ }
+ }
+
+done:
+ printf("%x+%x ", subr, pc - subr); /* XXX */
+ printf("(%x,%x,%x,%x)\n", a0, a1, a2, a3);
+
+ if (ra) {
+ pc = ra;
+ sp -= stksize;
+ goto loop;
+ }
+}
+#endif
+
+/*
+ * Very simple memory allocator for mdb.
+ */
+char *
+mdbmalloc(size)
+ int size;
+{
+ static char buffer[4096];
+ static char *bufp = buffer;
+ char *p;
+
+ /* round size up to sizeof(int) */
+ size = (size + sizeof(int) - 1) & ~(sizeof(int) - 1);
+ p = bufp;
+ bufp = p + size;
+ return (p);
+}
+
+/*
+ * Dump TLB contents.
+ */
+void arc_dump_tlb(int first,int last)
+{
+ int tlbno;
+ struct tlb tlb;
+
+ tlbno = first;
+
+ while(tlbno <= last) {
+ MachTLBRead(tlbno, &tlb);
+ if(tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V) {
+ printf("TLB %2d vad 0x%08x ", tlbno, tlb.tlb_hi);
+ }
+ else {
+ printf("TLB*%2d vad 0x%08x ", tlbno, tlb.tlb_hi);
+ }
+ printf("0=0x%08x ", pfn_to_vad(tlb.tlb_lo0));
+ printf("%c", tlb.tlb_lo0 & PG_M ? 'M' : ' ');
+ printf("%c", tlb.tlb_lo0 & PG_G ? 'G' : ' ');
+ printf(" atr %x ", (tlb.tlb_lo0 >> 3) & 7);
+ printf("1=0x%08x ", pfn_to_vad(tlb.tlb_lo1));
+ printf("%c", tlb.tlb_lo1 & PG_M ? 'M' : ' ');
+ printf("%c", tlb.tlb_lo1 & PG_G ? 'G' : ' ');
+ printf(" atr %x ", (tlb.tlb_lo1 >> 3) & 7);
+ printf(" sz=%x\n", tlb.tlb_mask);
+
+ tlbno++;
+ }
+}
diff --git a/sys/arch/arc/arc/pmap.c b/sys/arch/arc/arc/pmap.c
new file mode 100644
index 00000000000..f5baee426c6
--- /dev/null
+++ b/sys/arch/arc/arc/pmap.c
@@ -0,0 +1,1633 @@
+/* $OpenBSD: pmap.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)pmap.c 8.4 (Berkeley) 1/26/94
+ * $Id: pmap.c,v 1.1 1996/06/24 09:07:21 pefo Exp $
+ */
+
+/*
+ * Manages physical address maps.
+ *
+ * In addition to hardware address maps, this
+ * module is called upon to provide software-use-only
+ * maps which may or may not be stored in the same
+ * form as hardware maps. These pseudo-maps are
+ * used to store intermediate results from copy
+ * operations to and from address spaces.
+ *
+ * Since the information managed by this module is
+ * also stored by the logical address mapping module,
+ * this module may throw away valid virtual-to-physical
+ * mappings at almost any time. However, invalidations
+ * of virtual-to-physical mappings must be done as
+ * requested.
+ *
+ * In order to cope with hardware architectures which
+ * make virtual-to-physical map invalidates expensive,
+ * this module may delay invalidate or reduced protection
+ * operations until such time as they are actually
+ * necessary. This module is given full information as
+ * to which processors are currently using which maps,
+ * and to when physical maps must be made correct.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/user.h>
+#include <sys/buf.h>
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+
+#include <machine/cpu.h>
+#include <machine/pte.h>
+
+extern vm_page_t vm_page_alloc1 __P((void));
+extern void vm_page_free1 __P((vm_page_t));
+
+/*
+ * For each vm_page_t, there is a list of all currently valid virtual
+ * mappings of that page. An entry is a pv_entry_t, the list is pv_table.
+ * XXX really should do this as a part of the higher level code.
+ */
+typedef struct pv_entry {
+ struct pv_entry *pv_next; /* next pv_entry */
+ struct pmap *pv_pmap; /* pmap where mapping lies */
+ vm_offset_t pv_va; /* virtual address for mapping */
+ int pv_flags; /* Some flags for the mapping */
+} *pv_entry_t;
+#define PV_UNCACHED 0x0001 /* Page is mapped unchached */
+
+/*
+ * Local pte bits used only here
+ */
+#define PG_RO 0x40000000
+#define PG_WIRED 0x80000000
+
+pv_entry_t pv_table; /* array of entries, one per page */
+int pmap_remove_pv();
+
+#define pa_index(pa) atop((pa) - first_phys_addr)
+#define pa_to_pvh(pa) (&pv_table[pa_index(pa)])
+
+#ifdef DEBUG
+struct {
+ int kernel; /* entering kernel mapping */
+ int user; /* entering user mapping */
+ int ptpneeded; /* needed to allocate a PT page */
+ int pwchange; /* no mapping change, just wiring or protection */
+ int wchange; /* no mapping change, just wiring */
+ int mchange; /* was mapped but mapping to different page */
+ int managed; /* a managed page */
+ int firstpv; /* first mapping for this PA */
+ int secondpv; /* second mapping for this PA */
+ int ci; /* cache inhibited */
+ int unmanaged; /* not a managed page */
+ int flushes; /* cache flushes */
+ int cachehit; /* new entry forced valid entry out */
+} enter_stats;
+struct {
+ int calls;
+ int removes;
+ int flushes;
+ int pidflushes; /* HW pid stolen */
+ int pvfirst;
+ int pvsearch;
+} remove_stats;
+
+int pmapdebug = 0;
+#define PDB_FOLLOW 0x0001
+#define PDB_INIT 0x0002
+#define PDB_ENTER 0x0004
+#define PDB_REMOVE 0x0008
+#define PDB_CREATE 0x0010
+#define PDB_PTPAGE 0x0020
+#define PDB_PVENTRY 0x0040
+#define PDB_BITS 0x0080
+#define PDB_COLLECT 0x0100
+#define PDB_PROTECT 0x0200
+#define PDB_TLBPID 0x0400
+#define PDB_PARANOIA 0x2000
+#define PDB_WIRING 0x4000
+#define PDB_PVDUMP 0x8000
+
+#endif /* DEBUG */
+
+struct pmap kernel_pmap_store;
+
+vm_offset_t avail_start; /* PA of first available physical page */
+vm_offset_t avail_end; /* PA of last available physical page */
+vm_size_t mem_size; /* memory size in bytes */
+vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss)*/
+vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
+#ifdef ATTR
+char *pmap_attributes; /* reference and modify bits */
+#endif
+struct segtab *free_segtab; /* free list kept locally */
+u_int tlbpid_gen = 1; /* TLB PID generation count */
+int tlbpid_cnt = 2; /* next available TLB PID */
+pt_entry_t *Sysmap; /* kernel pte table */
+u_int Sysmapsize; /* number of pte's in Sysmap */
+
+/*
+ * Bootstrap the system enough to run with virtual memory.
+ * firstaddr is the first unused kseg0 address (not page aligned).
+ */
+void
+pmap_bootstrap(firstaddr)
+ vm_offset_t firstaddr;
+{
+ register int i;
+ register pt_entry_t *spte;
+ vm_offset_t start = firstaddr;
+ extern int maxmem, physmem;
+
+#define valloc(name, type, num) \
+ (name) = (type *)firstaddr; firstaddr = (vm_offset_t)((name)+(num))
+ /*
+ * Allocate a PTE table for the kernel.
+ * The '1024' comes from PAGER_MAP_SIZE in vm_pager_init().
+ * This should be kept in sync.
+ * We also reserve space for kmem_alloc_pageable() for vm_fork().
+ */
+ Sysmapsize = (VM_KMEM_SIZE + VM_MBUF_SIZE + VM_PHYS_SIZE +
+ nbuf * MAXBSIZE + 16 * NCARGS) / NBPG + 1024 + 256;
+#ifdef SYSVSHM
+ Sysmapsize += shminfo.shmall;
+#endif
+ valloc(Sysmap, pt_entry_t, Sysmapsize);
+#ifdef ATTR
+ valloc(pmap_attributes, char, physmem);
+#endif
+ /*
+ * Allocate memory for pv_table.
+ * This will allocate more entries than we really need.
+ * We could do this in pmap_init when we know the actual
+ * phys_start and phys_end but its better to use kseg0 addresses
+ * rather than kernel virtual addresses mapped through the TLB.
+ */
+ i = maxmem - pica_btop(CACHED_TO_PHYS(firstaddr));
+ valloc(pv_table, struct pv_entry, i);
+
+ /*
+ * Clear allocated memory.
+ */
+ firstaddr = pica_round_page(firstaddr);
+ bzero((caddr_t)start, firstaddr - start);
+
+ avail_start = CACHED_TO_PHYS(firstaddr);
+ avail_end = pica_ptob(maxmem);
+ mem_size = avail_end - avail_start;
+
+ virtual_avail = VM_MIN_KERNEL_ADDRESS;
+ virtual_end = VM_MIN_KERNEL_ADDRESS + Sysmapsize * NBPG;
+ /* XXX need to decide how to set cnt.v_page_size */
+
+ simple_lock_init(&pmap_kernel()->pm_lock);
+ pmap_kernel()->pm_count = 1;
+
+ /*
+ * The R4?00 stores only one copy of the Global bit in the
+ * translation lookaside buffer for each 2 page entry.
+ * Thus invalid entrys must have the Global bit set so
+ * when Entry LO and Entry HI G bits are anded together
+ * they will produce a global bit to store in the tlb.
+ */
+ for(i = 0, spte = Sysmap; i < Sysmapsize; i++, spte++)
+ spte->pt_entry = PG_G;
+}
+
+/*
+ * Bootstrap memory allocator. This function allows for early dynamic
+ * memory allocation until the virtual memory system has been bootstrapped.
+ * After that point, either kmem_alloc or malloc should be used. This
+ * function works by stealing pages from the (to be) managed page pool,
+ * stealing virtual address space, then mapping the pages and zeroing them.
+ *
+ * It should be used from pmap_bootstrap till vm_page_startup, afterwards
+ * it cannot be used, and will generate a panic if tried. Note that this
+ * memory will never be freed, and in essence it is wired down.
+ */
+void *
+pmap_bootstrap_alloc(size)
+ int size;
+{
+ vm_offset_t val;
+ extern boolean_t vm_page_startup_initialized;
+
+ if (vm_page_startup_initialized)
+ panic("pmap_bootstrap_alloc: called after startup initialized");
+
+ val = PHYS_TO_CACHED(avail_start);
+ size = round_page(size);
+ avail_start += size;
+
+ blkclr((caddr_t)val, size);
+ return ((void *)val);
+}
+
+/*
+ * Initialize the pmap module.
+ * Called by vm_init, to initialize any structures that the pmap
+ * system needs to map virtual memory.
+ */
+void
+pmap_init(phys_start, phys_end)
+ vm_offset_t phys_start, phys_end;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_INIT))
+ printf("pmap_init(%x, %x)\n", phys_start, phys_end);
+#endif
+}
+
+/*
+ * Create and return a physical map.
+ *
+ * If the size specified for the map
+ * is zero, the map is an actual physical
+ * map, and may be referenced by the
+ * hardware.
+ *
+ * If the size specified is non-zero,
+ * the map will be used in software only, and
+ * is bounded by that size.
+ */
+pmap_t
+pmap_create(size)
+ vm_size_t size;
+{
+ register pmap_t pmap;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ printf("pmap_create(%x)\n", size);
+#endif
+ /*
+ * Software use map does not need a pmap
+ */
+ if (size)
+ return (NULL);
+
+ /* XXX: is it ok to wait here? */
+ pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
+#ifdef notifwewait
+ if (pmap == NULL)
+ panic("pmap_create: cannot allocate a pmap");
+#endif
+ bzero(pmap, sizeof(*pmap));
+ pmap_pinit(pmap);
+ return (pmap);
+}
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ */
+void
+pmap_pinit(pmap)
+ register struct pmap *pmap;
+{
+ register int i;
+ int s;
+ extern struct vmspace vmspace0;
+ extern struct user *proc0paddr;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ printf("pmap_pinit(%x)\n", pmap);
+#endif
+ simple_lock_init(&pmap->pm_lock);
+ pmap->pm_count = 1;
+ if (free_segtab) {
+ s = splimp();
+ pmap->pm_segtab = free_segtab;
+ free_segtab = *(struct segtab **)free_segtab;
+ pmap->pm_segtab->seg_tab[0] = NULL;
+ splx(s);
+ } else {
+ register struct segtab *stp;
+ vm_page_t mem;
+ void pmap_zero_page();
+
+ mem = vm_page_alloc1();
+ pmap_zero_page(VM_PAGE_TO_PHYS(mem));
+ pmap->pm_segtab = stp = (struct segtab *)
+ PHYS_TO_CACHED(VM_PAGE_TO_PHYS(mem));
+ i = NBPG / sizeof(struct segtab);
+ s = splimp();
+ while (--i != 0) {
+ stp++;
+ *(struct segtab **)stp = free_segtab;
+ free_segtab = stp;
+ }
+ splx(s);
+ }
+#ifdef DIAGNOSTIC
+ for (i = 0; i < PMAP_SEGTABSIZE; i++)
+ if (pmap->pm_segtab->seg_tab[i] != 0)
+ panic("pmap_pinit: pm_segtab != 0");
+#endif
+ if (pmap == &vmspace0.vm_pmap) {
+ /*
+ * The initial process has already been allocated a TLBPID
+ * in mach_init().
+ */
+ pmap->pm_tlbpid = 1;
+ pmap->pm_tlbgen = tlbpid_gen;
+ proc0paddr->u_pcb.pcb_segtab = (void *)pmap->pm_segtab;
+ } else {
+ pmap->pm_tlbpid = 0;
+ pmap->pm_tlbgen = 0;
+ }
+}
+
+/*
+ * Retire the given physical map from service.
+ * Should only be called if the map contains
+ * no valid mappings.
+ */
+void
+pmap_destroy(pmap)
+ register pmap_t pmap;
+{
+ int count;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ printf("pmap_destroy(%x)\n", pmap);
+#endif
+ if (pmap == NULL)
+ return;
+
+ simple_lock(&pmap->pm_lock);
+ count = --pmap->pm_count;
+ simple_unlock(&pmap->pm_lock);
+ if (count == 0) {
+ pmap_release(pmap);
+ free((caddr_t)pmap, M_VMPMAP);
+ }
+}
+
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+void
+pmap_release(pmap)
+ register pmap_t pmap;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ printf("pmap_release(%x)\n", pmap);
+#endif
+
+ if (pmap->pm_segtab) {
+ register pt_entry_t *pte;
+ register int i;
+ int s;
+#ifdef DIAGNOSTIC
+ register int j;
+#endif
+
+ for (i = 0; i < PMAP_SEGTABSIZE; i++) {
+ /* get pointer to segment map */
+ pte = pmap->pm_segtab->seg_tab[i];
+ if (!pte)
+ continue;
+#ifdef DIAGNOSTIC
+ for (j = 0; j < NPTEPG; j++) {
+ if ((pte+j)->pt_entry)
+ panic("pmap_release: segmap not empty");
+ }
+#endif
+ MachHitFlushDCache(pte, PAGE_SIZE);
+ vm_page_free1(
+ PHYS_TO_VM_PAGE(CACHED_TO_PHYS(pte)));
+ pmap->pm_segtab->seg_tab[i] = NULL;
+ }
+ s = splimp();
+ *(struct segtab **)pmap->pm_segtab = free_segtab;
+ free_segtab = pmap->pm_segtab;
+ splx(s);
+ pmap->pm_segtab = NULL;
+ }
+}
+
+/*
+ * Add a reference to the specified pmap.
+ */
+void
+pmap_reference(pmap)
+ pmap_t pmap;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_reference(%x)\n", pmap);
+#endif
+ if (pmap != NULL) {
+ simple_lock(&pmap->pm_lock);
+ pmap->pm_count++;
+ simple_unlock(&pmap->pm_lock);
+ }
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ *
+ * It is assumed that the start and end are properly
+ * rounded to the page size.
+ */
+void
+pmap_remove(pmap, sva, eva)
+ register pmap_t pmap;
+ vm_offset_t sva, eva;
+{
+ register vm_offset_t nssva;
+ register pt_entry_t *pte;
+ unsigned entry;
+ int flush;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
+ printf("pmap_remove(%x, %x, %x)\n", pmap, sva, eva);
+ remove_stats.calls++;
+#endif
+ if (pmap == NULL)
+ return;
+
+ if (!pmap->pm_segtab) {
+ register pt_entry_t *pte;
+
+ /* remove entries from kernel pmap */
+#ifdef DIAGNOSTIC
+ if (sva < VM_MIN_KERNEL_ADDRESS || eva > virtual_end)
+ panic("pmap_remove: kva not in range");
+#endif
+ pte = kvtopte(sva);
+ for (; sva < eva; sva += NBPG, pte++) {
+ entry = pte->pt_entry;
+ if (!(entry & PG_V))
+ continue;
+ if (entry & PG_WIRED)
+ pmap->pm_stats.wired_count--;
+ pmap->pm_stats.resident_count--;
+ if(pmap_remove_pv(pmap, sva, pfn_to_vad(entry))) {
+ MachFlushDCache(sva, PAGE_SIZE);
+ }
+#ifdef ATTR
+ pmap_attributes[atop(pfn_to_vad(entry))] = 0;
+#endif
+ /*
+ * Flush the TLB for the given address.
+ */
+ pte->pt_entry = PG_NV | PG_G; /* See above about G bit */
+ MachTLBFlushAddr(sva);
+#ifdef DEBUG
+ remove_stats.flushes++;
+
+#endif
+ }
+ return;
+ }
+
+#ifdef DIAGNOSTIC
+ if (eva > VM_MAXUSER_ADDRESS)
+ panic("pmap_remove: uva not in range");
+#endif
+ while (sva < eva) {
+ nssva = pica_trunc_seg(sva) + NBSEG;
+ if (nssva == 0 || nssva > eva)
+ nssva = eva;
+ /*
+ * If VA belongs to an unallocated segment,
+ * skip to the next segment boundary.
+ */
+ if (!(pte = pmap_segmap(pmap, sva))) {
+ sva = nssva;
+ continue;
+ }
+ /*
+ * Invalidate every valid mapping within this segment.
+ */
+ pte += uvtopte(sva);
+ for (; sva < nssva; sva += NBPG, pte++) {
+ entry = pte->pt_entry;
+ if (!(entry & PG_V))
+ continue;
+ if (entry & PG_WIRED)
+ pmap->pm_stats.wired_count--;
+ pmap->pm_stats.resident_count--;
+ if(pmap_remove_pv(pmap, sva, pfn_to_vad(entry))) {
+ MachFlushDCache(sva, PAGE_SIZE);
+ }
+#ifdef ATTR
+ pmap_attributes[atop(pfn_to_vad(entry))] = 0;
+#endif
+ pte->pt_entry = PG_NV;
+ /*
+ * Flush the TLB for the given address.
+ */
+ if (pmap->pm_tlbgen == tlbpid_gen) {
+ MachTLBFlushAddr(sva | (pmap->pm_tlbpid <<
+ VMTLB_PID_SHIFT));
+#ifdef DEBUG
+ remove_stats.flushes++;
+#endif
+ }
+ }
+ }
+}
+
+/*
+ * pmap_page_protect:
+ *
+ * Lower the permission for all mappings to a given page.
+ */
+void
+pmap_page_protect(pa, prot)
+ vm_offset_t pa;
+ vm_prot_t prot;
+{
+ register pv_entry_t pv;
+ register vm_offset_t va;
+ int s;
+
+#ifdef DEBUG
+ if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) ||
+ prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE))
+ printf("pmap_page_protect(%x, %x)\n", pa, prot);
+#endif
+ if (!IS_VM_PHYSADDR(pa))
+ return;
+
+ switch (prot) {
+ case VM_PROT_READ|VM_PROT_WRITE:
+ case VM_PROT_ALL:
+ break;
+
+ /* copy_on_write */
+ case VM_PROT_READ:
+ case VM_PROT_READ|VM_PROT_EXECUTE:
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ /*
+ * Loop over all current mappings setting/clearing as appropos.
+ */
+ if (pv->pv_pmap != NULL) {
+ for (; pv; pv = pv->pv_next) {
+ extern vm_offset_t pager_sva, pager_eva;
+
+ va = pv->pv_va;
+
+ /*
+ * XXX don't write protect pager mappings
+ */
+ if (va >= pager_sva && va < pager_eva)
+ continue;
+ pmap_protect(pv->pv_pmap, va, va + PAGE_SIZE,
+ prot);
+ }
+ }
+ splx(s);
+ break;
+
+ /* remove_all */
+ default:
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ while (pv->pv_pmap != NULL) {
+ pmap_remove(pv->pv_pmap, pv->pv_va,
+ pv->pv_va + PAGE_SIZE);
+ }
+ splx(s);
+ }
+}
+
+/*
+ * Set the physical protection on the
+ * specified range of this map as requested.
+ */
+void
+pmap_protect(pmap, sva, eva, prot)
+ register pmap_t pmap;
+ vm_offset_t sva, eva;
+ vm_prot_t prot;
+{
+ register vm_offset_t nssva;
+ register pt_entry_t *pte;
+ register unsigned entry;
+ u_int p;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
+ printf("pmap_protect(%x, %x, %x, %x)\n", pmap, sva, eva, prot);
+#endif
+ if (pmap == NULL)
+ return;
+
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+ pmap_remove(pmap, sva, eva);
+ return;
+ }
+
+ p = (prot & VM_PROT_WRITE) ? PG_M : PG_RO;
+
+ if (!pmap->pm_segtab) {
+ /*
+ * Change entries in kernel pmap.
+ * This will trap if the page is writeable (in order to set
+ * the dirty bit) even if the dirty bit is already set. The
+ * optimization isn't worth the effort since this code isn't
+ * executed much. The common case is to make a user page
+ * read-only.
+ */
+#ifdef DIAGNOSTIC
+ if (sva < VM_MIN_KERNEL_ADDRESS || eva > virtual_end)
+ panic("pmap_protect: kva not in range");
+#endif
+ pte = kvtopte(sva);
+ for (; sva < eva; sva += NBPG, pte++) {
+ entry = pte->pt_entry;
+ if (!(entry & PG_V))
+ continue;
+ entry = (entry & ~(PG_M | PG_RO)) | p;
+ pte->pt_entry = entry;
+ /*
+ * Update the TLB if the given address is in the cache.
+ */
+ MachTLBUpdate(sva, entry);
+ }
+ return;
+ }
+
+#ifdef DIAGNOSTIC
+ if (eva > VM_MAXUSER_ADDRESS)
+ panic("pmap_protect: uva not in range");
+#endif
+ while (sva < eva) {
+ nssva = pica_trunc_seg(sva) + NBSEG;
+ if (nssva == 0 || nssva > eva)
+ nssva = eva;
+ /*
+ * If VA belongs to an unallocated segment,
+ * skip to the next segment boundary.
+ */
+ if (!(pte = pmap_segmap(pmap, sva))) {
+ sva = nssva;
+ continue;
+ }
+ /*
+ * Change protection on every valid mapping within this segment.
+ */
+ pte += (sva >> PGSHIFT) & (NPTEPG - 1);
+ for (; sva < nssva; sva += NBPG, pte++) {
+ entry = pte->pt_entry;
+ if (!(entry & PG_V))
+ continue;
+ entry = (entry & ~(PG_M | PG_RO)) | p;
+ pte->pt_entry = entry;
+ /*
+ * Update the TLB if the given address is in the cache.
+ */
+ if (pmap->pm_tlbgen == tlbpid_gen)
+ MachTLBUpdate(sva | (pmap->pm_tlbpid <<
+ VMTLB_PID_SHIFT), entry);
+ }
+ }
+}
+
+/*
+ * Return RO protection of page.
+ */
+int
+pmap_is_page_ro(pmap, va, entry)
+ pmap_t pmap;
+ vm_offset_t va;
+ int entry;
+{
+ return(entry & PG_RO);
+}
+
+/*
+ * pmap_page_cache:
+ *
+ * Change all mappings of a page to cached/uncached.
+ */
+void
+pmap_page_cache(pa,mode)
+ vm_offset_t pa;
+{
+ register pv_entry_t pv;
+ register pt_entry_t *pte;
+ register vm_offset_t va;
+ register unsigned entry;
+ register unsigned newmode;
+ int s;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
+ printf("pmap_page_uncache(%x)\n", pa);
+#endif
+ if (!IS_VM_PHYSADDR(pa))
+ return;
+
+ newmode = mode & PV_UNCACHED ? PG_UNCACHED : PG_CACHED;
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ while (pv) {
+ pv->pv_flags = (pv->pv_flags & ~PV_UNCACHED) | mode;
+ if (!pv->pv_pmap->pm_segtab) {
+ /*
+ * Change entries in kernel pmap.
+ */
+ pte = kvtopte(pv->pv_va);
+ entry = pte->pt_entry;
+ if (entry & PG_V) {
+ entry = (entry & ~PG_CACHEMODE) | newmode;
+ pte->pt_entry = entry;
+ MachTLBUpdate(pv->pv_va, entry);
+ }
+ }
+ else {
+ if (pte = pmap_segmap(pv->pv_pmap, pv->pv_va)) {
+ pte += (pv->pv_va >> PGSHIFT) & (NPTEPG - 1);
+ entry = pte->pt_entry;
+ if (entry & PG_V) {
+ entry = (entry & ~PG_CACHEMODE) | newmode;
+ pte->pt_entry = entry;
+ if (pv->pv_pmap->pm_tlbgen == tlbpid_gen)
+ MachTLBUpdate(pv->pv_va | (pv->pv_pmap->pm_tlbpid <<
+ VMTLB_PID_SHIFT), entry);
+ }
+ }
+ }
+ pv = pv->pv_next;
+ }
+
+ splx(s);
+}
+
+/*
+ * Insert the given physical page (p) at
+ * the specified virtual address (v) in the
+ * target physical map with the protection requested.
+ *
+ * If specified, the page will be wired down, meaning
+ * that the related pte can not be reclaimed.
+ *
+ * NB: This is the only routine which MAY NOT lazy-evaluate
+ * or lose information. That is, this routine must actually
+ * insert this page into the given map NOW.
+ */
+void
+pmap_enter(pmap, va, pa, prot, wired)
+ register pmap_t pmap;
+ vm_offset_t va;
+ register vm_offset_t pa;
+ vm_prot_t prot;
+ boolean_t wired;
+{
+ register pt_entry_t *pte;
+ register u_int npte;
+ register int i, j;
+ vm_page_t mem;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
+ printf("pmap_enter(%x, %x, %x, %x, %x)\n",
+ pmap, va, pa, prot, wired);
+#endif
+#ifdef DIAGNOSTIC
+ if (!pmap)
+ panic("pmap_enter: pmap");
+ if (!pmap->pm_segtab) {
+ enter_stats.kernel++;
+ if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end)
+ panic("pmap_enter: kva");
+ } else {
+ enter_stats.user++;
+ if (va >= VM_MAXUSER_ADDRESS)
+ panic("pmap_enter: uva");
+ }
+ if (pa & 0x80000000)
+ panic("pmap_enter: pa");
+ if (!(prot & VM_PROT_READ))
+ panic("pmap_enter: prot");
+#endif
+
+ if (IS_VM_PHYSADDR(pa)) {
+ register pv_entry_t pv, npv;
+ int s;
+
+ if (!(prot & VM_PROT_WRITE))
+ npte = PG_ROPAGE;
+ else {
+ register vm_page_t mem;
+
+ mem = PHYS_TO_VM_PAGE(pa);
+ if ((int)va < 0) {
+ /*
+ * Don't bother to trap on kernel writes,
+ * just record page as dirty.
+ */
+ npte = PG_RWPAGE;
+ mem->flags &= ~PG_CLEAN;
+ } else
+#ifdef ATTR
+ if ((pmap_attributes[atop(pa)] &
+ PMAP_ATTR_MOD) || !(mem->flags & PG_CLEAN))
+#else
+ if (!(mem->flags & PG_CLEAN))
+#endif
+ npte = PG_RWPAGE;
+ else
+ npte = PG_CWPAGE;
+ }
+
+#ifdef DEBUG
+ enter_stats.managed++;
+#endif
+ /*
+ * Enter the pmap and virtual address into the
+ * physical to virtual map table.
+ */
+ pv = pa_to_pvh(pa);
+ s = splimp();
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("pmap_enter: pv %x: was %x/%x/%x\n",
+ pv, pv->pv_va, pv->pv_pmap, pv->pv_next);
+#endif
+ if (pv->pv_pmap == NULL) {
+ /*
+ * No entries yet, use header as the first entry
+ */
+#ifdef DEBUG
+ if (pmapdebug & PDB_PVENTRY)
+ printf("pmap_enter: first pv: pmap %x va %x\n",
+ pmap, va);
+ enter_stats.firstpv++;
+#endif
+ pv->pv_va = va;
+ pv->pv_flags = 0;
+ pv->pv_pmap = pmap;
+ pv->pv_next = NULL;
+ } else {
+ if (!(pv->pv_flags & PV_UNCACHED)) {
+ /*
+ * There is at least one other VA mapping this page.
+ * Check if they are cache index compatible. If not
+ * remove all mappings, flush the cache and set page
+ * to be mapped uncached. Caching will be restored
+ * when pages are mapped compatible again. NOT!
+ */
+ for (npv = pv; npv; npv = npv->pv_next) {
+ /*
+ * Check cache aliasing incompatibility
+ */
+ if((npv->pv_va & machCacheAliasMask) != (va & machCacheAliasMask)) {
+ printf("pmap_enter: creating uncached mapping 0x%x, 0x%x.\n",npv->pv_va, va);
+ pmap_page_cache(pa,PV_UNCACHED);
+ MachFlushDCache(pv->pv_va, PAGE_SIZE);
+ npte = (npte & ~PG_CACHEMODE) | PG_UNCACHED;
+ break;
+ }
+ }
+ }
+ else {
+ npte = (npte & ~PG_CACHEMODE) | PG_UNCACHED;
+ }
+ /*
+ * There is at least one other VA mapping this page.
+ * Place this entry after the header.
+ *
+ * Note: the entry may already be in the table if
+ * we are only changing the protection bits.
+ */
+ for (npv = pv; npv; npv = npv->pv_next) {
+ if (pmap == npv->pv_pmap && va == npv->pv_va) {
+#ifdef DIAGNOSTIC
+ unsigned entry;
+
+ if (!pmap->pm_segtab)
+ entry = kvtopte(va)->pt_entry;
+ else {
+ pte = pmap_segmap(pmap, va);
+ if (pte) {
+ pte += (va >> PGSHIFT) &
+ (NPTEPG - 1);
+ entry = pte->pt_entry;
+ } else
+ entry = 0;
+ }
+ if (!(entry & PG_V) ||
+ pfn_to_vad(entry) != pa)
+ printf(
+ "pmap_enter: found va %x pa %x in pv_table but != %x\n",
+ va, pa, entry);
+#endif
+ goto fnd;
+ }
+ }
+#ifdef DEBUG
+ if (pmapdebug & PDB_PVENTRY)
+ printf("pmap_enter: new pv: pmap %x va %x\n",
+ pmap, va);
+#endif
+ /* can this cause us to recurse forever? */
+ npv = (pv_entry_t)
+ malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
+ npv->pv_va = va;
+ npv->pv_pmap = pmap;
+ npv->pv_next = pv->pv_next;
+ npv->pv_flags = pv->pv_flags;
+ pv->pv_next = npv;
+#ifdef DEBUG
+ if (!npv->pv_next)
+ enter_stats.secondpv++;
+#endif
+ fnd:
+ ;
+ }
+ splx(s);
+ } else {
+ /*
+ * Assumption: if it is not part of our managed memory
+ * then it must be device memory which may be volitile.
+ */
+#ifdef DEBUG
+ enter_stats.unmanaged++;
+#endif
+ npte = (prot & VM_PROT_WRITE) ? (PG_IOPAGE & ~PG_G) : (PG_IOPAGE& ~(PG_G | PG_M));
+ }
+
+ /*
+ * The only time we need to flush the cache is if we
+ * execute from a physical address and then change the data.
+ * This is the best place to do this.
+ * pmap_protect() and pmap_remove() are mostly used to switch
+ * between R/W and R/O pages.
+ * NOTE: we only support cache flush for read only text.
+ */
+ if (prot == (VM_PROT_READ | VM_PROT_EXECUTE))
+ MachFlushICache(PHYS_TO_CACHED(pa), PAGE_SIZE);
+
+ if (!pmap->pm_segtab) {
+ /* enter entries into kernel pmap */
+ pte = kvtopte(va);
+ npte |= vad_to_pfn(pa) | PG_ROPAGE | PG_G;
+ if (wired) {
+ pmap->pm_stats.wired_count++;
+ npte |= PG_WIRED;
+ }
+ if (!(pte->pt_entry & PG_V)) {
+ pmap->pm_stats.resident_count++;
+ } else {
+#ifdef DIAGNOSTIC
+ if (pte->pt_entry & PG_WIRED)
+ panic("pmap_enter: kernel wired");
+#endif
+ }
+ /*
+ * Update the same virtual address entry.
+ */
+ j = MachTLBUpdate(va, npte);
+ pte->pt_entry = npte;
+ return;
+ }
+
+ if (!(pte = pmap_segmap(pmap, va))) {
+ mem = vm_page_alloc1();
+ pmap_zero_page(VM_PAGE_TO_PHYS(mem));
+ pmap_segmap(pmap, va) = pte = (pt_entry_t *)
+ PHYS_TO_CACHED(VM_PAGE_TO_PHYS(mem));
+#ifdef DIAGNOSTIC
+ for (i = 0; i < NPTEPG; i++) {
+ if ((pte+i)->pt_entry)
+ panic("pmap_enter: new segmap not empty");
+ }
+#endif
+ }
+ pte += (va >> PGSHIFT) & (NPTEPG - 1);
+
+ /*
+ * Now validate mapping with desired protection/wiring.
+ * Assume uniform modified and referenced status for all
+ * MIPS pages in a MACH page.
+ */
+ npte |= vad_to_pfn(pa);
+ if (wired) {
+ pmap->pm_stats.wired_count++;
+ npte |= PG_WIRED;
+ }
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER) {
+ printf("pmap_enter: new pte %x", npte);
+ if (pmap->pm_tlbgen == tlbpid_gen)
+ printf(" tlbpid %d", pmap->pm_tlbpid);
+ printf("\n");
+ }
+#endif
+ if (!(pte->pt_entry & PG_V)) {
+ pmap->pm_stats.resident_count++;
+ }
+ pte->pt_entry = npte;
+ if (pmap->pm_tlbgen == tlbpid_gen)
+ j = MachTLBUpdate(va | (pmap->pm_tlbpid <<
+ VMTLB_PID_SHIFT), npte);
+}
+
+/*
+ * Routine: pmap_change_wiring
+ * Function: Change the wiring attribute for a map/virtual-address
+ * pair.
+ * In/out conditions:
+ * The mapping must already exist in the pmap.
+ */
+void
+pmap_change_wiring(pmap, va, wired)
+ register pmap_t pmap;
+ vm_offset_t va;
+ boolean_t wired;
+{
+ register pt_entry_t *pte;
+ u_int p;
+ register int i;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_WIRING))
+ printf("pmap_change_wiring(%x, %x, %x)\n", pmap, va, wired);
+#endif
+ if (pmap == NULL)
+ return;
+
+ p = wired ? PG_WIRED : 0;
+
+ /*
+ * Don't need to flush the TLB since PG_WIRED is only in software.
+ */
+ if (!pmap->pm_segtab) {
+ /* change entries in kernel pmap */
+#ifdef DIAGNOSTIC
+ if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end)
+ panic("pmap_change_wiring");
+#endif
+ pte = kvtopte(va);
+ } else {
+ if (!(pte = pmap_segmap(pmap, va)))
+ return;
+ pte += (va >> PGSHIFT) & (NPTEPG - 1);
+ }
+
+ if (!(pte->pt_entry & PG_WIRED) && p)
+ pmap->pm_stats.wired_count++;
+ else if ((pte->pt_entry & PG_WIRED) && !p)
+ pmap->pm_stats.wired_count--;
+
+ if (pte->pt_entry & PG_V)
+ pte->pt_entry = (pte->pt_entry & ~PG_WIRED) | p;
+}
+
+/*
+ * Routine: pmap_extract
+ * Function:
+ * Extract the physical page address associated
+ * with the given map/virtual_address pair.
+ */
+vm_offset_t
+pmap_extract(pmap, va)
+ register pmap_t pmap;
+ vm_offset_t va;
+{
+ register vm_offset_t pa;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_extract(%x, %x) -> ", pmap, va);
+#endif
+
+ if (!pmap->pm_segtab) {
+#ifdef DIAGNOSTIC
+ if (va < VM_MIN_KERNEL_ADDRESS || va >= virtual_end)
+ panic("pmap_extract");
+#endif
+ pa = pfn_to_vad(kvtopte(va)->pt_entry);
+ } else {
+ register pt_entry_t *pte;
+
+ if (!(pte = pmap_segmap(pmap, va)))
+ pa = 0;
+ else {
+ pte += (va >> PGSHIFT) & (NPTEPG - 1);
+ pa = pfn_to_vad(pte->pt_entry);
+ }
+ }
+ if (pa)
+ pa |= va & PGOFSET;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_extract: pa %x\n", pa);
+#endif
+ return (pa);
+}
+
+/*
+ * Copy the range specified by src_addr/len
+ * from the source map to the range dst_addr/len
+ * in the destination map.
+ *
+ * This routine is only advisory and need not do anything.
+ */
+void
+pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
+ pmap_t dst_pmap;
+ pmap_t src_pmap;
+ vm_offset_t dst_addr;
+ vm_size_t len;
+ vm_offset_t src_addr;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_copy(%x, %x, %x, %x, %x)\n",
+ dst_pmap, src_pmap, dst_addr, len, src_addr);
+#endif
+}
+
+/*
+ * Require that all active physical maps contain no
+ * incorrect entries NOW. [This update includes
+ * forcing updates of any address map caching.]
+ *
+ * Generally used to insure that a thread about
+ * to run will see a semantically correct world.
+ */
+void
+pmap_update()
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_update()\n");
+#endif
+}
+
+/*
+ * Routine: pmap_collect
+ * Function:
+ * Garbage collects the physical map system for
+ * pages which are no longer used.
+ * Success need not be guaranteed -- that is, there
+ * may well be pages which are not referenced, but
+ * others may be collected.
+ * Usage:
+ * Called by the pageout daemon when pages are scarce.
+ */
+void
+pmap_collect(pmap)
+ pmap_t pmap;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_collect(%x)\n", pmap);
+#endif
+}
+
+/*
+ * pmap_zero_page zeros the specified (machine independent)
+ * page.
+ */
+void
+pmap_zero_page(phys)
+ vm_offset_t phys;
+{
+ register int *p, *end;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_zero_page(%x)\n", phys);
+#endif
+/*XXX FIXME Not very sophisticated */
+ MachFlushCache();
+ p = (int *)PHYS_TO_CACHED(phys);
+ end = p + PAGE_SIZE / sizeof(int);
+ do {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ p[3] = 0;
+ p += 4;
+ } while (p != end);
+/*XXX FIXME Not very sophisticated */
+ MachFlushCache();
+}
+
+/*
+ * pmap_copy_page copies the specified (machine independent)
+ * page.
+ */
+void
+pmap_copy_page(src, dst)
+ vm_offset_t src, dst;
+{
+ register int *s, *d, *end;
+ register int tmp0, tmp1, tmp2, tmp3;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_copy_page(%x, %x)\n", src, dst);
+#endif
+/*XXX FIXME Not very sophisticated */
+ MachFlushCache();
+ s = (int *)PHYS_TO_CACHED(src);
+ d = (int *)PHYS_TO_CACHED(dst);
+ end = s + PAGE_SIZE / sizeof(int);
+ do {
+ tmp0 = s[0];
+ tmp1 = s[1];
+ tmp2 = s[2];
+ tmp3 = s[3];
+ d[0] = tmp0;
+ d[1] = tmp1;
+ d[2] = tmp2;
+ d[3] = tmp3;
+ s += 4;
+ d += 4;
+ } while (s != end);
+/*XXX FIXME Not very sophisticated */
+ MachFlushCache();
+}
+
+/*
+ * Routine: pmap_pageable
+ * Function:
+ * Make the specified pages (by pmap, offset)
+ * pageable (or not) as requested.
+ *
+ * A page which is not pageable may not take
+ * a fault; therefore, its page table entry
+ * must remain valid for the duration.
+ *
+ * This routine is merely advisory; pmap_enter
+ * will specify that these pages are to be wired
+ * down (or not) as appropriate.
+ */
+void
+pmap_pageable(pmap, sva, eva, pageable)
+ pmap_t pmap;
+ vm_offset_t sva, eva;
+ boolean_t pageable;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_pageable(%x, %x, %x, %x)\n",
+ pmap, sva, eva, pageable);
+#endif
+}
+
+/*
+ * Clear the modify bits on the specified physical page.
+ */
+void
+pmap_clear_modify(pa)
+ vm_offset_t pa;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_clear_modify(%x)\n", pa);
+#endif
+#ifdef ATTR
+ pmap_attributes[atop(pa)] &= ~PMAP_ATTR_MOD;
+#endif
+}
+
+/*
+ * pmap_clear_reference:
+ *
+ * Clear the reference bit on the specified physical page.
+ */
+void
+pmap_clear_reference(pa)
+ vm_offset_t pa;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_clear_reference(%x)\n", pa);
+#endif
+#ifdef ATTR
+ pmap_attributes[atop(pa)] &= ~PMAP_ATTR_REF;
+#endif
+}
+
+/*
+ * pmap_is_referenced:
+ *
+ * Return whether or not the specified physical page is referenced
+ * by any physical maps.
+ */
+boolean_t
+pmap_is_referenced(pa)
+ vm_offset_t pa;
+{
+#ifdef ATTR
+ return (pmap_attributes[atop(pa)] & PMAP_ATTR_REF);
+#else
+ return (FALSE);
+#endif
+}
+
+/*
+ * pmap_is_modified:
+ *
+ * Return whether or not the specified physical page is modified
+ * by any physical maps.
+ */
+boolean_t
+pmap_is_modified(pa)
+ vm_offset_t pa;
+{
+#ifdef ATTR
+ return (pmap_attributes[atop(pa)] & PMAP_ATTR_MOD);
+#else
+ return (FALSE);
+#endif
+}
+
+vm_offset_t
+pmap_phys_address(ppn)
+ int ppn;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_phys_address(%x)\n", ppn);
+#endif
+ return (pica_ptob(ppn));
+}
+
+/*
+ * Miscellaneous support routines
+ */
+
+/*
+ * Allocate a hardware PID and return it.
+ * It takes almost as much or more time to search the TLB for a
+ * specific PID and flush those entries as it does to flush the entire TLB.
+ * Therefore, when we allocate a new PID, we just take the next number. When
+ * we run out of numbers, we flush the TLB, increment the generation count
+ * and start over. PID zero is reserved for kernel use.
+ * This is called only by switch().
+ */
+int
+pmap_alloc_tlbpid(p)
+ register struct proc *p;
+{
+ register pmap_t pmap;
+ register int id;
+
+ pmap = &p->p_vmspace->vm_pmap;
+ if (pmap->pm_tlbgen != tlbpid_gen) {
+ id = tlbpid_cnt;
+ if (id == VMNUM_PIDS) {
+ MachTLBFlush();
+ /* reserve tlbpid_gen == 0 to alway mean invalid */
+ if (++tlbpid_gen == 0)
+ tlbpid_gen = 1;
+ id = 1;
+ }
+ tlbpid_cnt = id + 1;
+ pmap->pm_tlbpid = id;
+ pmap->pm_tlbgen = tlbpid_gen;
+ } else
+ id = pmap->pm_tlbpid;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_TLBPID)) {
+ if (curproc)
+ printf("pmap_alloc_tlbpid: curproc %d '%s' ",
+ curproc->p_pid, curproc->p_comm);
+ else
+ printf("pmap_alloc_tlbpid: curproc <none> ");
+ printf("segtab %x tlbpid %d pid %d '%s'\n",
+ pmap->pm_segtab, id, p->p_pid, p->p_comm);
+ }
+#endif
+ return (id);
+}
+
+/*
+ * Remove a physical to virtual address translation.
+ * Returns TRUE if it was the last mapping and cached, else FALSE.
+ */
+int
+pmap_remove_pv(pmap, va, pa)
+ pmap_t pmap;
+ vm_offset_t va, pa;
+{
+ register pv_entry_t pv, npv;
+ int s, last;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_PVENTRY))
+ printf("pmap_remove_pv(%x, %x, %x)\n", pmap, va, pa);
+#endif
+ /*
+ * Remove page from the PV table (raise IPL since we
+ * may be called at interrupt time).
+ */
+ if (!IS_VM_PHYSADDR(pa))
+ return(TRUE);
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ /*
+ * If it is the first entry on the list, it is actually
+ * in the header and we must copy the following entry up
+ * to the header. Otherwise we must search the list for
+ * the entry. In either case we free the now unused entry.
+ */
+ if (pmap == pv->pv_pmap && va == pv->pv_va) {
+ last = (pv->pv_flags & PV_UNCACHED) ? FALSE : TRUE;
+ npv = pv->pv_next;
+ if (npv) {
+ *pv = *npv;
+ free((caddr_t)npv, M_VMPVENT);
+ } else
+ pv->pv_pmap = NULL;
+#ifdef DEBUG
+ remove_stats.pvfirst++;
+#endif
+ } else {
+ last = FALSE;
+ for (npv = pv->pv_next; npv; pv = npv, npv = npv->pv_next) {
+#ifdef DEBUG
+ remove_stats.pvsearch++;
+#endif
+ if (pmap == npv->pv_pmap && va == npv->pv_va)
+ goto fnd;
+ }
+#ifdef DIAGNOSTIC
+ printf("pmap_remove_pv(%x, %x, %x) not found\n", pmap, va, pa);
+ panic("pmap_remove_pv");
+#endif
+ fnd:
+ pv->pv_next = npv->pv_next;
+ free((caddr_t)npv, M_VMPVENT);
+ }
+ splx(s);
+ return(last);
+}
+
+/*
+ * vm_page_alloc1:
+ *
+ * Allocate and return a memory cell with no associated object.
+ */
+vm_page_t
+vm_page_alloc1()
+{
+ register vm_page_t mem;
+ int spl;
+
+ spl = splimp(); /* XXX */
+ simple_lock(&vm_page_queue_free_lock);
+ if (vm_page_queue_free.tqh_first == NULL) {
+ simple_unlock(&vm_page_queue_free_lock);
+ splx(spl);
+ return (NULL);
+ }
+
+ mem = vm_page_queue_free.tqh_first;
+ TAILQ_REMOVE(&vm_page_queue_free, mem, pageq);
+
+ cnt.v_free_count--;
+ simple_unlock(&vm_page_queue_free_lock);
+ splx(spl);
+
+ mem->flags = PG_BUSY | PG_CLEAN | PG_FAKE;
+ mem->wire_count = 0;
+
+ /*
+ * Decide if we should poke the pageout daemon.
+ * We do this if the free count is less than the low
+ * water mark, or if the free count is less than the high
+ * water mark (but above the low water mark) and the inactive
+ * count is less than its target.
+ *
+ * We don't have the counts locked ... if they change a little,
+ * it doesn't really matter.
+ */
+
+ if (cnt.v_free_count < cnt.v_free_min ||
+ (cnt.v_free_count < cnt.v_free_target &&
+ cnt.v_inactive_count < cnt.v_inactive_target))
+ thread_wakeup((void *)&vm_pages_needed);
+ return (mem);
+}
+
+/*
+ * vm_page_free1:
+ *
+ * Returns the given page to the free list,
+ * disassociating it with any VM object.
+ *
+ * Object and page must be locked prior to entry.
+ */
+void
+vm_page_free1(mem)
+ register vm_page_t mem;
+{
+
+ if (mem->flags & PG_ACTIVE) {
+ TAILQ_REMOVE(&vm_page_queue_active, mem, pageq);
+ mem->flags &= ~PG_ACTIVE;
+ cnt.v_active_count--;
+ }
+
+ if (mem->flags & PG_INACTIVE) {
+ TAILQ_REMOVE(&vm_page_queue_inactive, mem, pageq);
+ mem->flags &= ~PG_INACTIVE;
+ cnt.v_inactive_count--;
+ }
+
+ if (!(mem->flags & PG_FICTITIOUS)) {
+ int spl;
+
+ spl = splimp();
+ simple_lock(&vm_page_queue_free_lock);
+ TAILQ_INSERT_TAIL(&vm_page_queue_free, mem, pageq);
+
+ cnt.v_free_count++;
+ simple_unlock(&vm_page_queue_free_lock);
+ splx(spl);
+ }
+}
+
+/*
+ * Find first virtual address >= *vap that doesn't cause
+ * a cache alias conflict.
+ */
+void
+pmap_prefer(foff, vap)
+ register vm_offset_t foff;
+ register vm_offset_t *vap;
+{
+ register vm_offset_t va = *vap;
+ register long m, d;
+
+ m = 0x10000; /* Max aliased cache size */
+
+ d = foff - va;
+ d &= (m-1);
+ *vap = va + d;
+}
+
diff --git a/sys/arch/arc/arc/process_machdep.c b/sys/arch/arc/arc/process_machdep.c
new file mode 100644
index 00000000000..6941e7e4ad4
--- /dev/null
+++ b/sys/arch/arc/arc/process_machdep.c
@@ -0,0 +1,114 @@
+/* $OpenBSD: process_machdep.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/*
+ * Copyright (c) 1994 Adam Glass
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1993 Jan-Simon Pendry
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From:
+ * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel
+ *
+ * $Id: process_machdep.c,v 1.1 1996/06/24 09:07:21 pefo Exp $
+ */
+
+/*
+ * This file may seem a bit stylized, but that so that it's easier to port.
+ * Functions to be implemented here are:
+ *
+ * process_read_regs(proc, regs)
+ * Get the current user-visible register set from the process
+ * and copy it into the regs structure (<machine/reg.h>).
+ * The process is stopped at the time read_regs is called.
+ *
+ * process_write_regs(proc, regs)
+ * Update the current register set from the passed in regs
+ * structure. Take care to avoid clobbering special CPU
+ * registers or privileged bits in the PSL.
+ * The process is stopped at the time write_regs is called.
+ *
+ * process_sstep(proc)
+ * Arrange for the process to trap after executing a single instruction.
+ *
+ * process_set_pc(proc)
+ * Set the process's program counter.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/vnode.h>
+#include <sys/ptrace.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+int
+process_read_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
+ bcopy((caddr_t)p->p_md.md_regs, (caddr_t)regs, sizeof(struct reg));
+ return (0);
+}
+
+int
+process_write_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
+ bcopy((caddr_t)regs, (caddr_t)p->p_md.md_regs, sizeof(struct reg));
+/*XXX Clear to user set bits!! */
+ return (0);
+}
+
+int
+process_sstep(p, sstep)
+ struct proc *p;
+{
+ if(sstep)
+ cpu_singlestep(p);
+ return (0);
+}
+
+int
+process_set_pc(p, addr)
+ struct proc *p;
+ caddr_t addr;
+{
+ p->p_md.md_regs[PC] = (int)addr;
+ return (0);
+}
+
diff --git a/sys/arch/arc/arc/swapgeneric.c b/sys/arch/arc/arc/swapgeneric.c
new file mode 100644
index 00000000000..ebba79bfcfb
--- /dev/null
+++ b/sys/arch/arc/arc/swapgeneric.c
@@ -0,0 +1,195 @@
+/* $OpenBSD: swapgeneric.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/* $NetBSD: swapgeneric.c,v 1.3 1995/03/24 15:03:02 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)swapgeneric.c 5.5 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+
+#include <machine/pte.h>
+
+/*
+ * Generic configuration; all in one
+ */
+dev_t rootdev = NODEV;
+dev_t argdev = NODEV;
+dev_t dumpdev = NODEV;
+int nswap;
+struct swdevt swdevt[] = {
+ { NODEV, 1, 0 },
+ { NODEV, 0, 0 },
+};
+long dumplo;
+int dmmin, dmmax, dmtext;
+
+#include "sd.h"
+#if NSD > 0
+extern struct cfdriver sd_cd;
+#endif
+#include "fdc.h"
+#if NFDC > 0
+extern struct cfdriver fd_cd;
+#endif
+
+struct genericconf {
+ struct cfdriver *gc_driver;
+ char *gc_name;
+ dev_t gc_major;
+} genericconf[] = {
+#if NSD > 0
+ { &sd_cd, "sd", 0 },
+#endif
+#if NFDC > 0
+ { &fd_cd, "fd", 7 },
+#endif
+ { 0 }
+};
+
+extern int ffs_mountroot();
+int (*mountroot)() = ffs_mountroot;
+
+setconf()
+{
+ register struct genericconf *gc;
+ int unit, swaponroot = 0;
+
+ if (rootdev != NODEV)
+ goto doswap;
+
+ if (genericconf[0].gc_driver == 0)
+ goto verybad;
+
+ if (boothowto & RB_ASKNAME) {
+ char name[128];
+retry:
+ printf("root device? ");
+ gets(name);
+
+ if (strcmp(name, "halt") == 0)
+ boot(RB_HALT);
+
+ for (gc = genericconf; gc->gc_driver; gc++)
+ if (gc->gc_name[0] == name[0] &&
+ gc->gc_name[1] == name[1])
+ goto gotit;
+ goto bad;
+gotit:
+ if (name[3] == '*') {
+ name[3] = name[4];
+ swaponroot++;
+ }
+ if (name[2] >= '0' && name[2] <= '7' && name[3] == 0) {
+ unit = name[2] - '0';
+ goto found;
+ }
+ printf("bad/missing unit number\n");
+bad:
+ printf("use:\n");
+ for (gc = genericconf; gc->gc_driver; gc++)
+ printf("\t%s%%d\n", gc->gc_name);
+ printf("\thalt\n");
+ goto retry;
+ }
+ unit = 0;
+ for (gc = genericconf; gc->gc_driver; gc++) {
+ if (gc->gc_driver->cd_ndevs > unit &&
+ gc->gc_driver->cd_devs[unit]) {
+ printf("root on %s0\n", gc->gc_name);
+ goto found;
+ }
+ }
+verybad:
+ printf("no suitable root\n");
+ boot(RB_HALT);
+
+found:
+ rootdev = makedev(gc->gc_major, unit * MAXPARTITIONS);
+doswap:
+ swdevt[0].sw_dev = argdev = dumpdev =
+ makedev(major(rootdev), minor(rootdev) + 1);
+ /* swap size and dumplo set during autoconfigure */
+ if (swaponroot)
+ rootdev = dumpdev;
+}
+
+gets(cp)
+ char *cp;
+{
+ register char *lp;
+ register c;
+
+ lp = cp;
+ for (;;) {
+ c = cngetc() & 0177;
+ switch (c) {
+ case '\n':
+ case '\r':
+ cnputc(c);
+ *lp++ = '\0';
+ return;
+ case '\b':
+ case '\177':
+ if (lp > cp) {
+ printf("\b \b");
+ lp--;
+ }
+ continue;
+ case '#':
+ cnputc(c);
+ lp--;
+ if (lp < cp)
+ lp = cp;
+ continue;
+ case '@':
+ case 'u'&037:
+ cnputc(c);
+ cnputc('\n');
+ lp = cp;
+ continue;
+ default:
+ cnputc(c);
+ *lp++ = c;
+ }
+ }
+}
diff --git a/sys/arch/arc/arc/sys_machdep.c b/sys/arch/arc/arc/sys_machdep.c
new file mode 100644
index 00000000000..54a5ef1b15a
--- /dev/null
+++ b/sys/arch/arc/arc/sys_machdep.c
@@ -0,0 +1,130 @@
+/* $OpenBSD: sys_machdep.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/* $NetBSD: sys_machdep.c,v 1.6 1994/10/26 21:10:42 cgd Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sys_machdep.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/mtio.h>
+#include <sys/buf.h>
+#include <sys/trace.h>
+
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
+#ifdef TRACE
+int nvualarm;
+
+vtrace(p, uap, retval)
+ struct proc *p;
+ register struct vtrace_args /* {
+ syscallarg(int) request;
+ syscallarg(int) value;
+ } */ *uap;
+ register_t *retval;
+{
+ int vdoualarm();
+
+ switch (SCARG(uap, request)) {
+
+ case VTR_DISABLE: /* disable a trace point */
+ case VTR_ENABLE: /* enable a trace point */
+ if (SCARG(uap, value) < 0 || SCARG(uap, value) >= TR_NFLAGS)
+ return (EINVAL);
+ *retval = traceflags[SCARG(uap, value)];
+ traceflags[SCARG(uap, value)] = SCARG(uap, request);
+ break;
+
+ case VTR_VALUE: /* return a trace point setting */
+ if (SCARG(uap, value) < 0 || SCARG(uap, value) >= TR_NFLAGS)
+ return (EINVAL);
+ *retval = traceflags[SCARG(uap, value)];
+ break;
+
+ case VTR_UALARM: /* set a real-time ualarm, less than 1 min */
+ if (SCARG(uap, value) <= 0 || SCARG(uap, value) > 60 * hz ||
+ nvualarm > 5)
+ return (EINVAL);
+ nvualarm++;
+ timeout(vdoualarm, (caddr_t)p->p_pid, SCARG(uap, value));
+ break;
+
+ case VTR_STAMP:
+ trace(TR_STAMP, SCARG(uap, value), p->p_pid);
+ break;
+ }
+ return (0);
+}
+
+vdoualarm(arg)
+ int arg;
+{
+ register struct proc *p;
+
+ p = pfind(arg);
+ if (p)
+ psignal(p, 16);
+ nvualarm--;
+}
+#endif
+
+sys_sysarch(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_sysarch_args /* {
+ syscallarg(int) op;
+ syscallarg(char *) parms;
+ } */ *uap = v;
+ int error = 0;
+
+ switch(SCARG(uap, op)) {
+ default:
+ error = EINVAL;
+ break;
+ }
+ return(error);
+}
diff --git a/sys/arch/arc/arc/trap.c b/sys/arch/arc/arc/trap.c
new file mode 100644
index 00000000000..99b6ba53a6f
--- /dev/null
+++ b/sys/arch/arc/arc/trap.c
@@ -0,0 +1,1561 @@
+/* $OpenBSD: trap.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: trap.c 1.32 91/04/06
+ *
+ * from: @(#)trap.c 8.5 (Berkeley) 1/11/94
+ * $Id: trap.c,v 1.1 1996/06/24 09:07:21 pefo Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/kernel.h>
+#include <sys/signalvar.h>
+#include <sys/syscall.h>
+#include <sys/user.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+#include <net/netisr.h>
+
+#include <machine/trap.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/cpu.h>
+#include <machine/pio.h>
+#include <machine/autoconf.h>
+#include <machine/pte.h>
+#include <machine/pmap.h>
+#include <machine/mips_opcode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+
+#include <arc/pica/pica.h>
+
+#include <sys/cdefs.h>
+#include <sys/syslog.h>
+
+struct proc *machFPCurProcPtr; /* pointer to last proc to use FP */
+
+extern void MachKernGenException();
+extern void MachUserGenException();
+extern void MachKernIntr();
+extern void MachUserIntr();
+extern void MachTLBModException();
+extern void MachTLBInvalidException();
+extern unsigned MachEmulateBranch();
+
+void (*machExceptionTable[])() = {
+/*
+ * The kernel exception handlers.
+ */
+ MachKernIntr, /* external interrupt */
+ MachKernGenException, /* TLB modification */
+ MachTLBInvalidException, /* TLB miss (load or instr. fetch) */
+ MachTLBInvalidException, /* TLB miss (store) */
+ MachKernGenException, /* address error (load or I-fetch) */
+ MachKernGenException, /* address error (store) */
+ MachKernGenException, /* bus error (I-fetch) */
+ MachKernGenException, /* bus error (load or store) */
+ MachKernGenException, /* system call */
+ MachKernGenException, /* breakpoint */
+ MachKernGenException, /* reserved instruction */
+ MachKernGenException, /* coprocessor unusable */
+ MachKernGenException, /* arithmetic overflow */
+ MachKernGenException, /* trap exception */
+ MachKernGenException, /* viritual coherence exception inst */
+ MachKernGenException, /* floating point exception */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* watch exception */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* reserved */
+ MachKernGenException, /* viritual coherence exception data */
+/*
+ * The user exception handlers.
+ */
+ MachUserIntr, /* 0 */
+ MachUserGenException, /* 1 */
+ MachUserGenException, /* 2 */
+ MachUserGenException, /* 3 */
+ MachUserGenException, /* 4 */
+ MachUserGenException, /* 5 */
+ MachUserGenException, /* 6 */
+ MachUserGenException, /* 7 */
+ MachUserGenException, /* 8 */
+ MachUserGenException, /* 9 */
+ MachUserGenException, /* 10 */
+ MachUserGenException, /* 11 */
+ MachUserGenException, /* 12 */
+ MachUserGenException, /* 13 */
+ MachUserGenException, /* 14 */
+ MachUserGenException, /* 15 */
+ MachUserGenException, /* 16 */
+ MachUserGenException, /* 17 */
+ MachUserGenException, /* 18 */
+ MachUserGenException, /* 19 */
+ MachUserGenException, /* 20 */
+ MachUserGenException, /* 21 */
+ MachUserGenException, /* 22 */
+ MachUserGenException, /* 23 */
+ MachUserGenException, /* 24 */
+ MachUserGenException, /* 25 */
+ MachUserGenException, /* 26 */
+ MachUserGenException, /* 27 */
+ MachUserGenException, /* 28 */
+ MachUserGenException, /* 29 */
+ MachUserGenException, /* 20 */
+ MachUserGenException, /* 31 */
+};
+
+char *trap_type[] = {
+ "external interrupt",
+ "TLB modification",
+ "TLB miss (load or instr. fetch)",
+ "TLB miss (store)",
+ "address error (load or I-fetch)",
+ "address error (store)",
+ "bus error (I-fetch)",
+ "bus error (load or store)",
+ "system call",
+ "breakpoint",
+ "reserved instruction",
+ "coprocessor unusable",
+ "arithmetic overflow",
+ "trap",
+ "viritual coherency instruction",
+ "floating point",
+ "reserved 16",
+ "reserved 17",
+ "reserved 18",
+ "reserved 19",
+ "reserved 20",
+ "reserved 21",
+ "reserved 22",
+ "watch",
+ "reserved 24",
+ "reserved 25",
+ "reserved 26",
+ "reserved 27",
+ "reserved 28",
+ "reserved 29",
+ "reserved 30",
+ "viritual coherency data",
+};
+
+struct {
+ int int_mask;
+ int (*int_hand)();
+} cpu_int_tab[8];
+
+int cpu_int_mask; /* External cpu interrupt mask */
+
+#ifdef DEBUG
+#define TRAPSIZE 10
+struct trapdebug { /* trap history buffer for debugging */
+ u_int status;
+ u_int cause;
+ u_int vadr;
+ u_int pc;
+ u_int ra;
+ u_int sp;
+ u_int code;
+} trapdebug[TRAPSIZE], *trp = trapdebug;
+#endif /* DEBUG */
+
+#ifdef DEBUG /* stack trace code, also useful for DDB one day */
+extern void stacktrace();
+extern void logstacktrace();
+
+/* extern functions printed by name in stack backtraces */
+extern void idle(), cpu_switch(), splx(), wbflush();
+extern void MachTLBMiss();
+#endif /* DEBUG */
+
+static void arc_errintr();
+extern const struct callback *callv;
+extern volatile struct chiptime *Mach_clock_addr;
+extern u_long intrcnt[];
+
+/*
+ * Handle an exception.
+ * Called from MachKernGenException() or MachUserGenException()
+ * when a processor trap occurs.
+ * In the case of a kernel trap, we return the pc where to resume if
+ * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc.
+ */
+unsigned
+trap(statusReg, causeReg, vadr, pc, args)
+ unsigned statusReg; /* status register at time of the exception */
+ unsigned causeReg; /* cause register at time of exception */
+ unsigned vadr; /* address (if any) the fault occured on */
+ unsigned pc; /* program counter where to continue */
+{
+ register int type, i;
+ unsigned ucode = 0;
+ register struct proc *p = curproc;
+ u_quad_t sticks;
+ vm_prot_t ftype;
+ extern unsigned onfault_table[];
+
+#ifdef DEBUG
+ trp->status = statusReg;
+ trp->cause = causeReg;
+ trp->vadr = vadr;
+ trp->pc = pc;
+ trp->ra = !USERMODE(statusReg) ? ((int *)&args)[19] :
+ p->p_md.md_regs[RA];
+ trp->sp = (int)&args;
+ trp->code = 0;
+ if (++trp == &trapdebug[TRAPSIZE])
+ trp = trapdebug;
+#endif
+
+ cnt.v_trap++;
+ type = (causeReg & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
+ if (USERMODE(statusReg)) {
+ type |= T_USER;
+ sticks = p->p_sticks;
+ }
+
+ /*
+ * Enable hardware interrupts if they were on before.
+ * We only respond to software interrupts when returning to user mode.
+ */
+ if (statusReg & SR_INT_ENAB)
+ splx((statusReg & HARD_INT_MASK) | SR_INT_ENAB);
+
+ switch (type) {
+ case T_TLB_MOD:
+ /* check for kernel address */
+ if ((int)vadr < 0) {
+ register pt_entry_t *pte;
+ register unsigned entry;
+ register vm_offset_t pa;
+
+ pte = kvtopte(vadr);
+ entry = pte->pt_entry;
+#ifdef DIAGNOSTIC
+ if (!(entry & PG_V) || (entry & PG_M))
+ panic("trap: ktlbmod: invalid pte");
+#endif
+ if (pmap_is_page_ro(pmap_kernel(), pica_trunc_page(vadr), entry)) {
+ /* write to read only page in the kernel */
+ ftype = VM_PROT_WRITE;
+ goto kernel_fault;
+ }
+ entry |= PG_M;
+ pte->pt_entry = entry;
+ vadr &= ~PGOFSET;
+ MachTLBUpdate(vadr, entry);
+ pa = pfn_to_vad(entry);
+#ifdef ATTR
+ pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
+#else
+ if (!IS_VM_PHYSADDR(pa))
+ panic("trap: ktlbmod: unmanaged page");
+ PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
+#endif
+ return (pc);
+ }
+ /* FALLTHROUGH */
+
+ case T_TLB_MOD+T_USER:
+ {
+ register pt_entry_t *pte;
+ register unsigned entry;
+ register vm_offset_t pa;
+ pmap_t pmap = &p->p_vmspace->vm_pmap;
+
+ if (!(pte = pmap_segmap(pmap, vadr)))
+ panic("trap: utlbmod: invalid segmap");
+ pte += (vadr >> PGSHIFT) & (NPTEPG - 1);
+ entry = pte->pt_entry;
+#ifdef DIAGNOSTIC
+ if (!(entry & PG_V) || (entry & PG_M)) {
+ panic("trap: utlbmod: invalid pte");
+ }
+#endif
+ if (pmap_is_page_ro(pmap, pica_trunc_page(vadr), entry)) {
+ /* write to read only page */
+ ftype = VM_PROT_WRITE;
+ goto dofault;
+ }
+ entry |= PG_M;
+ pte->pt_entry = entry;
+ vadr = (vadr & ~PGOFSET) |
+ (pmap->pm_tlbpid << VMTLB_PID_SHIFT);
+ MachTLBUpdate(vadr, entry);
+ pa = pfn_to_vad(entry);
+#ifdef ATTR
+ pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
+#else
+ if (!IS_VM_PHYSADDR(pa)) {
+ panic("trap: utlbmod: unmanaged page");
+ }
+ PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
+#endif
+ if (!USERMODE(statusReg))
+ return (pc);
+ goto out;
+ }
+
+ case T_TLB_LD_MISS:
+ case T_TLB_ST_MISS:
+ ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
+ /* check for kernel address */
+ if ((int)vadr < 0) {
+ register vm_offset_t va;
+ int rv;
+
+ kernel_fault:
+ va = trunc_page((vm_offset_t)vadr);
+ rv = vm_fault(kernel_map, va, ftype, FALSE);
+ if (rv == KERN_SUCCESS)
+ return (pc);
+ if (i = ((struct pcb *)UADDR)->pcb_onfault) {
+ ((struct pcb *)UADDR)->pcb_onfault = 0;
+ return (onfault_table[i]);
+ }
+ goto err;
+ }
+ /*
+ * It is an error for the kernel to access user space except
+ * through the copyin/copyout routines.
+ */
+ if ((i = ((struct pcb *)UADDR)->pcb_onfault) == 0)
+ goto err;
+ /* check for fuswintr() or suswintr() getting a page fault */
+ if (i == 4)
+ return (onfault_table[i]);
+ goto dofault;
+
+ case T_TLB_LD_MISS+T_USER:
+ ftype = VM_PROT_READ;
+ goto dofault;
+
+ case T_TLB_ST_MISS+T_USER:
+ ftype = VM_PROT_WRITE;
+ dofault:
+ {
+ register vm_offset_t va;
+ register struct vmspace *vm;
+ register vm_map_t map;
+ int rv;
+
+ vm = p->p_vmspace;
+ map = &vm->vm_map;
+ va = trunc_page((vm_offset_t)vadr);
+ rv = vm_fault(map, va, ftype, FALSE);
+#ifdef VMFAULT_TRACE
+ printf("vm_fault(%x (pmap %x), %x (%x), %x, %d) -> %x at pc %x\n",
+ map, &vm->vm_pmap, va, vadr, ftype, FALSE, rv, pc);
+#endif
+ /*
+ * If this was a stack access we keep track of the maximum
+ * accessed stack size. Also, if vm_fault gets a protection
+ * failure it is due to accessing the stack region outside
+ * the current limit and we need to reflect that as an access
+ * error.
+ */
+ if ((caddr_t)va >= vm->vm_maxsaddr) {
+ if (rv == KERN_SUCCESS) {
+ unsigned nss;
+
+ nss = clrnd(btoc(USRSTACK-(unsigned)va));
+ if (nss > vm->vm_ssize)
+ vm->vm_ssize = nss;
+ } else if (rv == KERN_PROTECTION_FAILURE)
+ rv = KERN_INVALID_ADDRESS;
+ }
+ if (rv == KERN_SUCCESS) {
+ if (!USERMODE(statusReg))
+ return (pc);
+ goto out;
+ }
+ if (!USERMODE(statusReg)) {
+ if (i = ((struct pcb *)UADDR)->pcb_onfault) {
+ ((struct pcb *)UADDR)->pcb_onfault = 0;
+ return (onfault_table[i]);
+ }
+ goto err;
+ }
+ ucode = vadr;
+ i = SIGSEGV;
+ break;
+ }
+
+ case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */
+ case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */
+ case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to cpu */
+ case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to cpu */
+ i = SIGBUS;
+ break;
+
+ case T_SYSCALL+T_USER:
+ {
+ register int *locr0 = p->p_md.md_regs;
+ register struct sysent *callp;
+ unsigned int code;
+ int numsys;
+ struct args {
+ int i[8];
+ } args;
+ int rval[2];
+
+ cnt.v_syscall++;
+ /* compute next PC after syscall instruction */
+ if ((int)causeReg < 0)
+ locr0[PC] = MachEmulateBranch(locr0, pc, 0, 0);
+ else
+ locr0[PC] += 4;
+ callp = p->p_emul->e_sysent;
+ numsys = p->p_emul->e_nsysent;
+ code = locr0[V0];
+ switch (code) {
+ case SYS_syscall:
+ /*
+ * Code is first argument, followed by actual args.
+ */
+ code = locr0[A0];
+ if (code >= numsys)
+ callp += p->p_emul->e_nosys; /* (illegal) */
+ else
+ callp += code;
+ i = callp->sy_argsize / sizeof(int);
+ args.i[0] = locr0[A1];
+ args.i[1] = locr0[A2];
+ args.i[2] = locr0[A3];
+ if (i > 3) {
+ i = copyin((caddr_t)(locr0[SP] +
+ 4 * sizeof(int)),
+ (caddr_t)&args.i[3],
+ (u_int)(i - 3) * sizeof(int));
+ if (i) {
+ locr0[V0] = i;
+ locr0[A3] = 1;
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, args.i);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code,
+ callp->sy_argsize,
+ args.i);
+#endif
+ goto done;
+ }
+ }
+ break;
+
+ case SYS___syscall:
+ /*
+ * Like syscall, but code is a quad, so as to maintain
+ * quad alignment for the rest of the arguments.
+ */
+ code = locr0[A0 + _QUAD_LOWWORD];
+ if (code >= numsys)
+ callp += p->p_emul->e_nosys; /* (illegal) */
+ else
+ callp += code;
+ i = callp->sy_argsize / sizeof(int);
+ args.i[0] = locr0[A2];
+ args.i[1] = locr0[A3];
+ if (i > 2) {
+ i = copyin((caddr_t)(locr0[SP] +
+ 4 * sizeof(int)),
+ (caddr_t)&args.i[2],
+ (u_int)(i - 2) * sizeof(int));
+ if (i) {
+ locr0[V0] = i;
+ locr0[A3] = 1;
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, args.i);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code,
+ callp->sy_argsize,
+ args.i);
+#endif
+ goto done;
+ }
+ }
+ break;
+
+ default:
+ if (code >= numsys)
+ callp += p->p_emul->e_nosys; /* (illegal) */
+ else
+ callp += code;
+ i = callp->sy_narg;
+ args.i[0] = locr0[A0];
+ args.i[1] = locr0[A1];
+ args.i[2] = locr0[A2];
+ args.i[3] = locr0[A3];
+ if (i > 4) {
+ i = copyin((caddr_t)(locr0[SP] +
+ 4 * sizeof(int)),
+ (caddr_t)&args.i[4],
+ (u_int)(i - 4) * sizeof(int));
+ if (i) {
+ locr0[V0] = i;
+ locr0[A3] = 1;
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, args.i);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code,
+ callp->sy_argsize,
+ args.i);
+#endif
+ goto done;
+ }
+ }
+ }
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, args.i);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code, callp->sy_argsize, args.i);
+#endif
+ rval[0] = 0;
+ rval[1] = locr0[V1];
+#ifdef DEBUG
+ if (trp == trapdebug)
+ trapdebug[TRAPSIZE - 1].code = code;
+ else
+ trp[-1].code = code;
+#endif
+ i = (*callp->sy_call)(p, &args, rval);
+ /*
+ * Reinitialize proc pointer `p' as it may be different
+ * if this is a child returning from fork syscall.
+ */
+ p = curproc;
+ locr0 = p->p_md.md_regs;
+#ifdef DEBUG
+ { int s;
+ s = splhigh();
+ trp->status = statusReg;
+ trp->cause = causeReg;
+ trp->vadr = locr0[SP];
+ trp->pc = locr0[PC];
+ trp->ra = locr0[RA];
+ trp->code = -code;
+ if (++trp == &trapdebug[TRAPSIZE])
+ trp = trapdebug;
+ splx(s);
+ }
+#endif
+ switch (i) {
+ case 0:
+ locr0[V0] = rval[0];
+ locr0[V1] = rval[1];
+ locr0[A3] = 0;
+ break;
+
+ case ERESTART:
+ locr0[PC] = pc;
+ break;
+
+ case EJUSTRETURN:
+ break; /* nothing to do */
+
+ default:
+ locr0[V0] = i;
+ locr0[A3] = 1;
+ }
+ if(code == SYS_ptrace)
+ MachFlushCache();
+ done:
+#ifdef SYSCALL_DEBUG
+ scdebug_ret(p, code, i, rval);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET))
+ ktrsysret(p->p_tracep, code, i, rval[0]);
+#endif
+ goto out;
+ }
+
+ case T_BREAK+T_USER:
+ {
+ register unsigned va, instr;
+ struct uio uio;
+ struct iovec iov;
+
+ /* compute address of break instruction */
+ va = pc;
+ if ((int)causeReg < 0)
+ va += 4;
+
+ /* read break instruction */
+ instr = fuiword((caddr_t)va);
+#if 0
+ printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
+ p->p_comm, p->p_pid, instr, pc,
+ p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
+#endif
+ if (p->p_md.md_ss_addr != va || instr != BREAK_SSTEP) {
+ i = SIGTRAP;
+ break;
+ }
+
+ /*
+ * Restore original instruction and clear BP
+ */
+ iov.iov_base = (caddr_t)&p->p_md.md_ss_instr;
+ iov.iov_len = sizeof(int);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = (off_t)va;
+ uio.uio_resid = sizeof(int);
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_WRITE;
+ uio.uio_procp = curproc;
+ i = procfs_domem(p, p, NULL, &uio);
+ MachFlushCache();
+
+ if (i < 0)
+ printf("Warning: can't restore instruction at %x: %x\n",
+ p->p_md.md_ss_addr, p->p_md.md_ss_instr);
+
+ p->p_md.md_ss_addr = 0;
+ i = SIGTRAP;
+ break;
+ }
+
+ case T_RES_INST+T_USER:
+ i = SIGILL;
+ break;
+
+ case T_COP_UNUSABLE+T_USER:
+ if ((causeReg & CR_COP_ERR) != 0x10000000) {
+ i = SIGILL; /* only FPU instructions allowed */
+ break;
+ }
+ MachSwitchFPState(machFPCurProcPtr, p->p_md.md_regs);
+ machFPCurProcPtr = p;
+ p->p_md.md_regs[PS] |= SR_COP_1_BIT;
+ p->p_md.md_flags |= MDP_FPUSED;
+ goto out;
+
+ case T_FPE:
+#ifdef DEBUG
+ trapDump("fpintr");
+#else
+ printf("FPU Trap: PC %x CR %x SR %x\n",
+ pc, causeReg, statusReg);
+ goto err;
+#endif
+
+ case T_FPE+T_USER:
+ MachFPTrap(statusReg, causeReg, pc);
+ goto out;
+
+ case T_OVFLOW+T_USER:
+ i = SIGFPE;
+ break;
+
+ case T_ADDR_ERR_LD: /* misaligned access */
+ case T_ADDR_ERR_ST: /* misaligned access */
+ case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
+ if (i = ((struct pcb *)UADDR)->pcb_onfault) {
+ ((struct pcb *)UADDR)->pcb_onfault = 0;
+ return (onfault_table[i]);
+ }
+ /* FALLTHROUGH */
+
+ default:
+ err:
+#ifdef DEBUG
+ {
+ extern struct pcb mdbpcb;
+
+ if (USERMODE(statusReg))
+ mdbpcb = p->p_addr->u_pcb;
+ else {
+ mdbpcb.pcb_regs[ZERO] = 0;
+ mdbpcb.pcb_regs[AST] = ((int *)&args)[2];
+ mdbpcb.pcb_regs[V0] = ((int *)&args)[3];
+ mdbpcb.pcb_regs[V1] = ((int *)&args)[4];
+ mdbpcb.pcb_regs[A0] = ((int *)&args)[5];
+ mdbpcb.pcb_regs[A1] = ((int *)&args)[6];
+ mdbpcb.pcb_regs[A2] = ((int *)&args)[7];
+ mdbpcb.pcb_regs[A3] = ((int *)&args)[8];
+ mdbpcb.pcb_regs[T0] = ((int *)&args)[9];
+ mdbpcb.pcb_regs[T1] = ((int *)&args)[10];
+ mdbpcb.pcb_regs[T2] = ((int *)&args)[11];
+ mdbpcb.pcb_regs[T3] = ((int *)&args)[12];
+ mdbpcb.pcb_regs[T4] = ((int *)&args)[13];
+ mdbpcb.pcb_regs[T5] = ((int *)&args)[14];
+ mdbpcb.pcb_regs[T6] = ((int *)&args)[15];
+ mdbpcb.pcb_regs[T7] = ((int *)&args)[16];
+ mdbpcb.pcb_regs[T8] = ((int *)&args)[17];
+ mdbpcb.pcb_regs[T9] = ((int *)&args)[18];
+ mdbpcb.pcb_regs[RA] = ((int *)&args)[19];
+ mdbpcb.pcb_regs[MULLO] = ((int *)&args)[21];
+ mdbpcb.pcb_regs[MULHI] = ((int *)&args)[22];
+ mdbpcb.pcb_regs[PC] = pc;
+ mdbpcb.pcb_regs[SR] = statusReg;
+ bzero((caddr_t)&mdbpcb.pcb_regs[F0], 33 * sizeof(int));
+ }
+ if (mdb(causeReg, vadr, p, !USERMODE(statusReg)))
+ return (mdbpcb.pcb_regs[PC]);
+ }
+#else
+#ifdef DEBUG
+ stacktrace();
+ trapDump("trap");
+#endif
+#endif
+ panic("trap");
+ }
+ p->p_md.md_regs[PC] = pc;
+ p->p_md.md_regs[CAUSE] = causeReg;
+ p->p_md.md_regs[BADVADDR] = vadr;
+ trapsignal(p, i, ucode);
+out:
+ /*
+ * Note: we should only get here if returning to user mode.
+ */
+ /* take pending signals */
+ while ((i = CURSIG(p)) != 0)
+ postsig(i);
+ p->p_priority = p->p_usrpri;
+ astpending = 0;
+ if (want_resched) {
+ int s;
+
+ /*
+ * Since we are curproc, clock will normally just change
+ * our priority without moving us from one queue to another
+ * (since the running process is not on a queue.)
+ * If that happened after we put ourselves on the run queue
+ * but before we switched, we might not be on the queue
+ * indicated by our priority.
+ */
+ s = splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nivcsw++;
+ mi_switch();
+ splx(s);
+ while ((i = CURSIG(p)) != 0)
+ postsig(i);
+ }
+
+ /*
+ * If profiling, charge system time to the trapped pc.
+ */
+ if (p->p_flag & P_PROFIL) {
+ extern int psratio;
+
+ addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);
+ }
+
+ curpriority = p->p_priority;
+ return (pc);
+}
+
+/*
+ * Handle an interrupt.
+ * Called from MachKernIntr() or MachUserIntr()
+ * Note: curproc might be NULL.
+ */
+interrupt(statusReg, causeReg, pc, what, args)
+ unsigned statusReg; /* status register at time of the exception */
+ unsigned causeReg; /* cause register at time of exception */
+ unsigned pc; /* program counter where to continue */
+{
+ register unsigned mask;
+ register int i;
+ struct clockframe cf;
+
+#ifdef DEBUG
+ trp->status = statusReg;
+ trp->cause = causeReg;
+ trp->vadr = 0;
+ trp->pc = pc;
+ trp->ra = 0;
+ trp->sp = (int)&args;
+ trp->code = 0;
+ if (++trp == &trapdebug[TRAPSIZE])
+ trp = trapdebug;
+#endif
+
+ cnt.v_intr++;
+ mask = causeReg & statusReg; /* pending interrupts & enable mask */
+
+ /*
+ * Check off all enabled interrupts. Called interrupt routine
+ * returns mask of interrupts to reenable.
+ */
+ for(i = 0; i < 5; i++) {
+ if(cpu_int_tab[i].int_mask & mask) {
+ causeReg &= (*cpu_int_tab[i].int_hand)(mask, pc, statusReg, causeReg);
+ }
+ }
+ /*
+ * Reenable all non served hardware levels.
+ */
+ splx((statusReg & ~causeReg & HARD_INT_MASK) | SR_INT_ENAB);
+
+
+ if (mask & SOFT_INT_MASK_0) {
+ clearsoftclock();
+ cnt.v_soft++;
+ softclock();
+ }
+ /*
+ * Process network interrupt if we trapped or will very soon
+ */
+ if ((mask & SOFT_INT_MASK_1) ||
+ netisr && (statusReg & SOFT_INT_MASK_1)) {
+ clearsoftnet();
+ cnt.v_soft++;
+ intrcnt[1]++;
+#ifdef INET
+ if (netisr & (1 << NETISR_ARP)) {
+ netisr &= ~(1 << NETISR_ARP);
+ arpintr();
+ }
+ if (netisr & (1 << NETISR_IP)) {
+ netisr &= ~(1 << NETISR_IP);
+ ipintr();
+ }
+#endif
+#ifdef NS
+ if (netisr & (1 << NETISR_NS)) {
+ netisr &= ~(1 << NETISR_NS);
+ nsintr();
+ }
+#endif
+#ifdef ISO
+ if (netisr & (1 << NETISR_ISO)) {
+ netisr &= ~(1 << NETISR_ISO);
+ clnlintr();
+ }
+#endif
+#include "ppp.h"
+#if NPPP > 0
+ if(netisr & (1 << NETISR_PPP)) {
+ netisr &= ~(1 << NETISR_PPP);
+ pppintr();
+ }
+#endif
+ }
+ if (mask & SOFT_INT_MASK_0) {
+ clearsoftclock();
+ intrcnt[0]++;
+ cnt.v_soft++;
+ softclock();
+ }
+}
+
+
+set_intr(mask, int_hand, prio)
+ int mask;
+ int (*int_hand)();
+ int prio;
+{
+ if(prio > 4)
+ panic("set_intr: to high priority");
+
+ if(cpu_int_tab[prio].int_mask != 0)
+ panic("set_intr: int already set");
+
+ cpu_int_tab[prio].int_hand = int_hand;
+ cpu_int_tab[prio].int_mask = mask;
+ cpu_int_mask |= mask >> 10;
+
+ /*
+ * Update external interrupt mask but don't enable clock.
+ */
+ out32(PICA_SYS_EXT_IMASK, cpu_int_mask & (~INT_MASK_4 >> 10));
+}
+
+/*
+ * This is called from MachUserIntr() if astpending is set.
+ * This is very similar to the tail of trap().
+ */
+softintr(statusReg, pc)
+ unsigned statusReg; /* status register at time of the exception */
+ unsigned pc; /* program counter where to continue */
+{
+ register struct proc *p = curproc;
+ int sig;
+
+ cnt.v_soft++;
+ /* take pending signals */
+ while ((sig = CURSIG(p)) != 0)
+ postsig(sig);
+ p->p_priority = p->p_usrpri;
+ astpending = 0;
+ if (p->p_flag & P_OWEUPC) {
+ p->p_flag &= ~P_OWEUPC;
+ ADDUPROF(p);
+ }
+ if (want_resched) {
+ int s;
+
+ /*
+ * Since we are curproc, clock will normally just change
+ * our priority without moving us from one queue to another
+ * (since the running process is not on a queue.)
+ * If that happened after we put ourselves on the run queue
+ * but before we switched, we might not be on the queue
+ * indicated by our priority.
+ */
+ s = splstatclock();
+ setrunqueue(p);
+ p->p_stats->p_ru.ru_nivcsw++;
+ mi_switch();
+ splx(s);
+ while ((sig = CURSIG(p)) != 0)
+ postsig(sig);
+ }
+ curpriority = p->p_priority;
+}
+
+#ifdef DEBUG
+trapDump(msg)
+ char *msg;
+{
+ register int i;
+ int s;
+
+ s = splhigh();
+ printf("trapDump(%s)\n", msg);
+ for (i = 0; i < TRAPSIZE; i++) {
+ if (trp == trapdebug)
+ trp = &trapdebug[TRAPSIZE - 1];
+ else
+ trp--;
+ if (trp->cause == 0)
+ break;
+ printf("%s: ADR %x PC %x CR %x SR %x\n",
+ trap_type[(trp->cause & CR_EXC_CODE) >>
+ CR_EXC_CODE_SHIFT],
+ trp->vadr, trp->pc, trp->cause, trp->status);
+ printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code);
+ }
+ splx(s);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MemErrorInterrupts --
+ * arc_errintr - for the ACER PICA_61
+ *
+ * Handler an interrupt for the control register.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+arc_errintr()
+{
+#if 0
+ volatile u_short *sysCSRPtr =
+ (u_short *)PHYS_TO_UNCACHED(KN01_SYS_CSR);
+ u_short csr;
+
+ csr = *sysCSRPtr;
+
+ if (csr & KN01_CSR_MERR) {
+ printf("Memory error at 0x%x\n",
+ *(unsigned *)PHYS_TO_UNCACHED(KN01_SYS_ERRADR));
+ panic("Mem error interrupt");
+ }
+ *sysCSRPtr = (csr & ~KN01_CSR_MBZ) | 0xff;
+#endif
+}
+
+
+/*
+ * Return the resulting PC as if the branch was executed.
+ */
+unsigned
+MachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch)
+ unsigned *regsPtr;
+ unsigned instPC;
+ unsigned fpcCSR;
+ int allowNonBranch;
+{
+ InstFmt inst;
+ unsigned retAddr;
+ int condition;
+
+#define GetBranchDest(InstPtr, inst) \
+ ((unsigned)InstPtr + 4 + ((short)inst.IType.imm << 2))
+
+
+ if(allowNonBranch == 0) {
+ inst = *(InstFmt *)instPC;
+ }
+ else {
+ inst = *(InstFmt *)&allowNonBranch;
+ }
+#if 0
+ printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,
+ inst.word, fpcCSR); /* XXX */
+#endif
+ switch ((int)inst.JType.op) {
+ case OP_SPECIAL:
+ switch ((int)inst.RType.func) {
+ case OP_JR:
+ case OP_JALR:
+ retAddr = regsPtr[inst.RType.rs];
+ break;
+
+ default:
+ if (!allowNonBranch)
+ panic("MachEmulateBranch: Non-branch");
+ retAddr = instPC + 4;
+ break;
+ }
+ break;
+
+ case OP_BCOND:
+ switch ((int)inst.IType.rt) {
+ case OP_BLTZ:
+ case OP_BLTZL:
+ case OP_BLTZAL:
+ case OP_BLTZALL:
+ if ((int)(regsPtr[inst.RType.rs]) < 0)
+ retAddr = GetBranchDest(instPC, inst);
+ else
+ retAddr = instPC + 8;
+ break;
+
+ case OP_BGEZ:
+ case OP_BGEZL:
+ case OP_BGEZAL:
+ case OP_BGEZALL:
+ if ((int)(regsPtr[inst.RType.rs]) >= 0)
+ retAddr = GetBranchDest(instPC, inst);
+ else
+ retAddr = instPC + 8;
+ break;
+
+ default:
+ panic("MachEmulateBranch: Bad branch cond");
+ }
+ break;
+
+ case OP_J:
+ case OP_JAL:
+ retAddr = (inst.JType.target << 2) |
+ ((unsigned)instPC & 0xF0000000);
+ break;
+
+ case OP_BEQ:
+ case OP_BEQL:
+ if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
+ retAddr = GetBranchDest(instPC, inst);
+ else
+ retAddr = instPC + 8;
+ break;
+
+ case OP_BNE:
+ case OP_BNEL:
+ if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
+ retAddr = GetBranchDest(instPC, inst);
+ else
+ retAddr = instPC + 8;
+ break;
+
+ case OP_BLEZ:
+ case OP_BLEZL:
+ if ((int)(regsPtr[inst.RType.rs]) <= 0)
+ retAddr = GetBranchDest(instPC, inst);
+ else
+ retAddr = instPC + 8;
+ break;
+
+ case OP_BGTZ:
+ case OP_BGTZL:
+ if ((int)(regsPtr[inst.RType.rs]) > 0)
+ retAddr = GetBranchDest(instPC, inst);
+ else
+ retAddr = instPC + 8;
+ break;
+
+ case OP_COP1:
+ switch (inst.RType.rs) {
+ case OP_BCx:
+ case OP_BCy:
+ if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
+ condition = fpcCSR & FPC_COND_BIT;
+ else
+ condition = !(fpcCSR & FPC_COND_BIT);
+ if (condition)
+ retAddr = GetBranchDest(instPC, inst);
+ else
+ retAddr = instPC + 8;
+ break;
+
+ default:
+ if (!allowNonBranch)
+ panic("MachEmulateBranch: Bad coproc branch instruction");
+ retAddr = instPC + 4;
+ }
+ break;
+
+ default:
+ if (!allowNonBranch)
+ panic("MachEmulateBranch: Non-branch instruction");
+ retAddr = instPC + 4;
+ }
+#if 0
+ printf("Target addr=%x\n", retAddr); /* XXX */
+#endif
+ return (retAddr);
+}
+
+/*
+ * This routine is called by procxmt() to single step one instruction.
+ * We do this by storing a break instruction after the current instruction,
+ * resuming execution, and then restoring the old instruction.
+ */
+cpu_singlestep(p)
+ register struct proc *p;
+{
+ register unsigned va;
+ register int *locr0 = p->p_md.md_regs;
+ int i;
+ int bpinstr = BREAK_SSTEP;
+ int curinstr;
+ struct uio uio;
+ struct iovec iov;
+
+ /*
+ * Fetch what's at the current location.
+ */
+ iov.iov_base = (caddr_t)&curinstr;
+ iov.iov_len = sizeof(int);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = (off_t)locr0[PC];
+ uio.uio_resid = sizeof(int);
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_procp = curproc;
+ procfs_domem(curproc, p, NULL, &uio);
+
+ /* compute next address after current location */
+ if(curinstr != 0) {
+ va = MachEmulateBranch(locr0, locr0[PC], locr0[FSR], curinstr);
+ }
+ else {
+ va = locr0[PC] + 4;
+ }
+ if (p->p_md.md_ss_addr) {
+ printf("SS %s (%d): breakpoint already set at %x (va %x)\n",
+ p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */
+ return (EFAULT);
+ }
+ p->p_md.md_ss_addr = va;
+ /*
+ * Fetch what's at the current location.
+ */
+ iov.iov_base = (caddr_t)&p->p_md.md_ss_instr;
+ iov.iov_len = sizeof(int);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = (off_t)va;
+ uio.uio_resid = sizeof(int);
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_procp = curproc;
+ procfs_domem(curproc, p, NULL, &uio);
+
+ /*
+ * Store breakpoint instruction at the "next" location now.
+ */
+ iov.iov_base = (caddr_t)&bpinstr;
+ iov.iov_len = sizeof(int);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = (off_t)va;
+ uio.uio_resid = sizeof(int);
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_WRITE;
+ uio.uio_procp = curproc;
+ i = procfs_domem(curproc, p, NULL, &uio);
+ MachFlushCache();
+
+ if (i < 0)
+ return (EFAULT);
+#if 0
+ printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
+ p->p_comm, p->p_pid, p->p_md.md_ss_addr,
+ p->p_md.md_ss_instr, locr0[PC], curinstr); /* XXX */
+#endif
+ return (0);
+}
+
+#ifdef DEBUG
+kdbpeek(addr)
+{
+ if (addr & 3) {
+ printf("kdbpeek: unaligned address %x\n", addr);
+ return (-1);
+ }
+ return (*(int *)addr);
+}
+#endif
+
+#ifdef DEBUG
+#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
+
+/* forward */
+char *fn_name(unsigned addr);
+void stacktrace_subr __P((int, int, int, int, void (*)(const char*, ...)));
+
+/*
+ * Print a stack backtrace.
+ */
+void
+stacktrace(a0, a1, a2, a3)
+ int a0, a1, a2, a3;
+{
+ stacktrace_subr(a0, a1, a2, a3, printf);
+}
+
+void
+logstacktrace(a0, a1, a2, a3)
+ int a0, a1, a2, a3;
+{
+ stacktrace_subr(a0, a1, a2, a3, addlog);
+}
+
+void
+stacktrace_subr(a0, a1, a2, a3, printfn)
+ int a0, a1, a2, a3;
+ void (*printfn) __P((const char*, ...));
+{
+ unsigned pc, sp, fp, ra, va, subr;
+ unsigned instr, mask;
+ InstFmt i;
+ int more, stksize;
+ int regs[3];
+ extern setsoftclock();
+ extern char start[], edata[];
+ unsigned int frames = 0;
+
+ cpu_getregs(regs);
+
+ /* get initial values from the exception frame */
+ sp = regs[0];
+ pc = regs[1];
+ ra = 0;
+ fp = regs[2];
+
+/* Jump here when done with a frame, to start a new one */
+loop:
+ ra = 0;
+
+/* Jump here after a nonstandard (interrupt handler) frame */
+specialframe:
+ stksize = 0;
+ subr = 0;
+ if (frames++ > 100) {
+ (*printfn)("\nstackframe count exceeded\n");
+ /* return breaks stackframe-size heuristics with gcc -O2 */
+ goto finish; /*XXX*/
+ }
+
+ /* check for bad SP: could foul up next frame */
+ if (sp & 3 || sp < 0x80000000) {
+ (*printfn)("SP 0x%x: not in kernel\n", sp);
+ ra = 0;
+ subr = 0;
+ goto done;
+ }
+
+ /* Backtraces should contine through interrupts from kernel mode */
+ if (pc >= (unsigned)MachKernIntr && pc < (unsigned)MachUserIntr) {
+ /* NOTE: the offsets depend on the code in locore.s */
+ (*printfn)("MachKernIntr+%x: (%x, %x ,%x) -------\n",
+ pc-(unsigned)MachKernIntr, a0, a1, a2);
+ a0 = kdbpeek(sp + 36);
+ a1 = kdbpeek(sp + 40);
+ a2 = kdbpeek(sp + 44);
+ a3 = kdbpeek(sp + 48);
+
+ pc = kdbpeek(sp + 20); /* exc_pc - pc at time of exception */
+ ra = kdbpeek(sp + 92); /* ra at time of exception */
+ sp = sp + 108;
+ goto specialframe;
+ }
+
+
+# define Between(x, y, z) \
+ ( ((x) <= (y)) && ((y) < (z)) )
+# define pcBetween(a,b) \
+ Between((unsigned)a, pc, (unsigned)b)
+
+ /*
+ * Check for current PC in exception handler code that don't
+ * have a preceding "j ra" at the tail of the preceding function.
+ * Depends on relative ordering of functions in locore.
+ */
+ if (pcBetween(MachKernGenException, MachUserGenException))
+ subr = (unsigned) MachKernGenException;
+ else if (pcBetween(MachUserGenException,MachKernIntr))
+ subr = (unsigned) MachUserGenException;
+ else if (pcBetween(MachKernIntr, MachUserIntr))
+ subr = (unsigned) MachKernIntr;
+ else if (pcBetween(MachUserIntr, MachTLBInvalidException))
+ subr = (unsigned) MachUserIntr;
+ else if (pcBetween(splx, wbflush))
+ subr = (unsigned) splx;
+ else if (pcBetween(cpu_switch, fuword))
+ subr = (unsigned) cpu_switch;
+ else if (pcBetween(idle, cpu_switch)) {
+ subr = (unsigned) idle;
+ ra = 0;
+ goto done;
+ }
+ else if (pc >= (unsigned)MachTLBMiss && pc < (unsigned)setsoftclock) {
+ (*printfn)("<<locore>>");
+ goto done;
+ }
+
+ /* check for bad PC */
+ if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) {
+ (*printfn)("PC 0x%x: not in kernel\n", pc);
+ ra = 0;
+ goto done;
+ }
+
+ /*
+ * Find the beginning of the current subroutine by scanning backwards
+ * from the current PC for the end of the previous subroutine.
+ */
+ if (!subr) {
+ va = pc - sizeof(int);
+ while ((instr = kdbpeek(va)) != MIPS_JR_RA)
+ va -= sizeof(int);
+ va += 2 * sizeof(int); /* skip back over branch & delay slot */
+ /* skip over nulls which might separate .o files */
+ while ((instr = kdbpeek(va)) == 0)
+ va += sizeof(int);
+ subr = va;
+ }
+
+ /*
+ * Jump here for locore entry pointsn for which the preceding
+ * function doesn't end in "j ra"
+ */
+stackscan:
+ /* scan forwards to find stack size and any saved registers */
+ stksize = 0;
+ more = 3;
+ mask = 0;
+ for (va = subr; more; va += sizeof(int),
+ more = (more == 3) ? 3 : more - 1) {
+ /* stop if hit our current position */
+ if (va >= pc)
+ break;
+ instr = kdbpeek(va);
+ i.word = instr;
+ switch (i.JType.op) {
+ case OP_SPECIAL:
+ switch (i.RType.func) {
+ case OP_JR:
+ case OP_JALR:
+ more = 2; /* stop after next instruction */
+ break;
+
+ case OP_SYSCALL:
+ case OP_BREAK:
+ more = 1; /* stop now */
+ };
+ break;
+
+ case OP_BCOND:
+ case OP_J:
+ case OP_JAL:
+ case OP_BEQ:
+ case OP_BNE:
+ case OP_BLEZ:
+ case OP_BGTZ:
+ more = 2; /* stop after next instruction */
+ break;
+
+ case OP_COP0:
+ case OP_COP1:
+ case OP_COP2:
+ case OP_COP3:
+ switch (i.RType.rs) {
+ case OP_BCx:
+ case OP_BCy:
+ more = 2; /* stop after next instruction */
+ };
+ break;
+
+ case OP_SW:
+ /* look for saved registers on the stack */
+ if (i.IType.rs != 29)
+ break;
+ /* only restore the first one */
+ if (mask & (1 << i.IType.rt))
+ break;
+ mask |= (1 << i.IType.rt);
+ switch (i.IType.rt) {
+ case 4: /* a0 */
+ a0 = kdbpeek(sp + (short)i.IType.imm);
+ break;
+
+ case 5: /* a1 */
+ a1 = kdbpeek(sp + (short)i.IType.imm);
+ break;
+
+ case 6: /* a2 */
+ a2 = kdbpeek(sp + (short)i.IType.imm);
+ break;
+
+ case 7: /* a3 */
+ a3 = kdbpeek(sp + (short)i.IType.imm);
+ break;
+
+ case 30: /* fp */
+ fp = kdbpeek(sp + (short)i.IType.imm);
+ break;
+
+ case 31: /* ra */
+ ra = kdbpeek(sp + (short)i.IType.imm);
+ }
+ break;
+
+ case OP_ADDI:
+ case OP_ADDIU:
+ /* look for stack pointer adjustment */
+ if (i.IType.rs != 29 || i.IType.rt != 29)
+ break;
+ stksize = - ((short)i.IType.imm);
+ }
+ }
+
+done:
+ (*printfn)("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
+ fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
+
+ if (ra) {
+ if (pc == ra && stksize == 0)
+ (*printfn)("stacktrace: loop!\n");
+ else {
+ pc = ra;
+ sp += stksize;
+ ra = 0;
+ goto loop;
+ }
+ } else {
+finish:
+ if (curproc)
+ (*printfn)("User-level: pid %d\n", curproc->p_pid);
+ else
+ (*printfn)("User-level: curproc NULL\n");
+ }
+}
+
+/*
+ * Functions ``special'' enough to print by name
+ */
+#ifdef __STDC__
+#define Name(_fn) { (void*)_fn, # _fn }
+#else
+#define Name(_fn) { _fn, "_fn"}
+#endif
+static struct { void *addr; char *name;} names[] = {
+ Name(interrupt),
+ Name(trap),
+ Name(MachKernGenException),
+ Name(MachUserGenException),
+ Name(MachKernIntr),
+ Name(MachUserIntr),
+ Name(splx),
+ Name(idle),
+ Name(cpu_switch),
+ {0, 0}
+};
+
+/*
+ * Map a function address to a string name, if known; or a hex string.
+ */
+char *
+fn_name(unsigned addr)
+{
+ static char buf[17];
+ int i = 0;
+
+ for (i = 0; names[i].name; i++)
+ if (names[i].addr == (void*)addr)
+ return (names[i].name);
+ sprintf(buf, "%x", addr);
+ return (buf);
+}
+
+#endif /* DEBUG */
diff --git a/sys/arch/arc/arc/vm_machdep.c b/sys/arch/arc/arc/vm_machdep.c
new file mode 100644
index 00000000000..a2875520867
--- /dev/null
+++ b/sys/arch/arc/arc/vm_machdep.c
@@ -0,0 +1,487 @@
+/* $OpenBSD: vm_machdep.c,v 1.1 1996/06/24 09:07:21 pefo Exp $ */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: vm_machdep.c 1.21 91/04/06
+ *
+ * from: @(#)vm_machdep.c 8.3 (Berkeley) 1/4/94
+ * $Id: vm_machdep.c,v 1.1 1996/06/24 09:07:21 pefo Exp $
+ */
+
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/vnode.h>
+#include <sys/user.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#if 0
+#include <vm/vm_object.h>
+#endif
+
+#include <machine/pte.h>
+#include <machine/cpu.h>
+
+vm_offset_t kmem_alloc_wait_align();
+
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the kernel stack and pcb, making the child
+ * ready to run, and marking it so that it can return differently
+ * than the parent. Returns 1 in the child process, 0 in the parent.
+ * We currently double-map the user area so that the stack is at the same
+ * address in each process; in the future we will probably relocate
+ * the frame pointers on the stack after copying.
+ */
+cpu_fork(p1, p2)
+ register struct proc *p1, *p2;
+{
+ register struct user *up = p2->p_addr;
+ register pt_entry_t *pte;
+ register int i;
+ extern struct proc *machFPCurProcPtr;
+
+ p2->p_md.md_regs = up->u_pcb.pcb_regs;
+ p2->p_md.md_flags = p1->p_md.md_flags & MDP_FPUSED;
+
+ /*
+ * Cache the PTEs for the user area in the machine dependent
+ * part of the proc struct so cpu_switch() can quickly map in
+ * the user struct and kernel stack. Note: if the virtual address
+ * translation changes (e.g. swapout) we have to update this.
+ */
+ pte = kvtopte(up);
+ for (i = 0; i < UPAGES; i++) {
+ p2->p_md.md_upte[i] = pte->pt_entry & ~(PG_G | PG_RO | PG_WIRED);
+ pte++;
+ }
+
+ /*
+ * Copy floating point state from the FP chip if this process
+ * has state stored there.
+ */
+ if (p1 == machFPCurProcPtr)
+ MachSaveCurFPState(p1);
+
+ /*
+ * Copy pcb and stack from proc p1 to p2.
+ * We do this as cheaply as possible, copying only the active
+ * part of the stack. The stack and pcb need to agree;
+ */
+ p2->p_addr->u_pcb = p1->p_addr->u_pcb;
+ /* cache segtab for ULTBMiss() */
+ p2->p_addr->u_pcb.pcb_segtab = (void *)p2->p_vmspace->vm_pmap.pm_segtab;
+
+ /*
+ * Arrange for a non-local goto when the new process
+ * is started, to resume here, returning nonzero from setjmp.
+ */
+#ifdef DIAGNOSTIC
+ if (p1 != curproc)
+ panic("cpu_fork: curproc");
+#endif
+ if (copykstack(up)) {
+ /*
+ * Return 1 in child.
+ */
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Finish a swapin operation.
+ * We neded to update the cached PTEs for the user area in the
+ * machine dependent part of the proc structure.
+ */
+void
+cpu_swapin(p)
+ register struct proc *p;
+{
+ register struct user *up = p->p_addr;
+ register pt_entry_t *pte;
+ register int i;
+
+ /*
+ * Cache the PTEs for the user area in the machine dependent
+ * part of the proc struct so cpu_switch() can quickly map in
+ * the user struct and kernel stack.
+ */
+ pte = kvtopte(up);
+ for (i = 0; i < UPAGES; i++) {
+ p->p_md.md_upte[i] = pte->pt_entry & ~(PG_G | PG_RO | PG_WIRED);
+ pte++;
+ }
+}
+
+/*
+ * cpu_exit is called as the last action during exit.
+ * We release the address space and machine-dependent resources,
+ * including the memory for the user structure and kernel stack.
+ * Once finished, we call switch_exit, which switches to a temporary
+ * pcb and stack and never returns. We block memory allocation
+ * until switch_exit has made things safe again.
+ */
+void cpu_exit(p)
+ struct proc *p;
+{
+ extern struct proc *machFPCurProcPtr;
+
+ if (machFPCurProcPtr == p)
+ machFPCurProcPtr = (struct proc *)0;
+
+ vmspace_free(p->p_vmspace);
+
+ (void) splhigh();
+ kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
+ switch_exit();
+ /* NOTREACHED */
+}
+
+/*
+ * Dump the machine specific header information at the start of a core dump.
+ */
+cpu_coredump(p, vp, cred, core)
+ struct proc *p;
+ struct vnode *vp;
+ struct ucred *cred;
+ struct core *core;
+{
+ extern struct proc *machFPCurProcPtr;
+
+ /*
+ * Copy floating point state from the FP chip if this process
+ * has state stored there.
+ */
+ if (p == machFPCurProcPtr)
+ MachSaveCurFPState(p);
+
+ return (vn_rdwr(UIO_WRITE, vp, (caddr_t)p->p_addr, ctob(UPAGES),
+ (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)NULL,
+ p));
+}
+
+/*
+ * Move pages from one kernel virtual address to another.
+ * Both addresses are assumed to reside in the Sysmap,
+ * and size must be a multiple of CLSIZE.
+ */
+void
+pagemove(from, to, size)
+ register caddr_t from, to;
+ size_t size;
+{
+ register pt_entry_t *fpte, *tpte;
+
+ if (size % CLBYTES)
+ panic("pagemove");
+ fpte = kvtopte(from);
+ tpte = kvtopte(to);
+ if(((int)from & machCacheAliasMask) != ((int)to & machCacheAliasMask)) {
+ MachHitFlushDCache(from, size);
+ }
+ while (size > 0) {
+ MachTLBFlushAddr(from);
+ MachTLBUpdate(to, *fpte);
+ *tpte++ = *fpte;
+ fpte->pt_entry = PG_NV | PG_G;
+ fpte++;
+ size -= NBPG;
+ from += NBPG;
+ to += NBPG;
+ }
+}
+
+extern vm_map_t phys_map;
+
+/*
+ * Map an IO request into kernel virtual address space. Requests fall into
+ * one of five catagories:
+ *
+ * B_PHYS|B_UAREA: User u-area swap.
+ * Address is relative to start of u-area (p_addr).
+ * B_PHYS|B_PAGET: User page table swap.
+ * Address is a kernel VA in usrpt (Usrptmap).
+ * B_PHYS|B_DIRTY: Dirty page push.
+ * Address is a VA in proc2's address space.
+ * B_PHYS|B_PGIN: Kernel pagein of user pages.
+ * Address is VA in user's address space.
+ * B_PHYS: User "raw" IO request.
+ * Address is VA in user's address space.
+ *
+ * All requests are (re)mapped into kernel VA space via the phys_map
+ */
+void
+vmapbuf(bp, len)
+ struct buf *bp;
+ vm_size_t len;
+{
+ register caddr_t addr;
+ register vm_size_t sz;
+ struct proc *p;
+ int off;
+ vm_offset_t kva;
+ register vm_offset_t pa;
+
+ if ((bp->b_flags & B_PHYS) == 0)
+ panic("vmapbuf");
+ addr = bp->b_saveaddr = bp->b_un.b_addr;
+ off = (int)addr & PGOFSET;
+ p = bp->b_proc;
+ sz = round_page(off + len);
+ kva = kmem_alloc_wait_align(phys_map, sz, (vm_size_t)addr & machCacheAliasMask);
+ bp->b_un.b_addr = (caddr_t) (kva + off);
+ sz = atop(sz);
+ while (sz--) {
+ pa = pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),
+ (vm_offset_t)addr);
+ if (pa == 0)
+ panic("vmapbuf: null page frame");
+ pmap_enter(vm_map_pmap(phys_map), kva, trunc_page(pa),
+ VM_PROT_READ|VM_PROT_WRITE, TRUE);
+ addr += PAGE_SIZE;
+ kva += PAGE_SIZE;
+ }
+}
+
+/*
+ * Free the io map PTEs associated with this IO operation.
+ * We also invalidate the TLB entries and restore the original b_addr.
+ */
+void
+vunmapbuf(bp, len)
+ struct buf *bp;
+ vm_size_t len;
+{
+ register caddr_t addr = bp->b_un.b_addr;
+ register vm_size_t sz;
+ vm_offset_t kva;
+
+ if ((bp->b_flags & B_PHYS) == 0)
+ panic("vunmapbuf");
+ sz = round_page(len + ((int)addr & PGOFSET));
+ kva = (vm_offset_t)((int)addr & ~PGOFSET);
+ kmem_free_wakeup(phys_map, kva, sz);
+ bp->b_un.b_addr = bp->b_saveaddr;
+ bp->b_saveaddr = NULL;
+}
+
+
+/*
+ * SAVE_HINT:
+ *
+ * Saves the specified entry as the hint for
+ * future lookups. Performs necessary interlocks.
+ */
+#define SAVE_HINT(map,value) \
+ simple_lock(&(map)->hint_lock); \
+ (map)->hint = (value); \
+ simple_unlock(&(map)->hint_lock);
+
+
+/*
+ * kmem_alloc_upage:
+ *
+ * Allocate pageable memory to the kernel's address map.
+ * map must be "kernel_map" below.
+ * (Currently only used when allocating U pages).
+ */
+vm_offset_t
+kmem_alloc_upage(map, size)
+ vm_map_t map;
+ register vm_size_t size;
+{
+ vm_offset_t addr;
+ register int result;
+
+
+ size = round_page(size);
+
+ addr = vm_map_min(map);
+ result = vm_map_find_U(map, NULL, (vm_offset_t) 0,
+ &addr, size, TRUE);
+ if (result != KERN_SUCCESS) {
+ return(0);
+ }
+
+ return(addr);
+}
+
+/*
+ * vm_map_find finds an unallocated region in the target address
+ * map with the given length aligned on U viritual address.
+ * The search is defined to be first-fit from the specified address;
+ * the region found is returned in the same parameter.
+ *
+ */
+int
+vm_map_find_U(map, object, offset, addr, length, find_space)
+ vm_map_t map;
+ vm_object_t object;
+ vm_offset_t offset;
+ vm_offset_t *addr; /* IN/OUT */
+ vm_size_t length;
+ boolean_t find_space;
+{
+ register vm_offset_t start;
+ int result;
+
+ start = *addr;
+ vm_map_lock(map);
+ if (find_space) {
+ if (vm_map_findspace_align(map, start, length, addr, 0)) {
+ vm_map_unlock(map);
+ return (KERN_NO_SPACE);
+ }
+ start = *addr;
+ }
+ result = vm_map_insert(map, object, offset, start, start + length);
+ vm_map_unlock(map);
+ return (result);
+}
+
+/*
+ * Find sufficient space for `length' bytes in the given map, starting at
+ * `start'. The map must be locked. Returns 0 on success, 1 on no space.
+ */
+int
+vm_map_findspace_align(map, start, length, addr, align)
+ register vm_map_t map;
+ register vm_offset_t start;
+ vm_size_t length;
+ vm_offset_t *addr;
+ vm_size_t align;
+{
+ register vm_map_entry_t entry, next;
+ register vm_offset_t end;
+
+ if (start < map->min_offset)
+ start = map->min_offset;
+ if (start > map->max_offset)
+ return (1);
+
+ /*
+ * Look for the first possible address; if there's already
+ * something at this address, we have to start after it.
+ */
+ if (start == map->min_offset) {
+ if ((entry = map->first_free) != &map->header)
+ start = entry->end;
+ } else {
+ vm_map_entry_t tmp;
+ if (vm_map_lookup_entry(map, start, &tmp))
+ start = tmp->end;
+ entry = tmp;
+ }
+
+ /*
+ * Look through the rest of the map, trying to fit a new region in
+ * the gap between existing regions, or after the very last region.
+ */
+ for (;; start = (entry = next)->end) {
+ /*
+ * Find the end of the proposed new region. Be sure we didn't
+ * go beyond the end of the map, or wrap around the address;
+ * if so, we lose. Otherwise, if this is the last entry, or
+ * if the proposed new region fits before the next entry, we
+ * win.
+ */
+ start = ((start + NBPG -1) & ~(NBPG - 1)); /* Paranoia */
+ if((start & machCacheAliasMask) <= align) {
+ start += align - (start & machCacheAliasMask);
+ }
+ else {
+ start = ((start + machCacheAliasMask) & ~machCacheAliasMask);
+ start += align;
+ }
+
+ end = start + length;
+ if (end > map->max_offset || end < start)
+ return (1);
+ next = entry->next;
+ if (next == &map->header || next->start >= end)
+ break;
+ }
+ SAVE_HINT(map, entry);
+ *addr = start;
+ return (0);
+}
+
+/*
+ * kmem_alloc_wait_align
+ *
+ * Allocates pageable memory from a sub-map of the kernel. If the submap
+ * has no room, the caller sleeps waiting for more memory in the submap.
+ *
+ */
+vm_offset_t
+kmem_alloc_wait_align(map, size, align)
+ vm_map_t map;
+ vm_size_t size;
+ vm_size_t align;
+{
+ vm_offset_t addr;
+
+ size = round_page(size);
+
+ for (;;) {
+ /*
+ * To make this work for more than one map,
+ * use the map's lock to lock out sleepers/wakers.
+ */
+ vm_map_lock(map);
+ if (vm_map_findspace_align(map, 0, size, &addr, align) == 0)
+ break;
+ /* no space now; see if we can ever get space */
+ if (vm_map_max(map) - vm_map_min(map) < size) {
+ vm_map_unlock(map);
+ return (0);
+ }
+ assert_wait(map, TRUE);
+ vm_map_unlock(map);
+ thread_block();
+ }
+ vm_map_insert(map, NULL, (vm_offset_t)0, addr, addr + size);
+ vm_map_unlock(map);
+ return (addr);
+}
diff --git a/sys/arch/arc/compile/.cvsignore b/sys/arch/arc/compile/.cvsignore
new file mode 100644
index 00000000000..db5b0e04a3a
--- /dev/null
+++ b/sys/arch/arc/compile/.cvsignore
@@ -0,0 +1 @@
+GENERIC
diff --git a/sys/arch/arc/compile/.keep_me b/sys/arch/arc/compile/.keep_me
new file mode 100644
index 00000000000..75270197a54
--- /dev/null
+++ b/sys/arch/arc/compile/.keep_me
@@ -0,0 +1 @@
+This file must remain so that 'cvs checkout' makes the compile directory.
diff --git a/sys/arch/arc/conf/GENERIC b/sys/arch/arc/conf/GENERIC
new file mode 100644
index 00000000000..21cfe44324b
--- /dev/null
+++ b/sys/arch/arc/conf/GENERIC
@@ -0,0 +1,97 @@
+#
+# Generic configuration file for MIPS R4400 PICA system
+#
+
+machine arc
+
+maxusers 8
+
+# does not really do anything anymore, but this replaces "ident GENERIC"
+options GENERIC
+
+# Need to set locally
+options TIMEZONE="8*60" # minutes west of GMT (for)
+options DST=1 # use daylight savings rules
+
+# Standard system options
+options SWAPPAGER # swap pager (anonymous and swap space)
+options VNODEPAGER # vnode pager (mapped files)
+options DEVPAGER # device pager (mapped devices)
+options DIAGNOSTIC # extra kernel debugging checks
+options DEBUG # extra kernel debugging support
+options "COMPAT_43" # compatibility with 4.3BSD binaries
+#options KTRACE # system call tracing support
+options "NKMEMCLUSTERS=1024" # 4K pages in kernel malloc pool
+#options KGDB # support for kernel gdb
+#options "KGDBRATE=19200" # kernel gdb port rate (default 9600)
+#options "KGDBDEV=15*256+0" # device for kernel gdb
+
+# System V options
+options SYSVMSG # System V-like message queues
+options SYSVSEM # System V-like semaphores
+options SYSVSHM # System V-like memory sharing
+options SHMMAXPGS=1024 # 1024 pages is the default
+options NATIVE_ELF
+
+# Filesystem options
+options FIFO # POSIX fifo support (in all filesystems)
+options FFS,QUOTA # fast filesystem with user and group quotas
+options MFS # memory-based filesystem
+options NFSCLIENT # Sun NFS-compatible filesystem (client)
+options NFSSERVER # Sun NFS-compatible filesystem (server)
+options KERNFS # kernel data-structure filesystem
+options MSDOSFS # Ability to read write MS-Dos filsystem
+options CD9660 # ISO 9660 + Rock Ridge file system
+options FDESC # user file descriptor filesystem
+#options UMAPFS # uid/gid remapping filesystem
+#options NULLFS # null layer filesystem
+#options LFS # Log-based filesystem (still experimental)
+#options PORTAL # portal filesystem (still experimental)
+
+# Networking options
+options INET # Internet protocols
+options "TCP_COMPAT_42" # compatibility with 4.2BSD TCP/IP
+options GATEWAY # IP packet forwarding
+#options MULTICAST # Multicast support
+#options MROUTING # Multicast routing support
+#options ISO # OSI networking
+#options TPIP
+#options EON
+
+config bsd swap generic
+
+mainbus0 at root
+cpu* at mainbus0
+
+pica* at mainbus0
+clock0 at pica?
+pc0 at pica?
+pms0 at pica?
+ace0 at pica?
+ace1 at pica?
+lpt0 at pica?
+sn0 at pica?
+
+fdc0 at pica?
+fd* at fdc? drive ?
+
+asc0 at pica?
+scsibus* at asc?
+
+sd* at scsibus? target ? lun ?
+st* at scsibus? target ? lun ?
+cd* at scsibus? target ? lun ?
+ch* at scsibus? target ? lun ?
+ss* at scsibus? target ? lun ?
+uk* at scsibus? target ? lun ?
+
+isabr* at mainbus0
+
+isa* at isabr?
+
+pseudo-device sl 2 # serial-line IP ports
+pseudo-device ppp 2 # serial-line PPP ports
+pseudo-device pty 64 # pseudo ptys
+pseudo-device bpfilter 16 # packet filter ports
+pseudo-device loop
+pseudo-device vnd 4 # virtual disk
diff --git a/sys/arch/arc/conf/Makefile.arc b/sys/arch/arc/conf/Makefile.arc
new file mode 100644
index 00000000000..d78ad52e462
--- /dev/null
+++ b/sys/arch/arc/conf/Makefile.arc
@@ -0,0 +1,183 @@
+# $OpenBSD: Makefile.arc,v 1.1 1996/06/24 09:07:20 pefo Exp $
+
+# @(#)Makefile.arc 8.2 (Berkeley) 2/16/94
+#
+# Makefile for 4.4 BSD
+#
+# This makefile is constructed from a machine description:
+# config machineid
+# Most changes should be made in the machine description
+# /sys/arch/MACHINE/conf/``machineid''
+# after which you should do
+# config machineid
+# Machine generic makefile changes should be made in
+# /sys/arch/MACHINE/conf/Makefile.``machinetype''
+# after which config should be rerun for all machines of that type.
+#
+# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE
+# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
+#
+# -DTRACE compile in kernel tracing hooks
+# -DQUOTA compile in file system quotas
+
+
+# DEBUG is set to -g by config if debugging is requested (config -g).
+# PROF is set to -pg by config if profiling is requested (config -p).
+AS?= as
+CC?= cc
+CPP?= cpp
+LD= ld.ok # XXX TEMPORARY
+STRIP?= strip -d
+TOUCH?= touch -f -c
+
+# source tree is located via $S relative to the compilation directory
+S= ../../../..
+ARC= ../..
+
+INCLUDES= -I. -I$S/arch -I$S
+CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL -Darc
+CFLAGS= ${DEBUG} -O2 -Werror -mno-abicalls -mips2 -mcpu=r4000
+AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE
+
+### find out what to use for libkern
+.include "$S/lib/libkern/Makefile.inc"
+.ifndef PROF
+LIBKERN= ${KERNLIB}
+.else
+LIBKERN= ${KERNLIB_PROF}
+.endif
+
+### find out what to use for libcompat
+.include "$S/compat/common/Makefile.inc"
+.ifndef PROF
+LIBCOMPAT= ${COMPATLIB}
+.else
+LIBCOMPAT= ${COMPATLIB_PROF}
+.endif
+
+# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP}
+# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix,
+# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file
+# is marked as config-dependent.
+
+USRLAND_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+USRLAND_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $<
+NORMAL_S_C= ${AS} ${COPTS} ${PARAM} $< -o $@
+
+%OBJS
+
+%CFILES
+
+%SFILES
+
+# load lines for config "xxx" will be emitted as:
+# xxx: ${SYSTEM_DEP} swapxxx.o
+# ${SYSTEM_LD_HEAD}
+# ${SYSTEM_LD} swapxxx.o
+# ${SYSTEM_LD_TAIL}
+
+SYSTEM_OBJ= locore.o fp.o ${OBJS} param.o ioconf.o ${LIBKERN} \
+ ${LIBCOMPAT}
+#
+SYSTEM_DEP= Makefile ${SYSTEM_OBJ}
+SYSTEM_LD_HEAD= rm -f $@
+SYSTEM_LD= -@if [ X${DEBUG} = X-g ]; \
+ then strip=-X; \
+ else strip=-x; \
+ fi; \
+ echo ${LD} $$strip -N -o $@ -e start -Ttext 80080000 \
+ '$${SYSTEM_OBJ}' vers.o; \
+ ${LD} $$strip -N -o $@ -e start -Ttext 80080000 \
+ ${SYSTEM_OBJ} vers.o
+#
+SYSTEM_LD_TAIL= chmod 755 $@; \
+ elf2ecoff $@ $@.ecoff; \
+ size $@
+
+%LOAD
+
+newvers:
+ sh $S/conf/newvers.sh
+ ${CC} $(CFLAGS) -c vers.c
+
+clean::
+ rm -f eddep bsd bsd.gdb tags *.o locore.i [a-z]*.s \
+ Errs errs linterrs makelinks genassym
+
+lint: /tmp param.c
+ @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} -UKGDB \
+ ${ARC}/arc/Locore.c ${CFILES} ${ARC}/arc/swapgeneric.c \
+ ioconf.c param.c
+
+symbols.sort: ${ARC}/arc/symbols.raw
+ grep -v '^#' ${ARC}/arc/symbols.raw \
+ | sed 's/^ //' | sort -u > symbols.sort
+
+locore.o: ${ARC}/arc/locore.S ${ARC}/include/asm.h \
+ ${ARC}/include/cpu.h ${ARC}/include/reg.h assym.h
+ ${NORMAL_S} -mips3 ${ARC}/arc/locore.S
+
+fp.o: ${ARC}/arc/fp.S ${ARC}/include/asm.h \
+ ${ARC}/include/cpu.h ${ARC}/include/reg.h assym.h
+ ${NORMAL_S} -mips3 ${ARC}/arc/fp.S
+
+# the following are necessary because the files depend on the types of
+# cpu's included in the system configuration
+clock.o machdep.o autoconf.o conf.o: Makefile
+
+# depend on network configuration
+uipc_domain.o uipc_proto.o vfs_conf.o: Makefile
+if_tun.o if_loop.o if_ethersubr.o: Makefile
+in_proto.o: Makefile
+
+assym.h: genassym
+ ./genassym >assym.h
+
+genassym: genassym.o
+ ${CC} -o $@ genassym.o
+
+genassym.o: ${ARC}/arc/genassym.c
+ ${CC} ${INCLUDES} ${IDENT} -D_KERNEL -Darc -c $<
+
+links:
+ egrep '#if' ${CFILES} | sed -f $S/conf/defines | \
+ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink
+ echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \
+ sort -u | comm -23 - dontlink | \
+ sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks
+ sh makelinks && rm -f dontlink
+
+tags:
+ @echo "see $S/kern/Makefile for tags"
+
+ioconf.o: ioconf.c
+ ${NORMAL_C}
+
+param.c: $S/conf/param.c
+ rm -f param.c
+ cp $S/conf/param.c .
+
+param.o: param.c Makefile
+ ${NORMAL_C_C}
+
+newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
+ sh $S/conf/newvers.sh
+ ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c
+
+depend:: .depend
+.depend: ${SRCS} assym.h param.c
+ mkdep ${AFLAGS} ${CPPFLAGS} ${ARC}/arc/locore.s
+ mkdep -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES}
+ mkdep -a ${AFLAGS} ${CPPFLAGS} ${SFILES}
+ mkdep -a ${CFLAGS} ${CPPFLAGS} ${PARAM} ${ARC}/arc/genassym.c
+
+%RULES
+
diff --git a/sys/arch/arc/conf/PICA b/sys/arch/arc/conf/PICA
new file mode 100644
index 00000000000..9251c84728d
--- /dev/null
+++ b/sys/arch/arc/conf/PICA
@@ -0,0 +1,108 @@
+#
+# Generic configuration file for MIPS R4400 PICA system
+#
+
+machine arc
+
+maxusers 8
+
+# does not really do anything anymore, but this replaces "ident GENERIC"
+# options GENERIC
+
+# Need to set locally
+options TIMEZONE="8*60" # minutes west of GMT (for)
+options DST=1 # use daylight savings rules
+
+# Standard system options
+options SWAPPAGER # swap pager (anonymous and swap space)
+options VNODEPAGER # vnode pager (mapped files)
+options DEVPAGER # device pager (mapped devices)
+options DIAGNOSTIC # extra kernel debugging checks
+options DEBUG # extra kernel debugging support
+options "COMPAT_43" # compatibility with 4.3BSD binaries
+#options KTRACE # system call tracing support
+options "NKMEMCLUSTERS=1024" # 4K pages in kernel malloc pool
+#options KGDB # support for kernel gdb
+#options "KGDBRATE=19200" # kernel gdb port rate (default 9600)
+#options "KGDBDEV=15*256+0" # device for kernel gdb
+
+# System V options
+options SYSVMSG # System V-like message queues
+options SYSVSEM # System V-like semaphores
+options SYSVSHM # System V-like memory sharing
+options SHMMAXPGS=1024 # 1024 pages is the default
+options NATIVE_ELF
+
+# Filesystem options
+options FIFO # POSIX fifo support (in all filesystems)
+options FFS,QUOTA # fast filesystem with user and group quotas
+options MFS # memory-based filesystem
+options NFSCLIENT # Sun NFS-compatible filesystem (client)
+options NFSSERVER # Sun NFS-compatible filesystem (server)
+options KERNFS # kernel data-structure filesystem
+options MSDOSFS # Ability to read write MS-Dos filsystem
+options CD9660 # ISO 9660 + Rock Ridge file system
+options FDESC # user file descriptor filesystem
+#options UMAPFS # uid/gid remapping filesystem
+#options NULLFS # null layer filesystem
+#options LFS # Log-based filesystem (still experimental)
+#options PORTAL # portal filesystem (still experimental)
+
+# Networking options
+options INET # Internet protocols
+options "TCP_COMPAT_42" # compatibility with 4.2BSD TCP/IP
+options GATEWAY # IP packet forwarding
+#options MULTICAST # Multicast support
+#options MROUTING # Multicast routing support
+#options ISO # OSI networking
+#options TPIP
+#options EON
+
+config bsd root on sd0 swap on sd0 and sd1
+
+mainbus0 at root
+cpu* at mainbus0
+
+#
+# PICA Bus
+#
+pica* at mainbus0
+
+clock0 at pica?
+pc0 at pica?
+pms0 at pica?
+ace0 at pica?
+ace1 at pica?
+lpt0 at pica?
+sn0 at pica?
+
+fdc0 at pica?
+fd* at fdc? drive ?
+
+asc0 at pica?
+scsibus* at asc?
+
+sd* at scsibus? target ? lun ?
+st* at scsibus? target ? lun ?
+cd* at scsibus? target ? lun ?
+ch* at scsibus? target ? lun ?
+ss* at scsibus? target ? lun ?
+uk* at scsibus? target ? lun ?
+
+#
+# ISA Bus.
+#
+isabr* at mainbus0
+
+isa* at isabr?
+
+ace2 at isa? port 0x3f8 irq 4
+ace3 at isa? port 0x2f8 irq 3
+
+
+pseudo-device sl 2 # serial-line IP ports
+pseudo-device ppp 2 # serial-line PPP ports
+pseudo-device pty 64 # pseudo ptys
+pseudo-device bpfilter 16 # packet filter ports
+pseudo-device loop
+pseudo-device vnd 4 # virtual disk
diff --git a/sys/arch/arc/conf/files.arc b/sys/arch/arc/conf/files.arc
new file mode 100644
index 00000000000..3d57f328b3c
--- /dev/null
+++ b/sys/arch/arc/conf/files.arc
@@ -0,0 +1,124 @@
+# $OpenBSD: files.arc,v 1.1 1996/06/24 09:07:20 pefo Exp $
+#
+# maxpartitions must be first item in files.${ARCH}
+#
+maxpartitions 8
+
+maxusers 2 8 64
+
+# Required files
+
+
+file arch/arc/arc/autoconf.c
+file arch/arc/arc/conf.c
+file arch/arc/arc/cpu_exec.c
+file arch/arc/arc/disksubr.c
+file arch/arc/dev/dma.c
+file arch/arc/arc/machdep.c
+file arch/arc/arc/minidebug.c
+file arch/arc/arc/mem.c
+file arch/arc/arc/pmap.c
+file arch/arc/arc/process_machdep.c
+file arch/arc/arc/sys_machdep.c
+file arch/arc/arc/trap.c
+file arch/arc/arc/vm_machdep.c
+
+#
+# Machine-independent ATAPI drivers
+#
+
+include "../../../dev/atapi/files.atapi"
+
+
+#
+# System BUS types
+#
+
+define mainbus {}
+device mainbus
+attach mainbus at root
+file arch/arc/arc/mainbus.c mainbus
+
+# Our CPU configurator
+device cpu
+attach cpu at mainbus # not optional
+file arch/arc/arc/cpu.c cpu
+
+#
+# PICA bus autoconfiguration devices
+#
+device pica {}
+attach pica at mainbus # { slot = -1, offset = -1 }
+file arch/arc/pica/picabus.c pica
+
+# Real time clock, must have one..
+device clock
+attach clock at pica
+file arch/arc/arc/clock.c clock
+file arch/arc/arc/clock_mc.c clock
+
+# Ethernet chip
+device sn
+attach sn at pica: ifnet, ether
+file arch/arc/dev/if_sn.c sn needs-count
+
+# Use machine independent SCSI driver routines
+include "../../../scsi/files.scsi"
+major {sd = 0}
+major {cd = 3}
+
+# Machine dependent SCSI interface driver
+device asc: scsi
+attach asc at pica
+file arch/arc/dev/asc.c asc needs-count
+
+# Console driver on PC-style graphics
+device pc: tty
+attach pc at pica
+device pms: tty
+attach pms at pica
+file arch/arc/dev/pccons.c pc needs-count
+
+# Floppy disk controller
+device fdc {drive = -1}
+attach fdc at pica
+device fd: disk
+attach fd at fdc
+file arch/arc/dev/fd.c fdc needs-flag
+major {fd = 7}
+
+
+#
+# ISA
+#
+device isabr {} : isabus
+attach isabr at mainbus
+file arch/arc/isa/isabus.c isabr
+file arch/arc/isa/isadma.c isadma needs-flag
+
+#
+# Stock ISA bus support
+#
+define pcmcia {} # XXX dummy decl...
+define pci {} # XXX dummy decl...
+
+include "../../../dev/isa/files.isa"
+
+# Serial driver for both ISA and LOCAL bus.
+device ace: tty
+attach ace at isa with ace_isa
+attach ace at commulti with ace_commulti
+attach ace at pica with ace_pica
+file arch/arc/dev/ace.c ace & (ace_isa | ace_commulti | ace_pica) needs-flag
+
+#
+
+file dev/cons.c
+file dev/cninit.c
+file netinet/in_cksum.c
+file netns/ns_cksum.c ns
+
+file compat/ultrix/ultrix_misc.c compat_ultrix
+file compat/ultrix/ultrix_syscalls.c compat_ultrix
+file compat/ultrix/ultrix_sysent.c compat_ultrix
+
diff --git a/sys/arch/arc/dev/ace.c b/sys/arch/arc/dev/ace.c
new file mode 100644
index 00000000000..a285e748ff7
--- /dev/null
+++ b/sys/arch/arc/dev/ace.c
@@ -0,0 +1,1783 @@
+/* $OpenBSD: ace.c,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994, 1995, 1996
+ * Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)com.c 7.5 (Berkeley) 5/16/91
+ */
+
+/*
+ * ACE driver, based on HP dca driver
+ * uses National Semiconductor NS16450/NS16550AF UART
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/types.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/comreg.h>
+#include <dev/isa/comvar.h>
+#include <dev/ic/ns16550reg.h>
+#ifdef COM_HAYESP
+#include <dev/ic/hayespreg.h>
+#endif
+#define com_lcr com_cfcr
+
+#include "com.h"
+
+
+#define COM_IBUFSIZE (2 * 512)
+#define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4)
+
+struct com_softc {
+ struct device sc_dev;
+ void *sc_ih;
+ bus_chipset_tag_t sc_bc;
+ struct tty *sc_tty;
+
+ int sc_overflows;
+ int sc_floods;
+ int sc_errors;
+
+ int sc_halt;
+
+ int sc_iobase;
+#ifdef COM_HAYESP
+ int sc_hayespbase;
+#endif
+
+ bus_io_handle_t sc_ioh;
+ bus_io_handle_t sc_hayespioh;
+
+ u_char sc_hwflags;
+#define COM_HW_NOIEN 0x01
+#define COM_HW_FIFO 0x02
+#define COM_HW_HAYESP 0x04
+#define COM_HW_ABSENT_PENDING 0x08 /* reattached, awaiting close/reopen */
+#define COM_HW_ABSENT 0x10 /* configure actually failed, or removed */
+#define COM_HW_REATTACH 0x20 /* reattaching */
+#define COM_HW_CONSOLE 0x40
+ u_char sc_swflags;
+#define COM_SW_SOFTCAR 0x01
+#define COM_SW_CLOCAL 0x02
+#define COM_SW_CRTSCTS 0x04
+#define COM_SW_MDMBUF 0x08
+ u_char sc_msr, sc_mcr, sc_lcr, sc_ier;
+ u_char sc_dtr;
+
+ u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend;
+ u_char sc_ibufs[2][COM_IBUFSIZE];
+};
+
+#ifdef COM_HAYESP
+int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc));
+#endif
+void comdiag __P((void *));
+int comspeed __P((long));
+int comparam __P((struct tty *, struct termios *));
+void comstart __P((struct tty *));
+void compoll __P((void *));
+
+/* XXX: These belong elsewhere */
+cdev_decl(com);
+bdev_decl(com);
+
+struct consdev;
+void comcnprobe __P((struct consdev *));
+void comcninit __P((struct consdev *));
+int comcngetc __P((dev_t));
+void comcnputc __P((dev_t, int));
+void comcnpollc __P((dev_t, int));
+
+static u_char tiocm_xxx2mcr __P((int));
+
+/*
+ * XXX the following two cfattach structs should be different, and possibly
+ * XXX elsewhere.
+ */
+int comprobe __P((struct device *, void *, void *));
+void comattach __P((struct device *, struct device *, void *));
+void com_absent_notify __P((struct com_softc *sc));
+void comstart_pending __P((void *));
+
+#if NACE_ISA
+struct cfattach ace_isa_ca = {
+ sizeof(struct com_softc), comprobe, comattach
+};
+#endif
+
+#if NACE_COMMULTI
+struct cfattach ace_commulti_ca = {
+ sizeof(struct com_softc), comprobe, comattach
+};
+#endif
+
+#if NACE_PICA
+#undef CONADDR /* This is stupid but using devs before config .. */
+#define CONADDR 0xe0006000
+
+struct cfattach ace_pica_ca = {
+ sizeof(struct com_softc), comprobe, comattach
+};
+#endif
+
+
+struct cfdriver ace_cd = {
+ NULL, "com", DV_TTY
+};
+
+void cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
+
+#ifndef CONSPEED
+#define CONSPEED B9600
+#endif
+
+#ifdef COMCONSOLE
+int comdefaultrate = CONSPEED; /* XXX why set default? */
+#else
+int comdefaultrate = TTYDEF_SPEED;
+#endif
+int comconsaddr;
+int comconsinit;
+int comconsattached;
+bus_chipset_tag_t comconsbc;
+bus_io_handle_t comconsioh;
+tcflag_t comconscflag = TTYDEF_CFLAG;
+
+int commajor;
+int comsopen = 0;
+int comevents = 0;
+
+#ifdef KGDB
+#include <machine/remote-sl.h>
+extern int kgdb_dev;
+extern int kgdb_rate;
+extern int kgdb_debug_init;
+#endif
+
+#define 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))
+
+#if NACE_PCMCIA
+#include <dev/pcmcia/pcmciavar.h>
+
+int com_pcmcia_match __P((struct device *, void *, void *));
+void com_pcmcia_attach __P((struct device *, struct device *, void *));
+int com_pcmcia_detach __P((struct device *));
+
+struct cfattach ace_pcmcia_ca = {
+ sizeof(struct com_softc), com_pcmcia_match, comattach,
+ com_pcmcia_detach
+};
+
+int com_pcmcia_mod __P((struct pcmcia_link *pc_link, struct device *self,
+ struct pcmcia_conf *pc_cf, struct cfdata *cf));
+
+/* additional setup needed for pcmcia devices */
+/* modify config entry */
+int
+com_pcmcia_mod(pc_link, self, pc_cf, cf)
+ struct pcmcia_link *pc_link;
+ struct device *self;
+ struct pcmcia_conf *pc_cf;
+ struct cfdata *cf;
+{
+ int err;
+ struct pcmciadevs *dev = pc_link->device;
+ struct ed_softc *sc = (void *)self;
+ if (!(err = PCMCIA_BUS_CONFIG(pc_link->adapter, pc_link, self,
+ pc_cf, cf))) {
+ pc_cf->memwin = 0;
+ if (pc_cf->cfgtype == 0)
+ pc_cf->cfgtype = CFGENTRYID; /* determine from ioaddr */
+ }
+ return err;
+}
+
+int com_pcmcia_isa_attach __P((struct device *, void *, void *,
+ struct pcmcia_link *));
+int com_pcmcia_remove __P((struct pcmcia_link *, struct device *));
+
+static struct pcmcia_com {
+ struct pcmcia_device pcd;
+} pcmcia_com = {
+ {"PCMCIA Modem card", com_pcmcia_mod, com_pcmcia_isa_attach,
+ NULL, com_pcmcia_remove}
+};
+
+
+struct pcmciadevs pcmcia_com_devs[] = {
+ { "com", 0,
+ NULL, "*MODEM*", NULL, NULL,
+ NULL, (void *)&pcmcia_com
+ },
+ { "com", 0,
+ NULL, NULL, "*MODEM*", NULL,
+ NULL, (void *)&pcmcia_com
+ },
+ { "com", 0,
+ NULL, NULL, NULL, "*MODEM*",
+ NULL, (void *)&pcmcia_com
+ },
+ {NULL}
+};
+#define ncom_pcmcia_devs sizeof(pcmcia_com_devs)/sizeof(pcmcia_com_devs[0])
+
+int
+com_pcmcia_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ return pcmcia_slave_match(parent, match, aux, pcmcia_com_devs,
+ ncom_pcmcia_devs);
+}
+
+int
+com_pcmcia_isa_attach(parent, match, aux, pc_link)
+ struct device *parent;
+ void *match;
+ void *aux;
+ struct pcmcia_link *pc_link;
+{
+ struct isa_attach_args *ia = aux;
+ struct com_softc *sc = match;
+
+ int rval;
+ if (rval = comprobe(parent, sc->sc_dev.dv_cfdata, ia)) {
+ if (ISSET(pc_link->flags, PCMCIA_REATTACH)) {
+#ifdef COM_DEBUG
+ printf("comreattach, hwflags=%x\n", sc->sc_hwflags);
+#endif
+ sc->sc_hwflags = COM_HW_REATTACH |
+ (sc->sc_hwflags & (COM_HW_ABSENT_PENDING|COM_HW_CONSOLE));
+ } else
+ sc->sc_hwflags = 0;
+ }
+ return rval;
+}
+
+
+/*
+ * Called by config_detach attempts, shortly after com_pcmcia_remove
+ * was called.
+ */
+int
+com_pcmcia_detach(self)
+ struct device *self;
+{
+ struct com_softc *sc = (void *)self;
+
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
+ /* don't let it really be detached, it is still open */
+ return EBUSY;
+ }
+ return 0; /* OK! */
+}
+
+/*
+ * called by pcmcia framework to accept/reject remove attempts.
+ * If we return 0, then the detach will proceed.
+ */
+int
+com_pcmcia_remove(pc_link, self)
+ struct pcmcia_link *pc_link;
+ struct device *self;
+{
+ struct com_softc *sc = (void *)self;
+ struct tty *tp;
+ int s;
+
+ if (!sc->sc_tty)
+ goto ok;
+ tp = sc->sc_tty;
+
+ /* not in use ? if so, return "OK" */
+ if (!ISSET(tp->t_state, TS_ISOPEN) &&
+ !ISSET(tp->t_state, TS_WOPEN)) {
+ ttyfree(sc->sc_tty);
+ sc->sc_tty = NULL;
+ ok:
+ isa_intr_disestablish(sc->sc_bc, sc->sc_ih);
+ sc->sc_ih = NULL;
+ SET(sc->sc_hwflags, COM_HW_ABSENT);
+ return 0; /* OK! */
+ }
+ /*
+ * Not easily removed. Put device into a dead state, clean state
+ * as best we can. notify all waiters.
+ */
+ SET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING);
+#ifdef COM_DEBUG
+ printf("pending detach flags %x\n", sc->sc_hwflags);
+#endif
+
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+
+ return 0;
+}
+
+#if 0
+void
+com_pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcmcia_attach_args *paa = aux;
+
+ printf("com_pcmcia_attach %p %p %p\n", parent, self, aux);
+ delay(2000000);
+ if (!pcmcia_configure(parent, self, paa->paa_link)) {
+ struct com_softc *sc = (void *)self;
+ sc->sc_hwflags |= COM_HW_ABSENT;
+ printf(": not attached\n");
+ }
+}
+#endif
+#endif
+
+/*
+ * must be called at spltty() or higher.
+ */
+void
+com_absent_notify(sc)
+ struct com_softc *sc;
+{
+ struct tty *tp = sc->sc_tty;
+
+ if (tp) {
+ CLR(tp->t_state, TS_CARR_ON|TS_BUSY);
+ ttyflush(tp, FREAD|FWRITE);
+ }
+}
+
+int
+comspeed(speed)
+ long speed;
+{
+#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
+
+ int x, err;
+
+ if (speed == 0)
+ return 0;
+ if (speed < 0)
+ return -1;
+ x = divrnd((COM_FREQ / 16), speed);
+ if (x <= 0)
+ return -1;
+ err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
+ if (err < 0)
+ err = -err;
+ if (err > COM_TOLERANCE)
+ return -1;
+ return x;
+
+#undef divrnd(n, q)
+}
+
+int
+comprobe1(bc, ioh, iobase)
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ int iobase;
+{
+ int i, k;
+
+ /* force access to id reg */
+ bus_io_write_1(bc, ioh, com_lcr, 0);
+ bus_io_write_1(bc, ioh, com_iir, 0);
+ for (i = 0; i < 32; i++) {
+ k = bus_io_read_1(bc, ioh, com_iir);
+ if (k & 0x38) {
+ bus_io_read_1(bc, ioh, com_data); /* cleanup */
+ } else
+ break;
+ }
+ if (i >= 32)
+ return 0;
+
+ return 1;
+}
+
+#ifdef COM_HAYESP
+int
+comprobeHAYESP(hayespioh, sc)
+ bus_io_handle_t hayespioh;
+ struct com_softc *sc;
+{
+ char val, dips;
+ int combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+ bus_chipset_tag_t bc = sc->sc_bc;
+
+ /*
+ * Hayes ESP cards have two iobases. One is for compatibility with
+ * 16550 serial chips, and at the same ISA PC base addresses. The
+ * other is for ESP-specific enhanced features, and lies at a
+ * different addressing range entirely (0x140, 0x180, 0x280, or 0x300).
+ */
+
+ /* Test for ESP signature */
+ if ((bus_io_read_1(bc, hayespioh, 0) & 0xf3) == 0)
+ return 0;
+
+ /*
+ * ESP is present at ESP enhanced base address; unknown com port
+ */
+
+ /* Get the dip-switch configurations */
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
+ dips = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1);
+
+ /* Determine which com port this ESP card services: bits 0,1 of */
+ /* dips is the port # (0-3); combaselist[val] is the com_iobase */
+ if (sc->sc_iobase != combaselist[dips & 0x03])
+ return 0;
+
+ printf(": ESP");
+
+ /* Check ESP Self Test bits. */
+ /* Check for ESP version 2.0: bits 4,5,6 == 010 */
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
+ val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1); /* Clear reg 1 */
+ val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS2);
+ if ((val & 0x70) < 0x20) {
+ printf("-old (%o)", val & 0x70);
+ /* we do not support the necessary features */
+ return 0;
+ }
+
+ /* Check for ability to emulate 16550: bit 8 == 1 */
+ if ((dips & 0x80) == 0) {
+ printf(" slave");
+ /* XXX Does slave really mean no 16550 support?? */
+ return 0;
+ }
+
+ /*
+ * If we made it this far, we are a full-featured ESP v2.0 (or
+ * better), at the correct com port address.
+ */
+
+ SET(sc->sc_hwflags, COM_HW_HAYESP);
+ printf(", 1024 byte fifo\n");
+ return 1;
+}
+#endif
+
+int
+comprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ int iobase, needioh;
+ int rv = 1;
+
+#if NACE_ISA || NACE_PCMCIA
+#define IS_ISA(parent) \
+ (!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa") || \
+ !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pcmcia"))
+#elif NACE_ISA
+#define IS_ISA(parent) \
+ !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa")
+#endif
+#if NACE_PICA
+#define IS_PICA(parent) \
+ !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pica")
+#endif
+ /*
+ * XXX should be broken out into functions for isa probe and
+ * XXX for commulti probe, with a helper function that contains
+ * XXX most of the interesting stuff.
+ */
+#if NACE_ISA || NACE_PCMCIA
+ if (IS_ISA(parent)) {
+ struct isa_attach_args *ia = aux;
+
+ bc = ia->ia_bc;
+ iobase = ia->ia_iobase;
+ needioh = 1;
+ } else
+#endif
+#if NACE_PICA
+ if(IS_PICA(parent)) {
+ struct confargs *ca = aux;
+ if(!BUS_MATCHNAME(ca, "com"))
+ return(0);
+ iobase = (long)BUS_CVTADDR(ca);
+ bc = 0;
+ needioh = 1;
+ } else
+#endif
+#if NACE_COMMULTI
+ if (1) {
+ struct cfdata *cf = match;
+ struct commulti_attach_args *ca = aux;
+
+ if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
+ return (0);
+
+ bc = ca->ca_bc;
+ iobase = ca->ca_iobase;
+ ioh = ca->ca_ioh;
+ needioh = 0;
+ } else
+#endif
+ return(0); /* This cannot happen */
+
+ /* if it's in use as console, it's there. */
+ if (iobase == comconsaddr && !comconsattached)
+ goto out;
+
+ if (needioh && bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
+ rv = 0;
+ goto out;
+ }
+ rv = comprobe1(bc, ioh, iobase);
+ if (needioh)
+ bus_io_unmap(bc, ioh, COM_NPORTS);
+
+out:
+#if NACE_ISA || NACE_PCMCIA
+ if (rv && IS_ISA(parent)) {
+ struct isa_attach_args *ia = aux;
+
+ ia->ia_iosize = COM_NPORTS;
+ ia->ia_msize = 0;
+ }
+#endif
+ return (rv);
+}
+
+void
+comattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct com_softc *sc = (void *)self;
+ int iobase, irq;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+#ifdef COM_HAYESP
+ int hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
+ int *hayespp;
+#endif
+
+ /*
+ * XXX should be broken out into functions for isa attach and
+ * XXX for commulti attach, with a helper function that contains
+ * XXX most of the interesting stuff.
+ */
+ if (ISSET(sc->sc_hwflags, COM_HW_REATTACH)) {
+ int s;
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ } else
+ sc->sc_hwflags = 0;
+ sc->sc_swflags = 0;
+#if NACE_ISA || NACE_PCMCIA
+ if (IS_ISA(parent)) {
+ struct isa_attach_args *ia = aux;
+
+ /*
+ * We're living on an isa.
+ */
+ iobase = ia->ia_iobase;
+ bc = ia->ia_bc;
+ if (iobase != comconsaddr) {
+ if (bus_io_map(bc, iobase, COM_NPORTS, &ioh))
+ panic("comattach: io mapping failed");
+ } else
+ ioh = comconsioh;
+ irq = ia->ia_irq;
+ } else
+#endif
+#if NACE_PICA
+ if(IS_PICA(parent)) {
+ struct confargs *ca = aux;
+ iobase = (long)BUS_CVTADDR(ca);
+ bc = 0;
+ irq = 0;
+ ioh = iobase;
+ } else
+#endif
+#if NACE_COMMULTI
+ if (1) {
+ struct commulti_attach_args *ca = aux;
+
+ /*
+ * We're living on a commulti.
+ */
+ iobase = ca->ca_iobase;
+ bc = ca->ca_bc;
+ ioh = ca->ca_ioh;
+ irq = IRQUNK;
+
+ if (ca->ca_noien)
+ SET(sc->sc_hwflags, COM_HW_NOIEN);
+ } else
+#endif
+ panic("comattach: impossible");
+
+ sc->sc_bc = bc;
+ sc->sc_ioh = ioh;
+ sc->sc_iobase = iobase;
+
+ if (iobase == comconsaddr) {
+ comconsattached = 1;
+
+ /*
+ * Need to reset baud rate, etc. of next print so reset
+ * comconsinit. Also make sure console is always "hardwired".
+ */
+ delay(1000); /* wait for output to finish */
+ comconsinit = 0;
+ SET(sc->sc_hwflags, COM_HW_CONSOLE);
+ SET(sc->sc_swflags, COM_SW_SOFTCAR);
+ }
+
+#ifdef COM_HAYESP
+ /* Look for a Hayes ESP board. */
+ for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
+ bus_io_handle_t hayespioh;
+
+#define HAYESP_NPORTS 8 /* XXX XXX XXX ??? ??? ??? */
+ if (bus_io_map(bc, *hayespp, HAYESP_NPORTS, &hayespioh))
+ continue;
+ if (comprobeHAYESP(hayespioh, sc)) {
+ sc->sc_hayespbase = *hayespp;
+ sc->sc_hayespioh = hayespioh;
+ break;
+ }
+ bus_io_unmap(bc, hayespioh, HAYESP_NPORTS);
+ }
+ /* No ESP; look for other things. */
+ if (*hayespp == 0) {
+#endif
+
+ /* look for a NS 16550AF UART with FIFOs */
+ bus_io_write_1(bc, ioh, com_fifo,
+ FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
+ delay(100);
+ if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_FIFO_MASK) ==
+ IIR_FIFO_MASK)
+ if (ISSET(bus_io_read_1(bc, ioh, com_fifo), FIFO_TRIGGER_14) ==
+ FIFO_TRIGGER_14) {
+ SET(sc->sc_hwflags, COM_HW_FIFO);
+ printf(": ns16550a, working fifo\n");
+ } else
+ printf(": ns16550, broken fifo\n");
+ else
+ printf(": ns8250 or ns16450, no fifo\n");
+ bus_io_write_1(bc, ioh, com_fifo, 0);
+#ifdef COM_HAYESP
+ }
+#endif
+
+ /* disable interrupts */
+ bus_io_write_1(bc, ioh, com_ier, 0);
+ bus_io_write_1(bc, ioh, com_mcr, 0);
+
+ if (irq != IRQUNK) {
+#if NACE_ISA || NACE_PCMCIA
+ if (IS_ISA(parent)) {
+ struct isa_attach_args *ia = aux;
+
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
+ IST_EDGE, IPL_TTY, comintr, sc,
+ sc->sc_dev.dv_xname);
+ } else
+#endif
+#if NACE_PICA
+ if (IS_PICA(parent)) {
+ struct confargs *ca = aux;
+ BUS_INTR_ESTABLISH(ca, comintr, (void *)(long)sc);
+ } else
+#endif
+ panic("comattach: IRQ but can't have one");
+ }
+
+#ifdef KGDB
+ if (kgdb_dev == makedev(commajor, unit)) {
+ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+ kgdb_dev = -1; /* can't debug over console port */
+ else {
+ cominit(bc, ioh, kgdb_rate);
+ if (kgdb_debug_init) {
+ /*
+ * Print prefix of device name,
+ * let kgdb_connect print the rest.
+ */
+ printf("%s: ", sc->sc_dev.dv_xname);
+ kgdb_connect(1);
+ } else
+ printf("%s: kgdb enabled\n",
+ sc->sc_dev.dv_xname);
+ }
+ }
+#endif
+
+ /* XXX maybe move up some? */
+ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+ printf("%s: console\n", sc->sc_dev.dv_xname);
+}
+
+int
+comopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ int unit = COMUNIT(dev);
+ struct com_softc *sc;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ struct tty *tp;
+ int s;
+ int error = 0;
+
+ if (unit >= com_cd.cd_ndevs)
+ return ENXIO;
+ sc = com_cd.cd_devs[unit];
+ if (!sc || ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING))
+ return ENXIO;
+
+ if (!sc->sc_tty) {
+ tp = sc->sc_tty = ttymalloc();
+ tty_attach(tp);
+ } 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;
+ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+ tp->t_cflag = comconscflag;
+ else
+ tp->t_cflag = TTYDEF_CFLAG;
+ if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
+ SET(tp->t_cflag, CLOCAL);
+ if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
+ SET(tp->t_cflag, CRTSCTS);
+ if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
+ SET(tp->t_cflag, MDMBUF);
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = comdefaultrate;
+
+ s = spltty();
+
+ comparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+
+ if (comsopen++ == 0)
+ timeout(compoll, NULL, 1);
+
+ sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
+ sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
+ sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
+
+ bc = sc->sc_bc;
+ ioh = sc->sc_ioh;
+#ifdef COM_HAYESP
+ /* Setup the ESP board */
+ if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
+ bus_io_handle_t hayespioh = sc->sc_hayespioh;
+
+ bus_io_write_1(bc, ioh, com_fifo,
+ FIFO_DMA_MODE|FIFO_ENABLE|
+ FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);
+
+ /* Set 16550 compatibility mode */
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
+ HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
+ HAYESP_MODE_SCALE);
+
+ /* Set RTS/CTS flow control */
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE);
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS);
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS);
+
+ /* Set flow control levels */
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW);
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
+ HAYESP_HIBYTE(HAYESP_RXHIWMARK));
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
+ HAYESP_LOBYTE(HAYESP_RXHIWMARK));
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
+ HAYESP_HIBYTE(HAYESP_RXLOWMARK));
+ bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
+ HAYESP_LOBYTE(HAYESP_RXLOWMARK));
+ } else
+#endif
+ if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
+ /* Set the FIFO threshold based on the receive speed. */
+ bus_io_write_1(bc, ioh, com_fifo,
+ FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
+ (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+ /* flush any pending I/O */
+ while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
+ (void) bus_io_read_1(bc, ioh, com_data);
+ /* you turn me on, baby */
+ sc->sc_mcr = MCR_DTR | MCR_RTS;
+ if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
+ SET(sc->sc_mcr, MCR_IENABLE);
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
+ bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
+
+ sc->sc_msr = bus_io_read_1(bc, ioh, com_msr);
+ if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) ||
+ 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;
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
+ int s;
+
+ /* XXX This is for cons.c. */
+ if (!ISSET(tp->t_state, TS_ISOPEN))
+ return 0;
+
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ s = spltty();
+ if (!ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ /* can't do any of this stuff .... */
+ CLR(sc->sc_lcr, LCR_SBREAK);
+ bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
+ bus_io_write_1(bc, ioh, com_ier, 0);
+ if (ISSET(tp->t_cflag, HUPCL) &&
+ !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
+ /* XXX perhaps only clear DTR */
+ bus_io_write_1(bc, ioh, com_mcr, 0);
+ }
+ }
+ CLR(tp->t_state, TS_BUSY | TS_FLUSH);
+ if (--comsopen == 0)
+ untimeout(compoll, NULL);
+ splx(s);
+ ttyclose(tp);
+#ifdef COM_DEBUG
+ /* mark it ready for more use if reattached earlier */
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
+ printf("comclose pending cleared\n");
+ }
+#endif
+ CLR(sc->sc_hwflags, COM_HW_ABSENT_PENDING);
+
+#ifdef notyet /* XXXX */
+ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
+ ttyfree(tp);
+ sc->sc_tty = 0;
+ }
+#endif
+ return 0;
+}
+
+int
+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;
+
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+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;
+
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+struct tty *
+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;
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
+ int error;
+
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
+ error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return error;
+ error = ttioctl(tp, cmd, data, flag, p);
+ if (error >= 0)
+ return error;
+
+ switch (cmd) {
+ case TIOCSBRK:
+ SET(sc->sc_lcr, LCR_SBREAK);
+ bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
+ break;
+ case TIOCCBRK:
+ CLR(sc->sc_lcr, LCR_SBREAK);
+ bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
+ break;
+ case TIOCSDTR:
+ SET(sc->sc_mcr, sc->sc_dtr);
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ break;
+ case TIOCCDTR:
+ CLR(sc->sc_mcr, sc->sc_dtr);
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ break;
+ case TIOCMSET:
+ CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
+ case TIOCMBIS:
+ SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ break;
+ case TIOCMBIC:
+ CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ break;
+ case TIOCMGET: {
+ u_char m;
+ int bits = 0;
+
+ m = sc->sc_mcr;
+ if (ISSET(m, MCR_DTR))
+ SET(bits, TIOCM_DTR);
+ if (ISSET(m, MCR_RTS))
+ SET(bits, TIOCM_RTS);
+ m = sc->sc_msr;
+ if (ISSET(m, MSR_DCD))
+ SET(bits, TIOCM_CD);
+ if (ISSET(m, MSR_CTS))
+ SET(bits, TIOCM_CTS);
+ if (ISSET(m, MSR_DSR))
+ SET(bits, TIOCM_DSR);
+ if (ISSET(m, MSR_RI | MSR_TERI))
+ SET(bits, TIOCM_RI);
+ if (bus_io_read_1(bc, ioh, com_ier))
+ SET(bits, TIOCM_LE);
+ *(int *)data = bits;
+ break;
+ }
+ case TIOCGFLAGS: {
+ int driverbits, userbits = 0;
+
+ driverbits = sc->sc_swflags;
+ if (ISSET(driverbits, COM_SW_SOFTCAR))
+ SET(userbits, TIOCFLAG_SOFTCAR);
+ if (ISSET(driverbits, COM_SW_CLOCAL))
+ SET(userbits, TIOCFLAG_CLOCAL);
+ if (ISSET(driverbits, COM_SW_CRTSCTS))
+ SET(userbits, TIOCFLAG_CRTSCTS);
+ if (ISSET(driverbits, COM_SW_MDMBUF))
+ SET(userbits, TIOCFLAG_MDMBUF);
+
+ *(int *)data = userbits;
+ break;
+ }
+ case TIOCSFLAGS: {
+ int userbits, driverbits = 0;
+
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error != 0)
+ return(EPERM);
+
+ userbits = *(int *)data;
+ if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
+ ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+ SET(driverbits, COM_SW_SOFTCAR);
+ if (ISSET(userbits, TIOCFLAG_CLOCAL))
+ SET(driverbits, COM_SW_CLOCAL);
+ if (ISSET(userbits, TIOCFLAG_CRTSCTS))
+ SET(driverbits, COM_SW_CRTSCTS);
+ if (ISSET(userbits, TIOCFLAG_MDMBUF))
+ SET(driverbits, COM_SW_MDMBUF);
+
+ sc->sc_swflags = driverbits;
+ break;
+ }
+ default:
+ return ENOTTY;
+ }
+
+ return 0;
+}
+
+int
+comparam(tp, t)
+ struct tty *tp;
+ struct termios *t;
+{
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
+ int ospeed = comspeed(t->c_ospeed);
+ u_char lcr;
+ tcflag_t oldcflag;
+ int s;
+
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
+ /* check requested parameters */
+ if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
+ return EINVAL;
+
+ lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
+
+ switch (ISSET(t->c_cflag, CSIZE)) {
+ case CS5:
+ SET(lcr, LCR_5BITS);
+ break;
+ case CS6:
+ SET(lcr, LCR_6BITS);
+ break;
+ case CS7:
+ SET(lcr, LCR_7BITS);
+ break;
+ case CS8:
+ SET(lcr, LCR_8BITS);
+ break;
+ }
+ if (ISSET(t->c_cflag, PARENB)) {
+ SET(lcr, LCR_PENAB);
+ if (!ISSET(t->c_cflag, PARODD))
+ SET(lcr, LCR_PEVEN);
+ }
+ if (ISSET(t->c_cflag, CSTOPB))
+ SET(lcr, LCR_STOPB);
+
+ sc->sc_lcr = lcr;
+
+ s = spltty();
+
+ if (ospeed == 0) {
+ CLR(sc->sc_mcr, MCR_DTR);
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ }
+
+ /*
+ * Set the FIFO threshold based on the receive speed, if we are
+ * changing it.
+ */
+#if 1
+ if (tp->t_ispeed != t->c_ispeed) {
+#else
+ if (1) {
+#endif
+ if (ospeed != 0) {
+ /*
+ * Make sure the transmit FIFO is empty before
+ * proceeding. If we don't do this, some revisions
+ * of the UART will hang. Interestingly enough,
+ * even if we do this will the last character is
+ * still being pushed out, they don't hang. This
+ * seems good enough.
+ */
+ while (ISSET(tp->t_state, TS_BUSY)) {
+ int error;
+
+ ++sc->sc_halt;
+ error = ttysleep(tp, &tp->t_outq,
+ TTOPRI | PCATCH, "comprm", 0);
+ --sc->sc_halt;
+ if (error) {
+ splx(s);
+ comstart(tp);
+ return (error);
+ }
+ }
+
+ bus_io_write_1(bc, ioh, com_lcr, lcr | LCR_DLAB);
+ bus_io_write_1(bc, ioh, com_dlbl, ospeed);
+ bus_io_write_1(bc, ioh, com_dlbh, ospeed >> 8);
+ bus_io_write_1(bc, ioh, com_lcr, lcr);
+ SET(sc->sc_mcr, MCR_DTR);
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ } else
+ bus_io_write_1(bc, ioh, com_lcr, lcr);
+
+ if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) &&
+ ISSET(sc->sc_hwflags, COM_HW_FIFO))
+ bus_io_write_1(bc, ioh, com_fifo,
+ FIFO_ENABLE |
+ (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
+ } else
+ bus_io_write_1(bc, ioh, com_lcr, lcr);
+
+ /* When not using CRTSCTS, RTS follows DTR. */
+ if (!ISSET(t->c_cflag, CRTSCTS)) {
+ if (ISSET(sc->sc_mcr, MCR_DTR)) {
+ if (!ISSET(sc->sc_mcr, MCR_RTS)) {
+ SET(sc->sc_mcr, MCR_RTS);
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ }
+ } else {
+ if (ISSET(sc->sc_mcr, MCR_RTS)) {
+ CLR(sc->sc_mcr, MCR_RTS);
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ }
+ }
+ sc->sc_dtr = MCR_DTR | MCR_RTS;
+ } else
+ sc->sc_dtr = MCR_DTR;
+
+ /* and copy to tty */
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ oldcflag = tp->t_cflag;
+ tp->t_cflag = t->c_cflag;
+
+ /*
+ * If DCD is off and MDMBUF is changed, ask the tty layer if we should
+ * stop the device.
+ */
+ if (!ISSET(sc->sc_msr, MSR_DCD) &&
+ !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
+ ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
+ (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
+ CLR(sc->sc_mcr, sc->sc_dtr);
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ }
+
+ /* Just to be sure... */
+ splx(s);
+ comstart(tp);
+ return 0;
+}
+
+void
+comstart_pending(arg)
+ void *arg;
+{
+ struct com_softc *sc = arg;
+ int s;
+
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+}
+
+void
+comstart(tp)
+ struct tty *tp;
+{
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
+ int s;
+
+ s = spltty();
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ /*
+ * not quite good enough: if caller is ttywait() it will
+ * go to sleep immediately, so hang out a bit and then
+ * prod caller again.
+ */
+ com_absent_notify(sc);
+ timeout(comstart_pending, sc, 1);
+ goto out;
+ }
+ if (ISSET(tp->t_state, TS_BUSY))
+ goto out;
+ if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) ||
+ sc->sc_halt > 0)
+ goto stopped;
+ if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
+ goto stopped;
+ if (tp->t_outq.c_cc <= tp->t_lowat) {
+ if (ISSET(tp->t_state, TS_ASLEEP)) {
+ CLR(tp->t_state, TS_ASLEEP);
+ wakeup(&tp->t_outq);
+ }
+ if (tp->t_outq.c_cc == 0)
+ goto stopped;
+ selwakeup(&tp->t_wsel);
+ }
+ SET(tp->t_state, TS_BUSY);
+
+ if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
+ SET(sc->sc_ier, IER_ETXRDY);
+ bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
+ }
+#ifdef COM_HAYESP
+ if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
+ u_char buffer[1024], *cp = buffer;
+ int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
+ do
+ bus_io_write_1(bc, ioh, com_data, *cp++);
+ while (--n);
+ }
+ else
+#endif
+ if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
+ u_char buffer[16], *cp = buffer;
+ int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
+ do {
+ bus_io_write_1(bc, ioh, com_data, *cp++);
+ } while (--n);
+ } else
+ bus_io_write_1(bc, ioh, com_data, getc(&tp->t_outq));
+out:
+ splx(s);
+ return;
+stopped:
+ if (ISSET(sc->sc_ier, IER_ETXRDY)) {
+ CLR(sc->sc_ier, IER_ETXRDY);
+ bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
+ }
+ splx(s);
+}
+
+/*
+ * Stop output on a line.
+ */
+int
+comstop(tp, flag)
+ struct tty *tp;
+ int flag;
+{
+ int s;
+
+ s = spltty();
+ if (ISSET(tp->t_state, TS_BUSY))
+ if (!ISSET(tp->t_state, TS_TTSTOP))
+ SET(tp->t_state, TS_FLUSH);
+ splx(s);
+ return 0;
+}
+
+void
+comdiag(arg)
+ void *arg;
+{
+ struct com_softc *sc = arg;
+ int overflows, floods;
+ int s;
+
+ s = spltty();
+ sc->sc_errors = 0;
+ overflows = sc->sc_overflows;
+ sc->sc_overflows = 0;
+ floods = sc->sc_floods;
+ sc->sc_floods = 0;
+ splx(s);
+
+ log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
+ sc->sc_dev.dv_xname,
+ overflows, overflows == 1 ? "" : "s",
+ floods, floods == 1 ? "" : "s");
+}
+
+void
+compoll(arg)
+ void *arg;
+{
+ int unit;
+ struct com_softc *sc;
+ struct tty *tp;
+ register u_char *ibufp;
+ u_char *ibufend;
+ register int c;
+ int s;
+ static int lsrmap[8] = {
+ 0, TTY_PE,
+ TTY_FE, TTY_PE|TTY_FE,
+ TTY_FE, TTY_PE|TTY_FE,
+ TTY_FE, TTY_PE|TTY_FE
+ };
+
+ s = spltty();
+ if (comevents == 0) {
+ splx(s);
+ goto out;
+ }
+ comevents = 0;
+ splx(s);
+
+ for (unit = 0; unit < 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);
+ bus_io_write_1(sc->sc_bc, sc->sc_ioh, com_mcr,
+ sc->sc_mcr);
+ }
+
+ splx(s);
+
+ while (ibufp < ibufend) {
+ c = *ibufp++;
+ if (*ibufp & LSR_OE) {
+ sc->sc_overflows++;
+ if (sc->sc_errors++ == 0)
+ timeout(comdiag, sc, 60 * hz);
+ }
+ /* This is ugly, but fast. */
+ c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
+ (*linesw[tp->t_line].l_rint)(c, tp);
+ }
+ }
+
+out:
+ timeout(compoll, NULL, 1);
+}
+
+int
+comintr(arg)
+ void *arg;
+{
+ struct com_softc *sc = arg;
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
+ struct tty *tp;
+ u_char lsr, data, msr, delta;
+#ifdef COM_DEBUG
+ int n;
+ struct {
+ u_char iir, lsr, msr;
+ } iter[32];
+#endif
+
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT) || !sc->sc_tty)
+ return 0; /* can't do squat. */
+
+#ifdef COM_DEBUG
+ n = 0;
+ if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
+ return (0);
+#else
+ if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
+ return (0);
+#endif
+
+ tp = sc->sc_tty;
+
+ for (;;) {
+#ifdef COM_DEBUG
+ iter[n].lsr =
+#endif
+ lsr = bus_io_read_1(bc, ioh, com_lsr);
+
+ if (ISSET(lsr, LSR_RXRDY)) {
+ register u_char *p = sc->sc_ibufp;
+
+ comevents = 1;
+ do {
+ data = bus_io_read_1(bc, ioh, com_data);
+ if (ISSET(lsr, LSR_BI)) {
+#ifdef notdef
+ printf("break %02x %02x %02x %02x\n",
+ sc->sc_msr, sc->sc_mcr, sc->sc_lcr,
+ sc->sc_dtr);
+#endif
+#ifdef DDB
+ if (ISSET(sc->sc_hwflags,
+ COM_HW_CONSOLE)) {
+ Debugger();
+ goto next;
+ }
+#endif
+ }
+ if (p >= sc->sc_ibufend) {
+ sc->sc_floods++;
+ if (sc->sc_errors++ == 0)
+ timeout(comdiag, sc, 60 * hz);
+ } else {
+ *p++ = data;
+ *p++ = lsr;
+ if (p == sc->sc_ibufhigh &&
+ ISSET(tp->t_cflag, CRTSCTS)) {
+ /* XXX */
+ CLR(sc->sc_mcr, MCR_RTS);
+ bus_io_write_1(bc, ioh, com_mcr,
+ sc->sc_mcr);
+ }
+ }
+ next:
+#ifdef COM_DEBUG
+ if (++n >= 32)
+ goto ohfudge;
+ iter[n].lsr =
+#endif
+ lsr = bus_io_read_1(bc, ioh, com_lsr);
+ } while (ISSET(lsr, LSR_RXRDY));
+
+ sc->sc_ibufp = p;
+ }
+#ifdef COM_DEBUG
+ else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
+ printf("weird lsr %02x\n", lsr);
+#endif
+
+#ifdef COM_DEBUG
+ iter[n].msr =
+#endif
+ msr = bus_io_read_1(bc, ioh, com_msr);
+
+ if (msr != sc->sc_msr) {
+ delta = msr ^ sc->sc_msr;
+ sc->sc_msr = msr;
+ if (ISSET(delta, MSR_DCD) &&
+ !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
+ (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
+ CLR(sc->sc_mcr, sc->sc_dtr);
+ bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
+ }
+ if (ISSET(delta & msr, MSR_CTS) &&
+ ISSET(tp->t_cflag, CRTSCTS)) {
+ /* the line is up and we want to do rts/cts flow control */
+ (*linesw[tp->t_line].l_start)(tp);
+ }
+ }
+
+ if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
+ CLR(tp->t_state, TS_BUSY | TS_FLUSH);
+ if (sc->sc_halt > 0)
+ wakeup(&tp->t_outq);
+ (*linesw[tp->t_line].l_start)(tp);
+ }
+
+#ifdef COM_DEBUG
+ if (++n >= 32)
+ goto ohfudge;
+ if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
+ return (1);
+#else
+ if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
+ return (1);
+#endif
+ }
+#ifdef COM_DEBUG
+ohfudge:
+ printf("comintr: too many iterations");
+ for (n = 0; n < 32; n++) {
+ if ((n % 4) == 0)
+ printf("\ncomintr: iter[%02d]", n);
+ printf(" %02x %02x %02x", iter[n].iir, iter[n].lsr, iter[n].msr);
+ }
+ printf("\n");
+ printf("comintr: msr %02x mcr %02x lcr %02x ier %02x\n",
+ sc->sc_msr, sc->sc_mcr, sc->sc_lcr, sc->sc_ier);
+ printf("comintr: state %08x cc %d\n", sc->sc_tty->t_state,
+ sc->sc_tty->t_outq.c_cc);
+#endif
+}
+
+/*
+ * Following are all routines needed for COM to act as console
+ */
+#include <dev/cons.h>
+
+void
+comcnprobe(cp)
+ struct consdev *cp;
+{
+ /* XXX NEEDS TO BE FIXED XXX */
+ bus_chipset_tag_t bc = 0;
+ bus_io_handle_t ioh;
+ int found;
+
+#if 0
+ if (bus_io_map(bc, CONADDR, COM_NPORTS, &ioh)) {
+ cp->cn_pri = CN_DEAD;
+ return;
+ }
+#else
+ ioh = CONADDR;
+#endif
+ found = comprobe1(bc, ioh, CONADDR);
+ bus_io_unmap(bc, ioh, COM_NPORTS);
+ if (!found) {
+ 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;
+{
+
+#if 0
+ XXX NEEDS TO BE FIXED XXX
+ comconsbc = ???;
+#endif
+ if (bus_io_map(comconsbc, CONADDR, COM_NPORTS, &comconsioh))
+ panic("comcninit: mapping failed");
+
+ cominit(comconsbc, comconsioh, comdefaultrate);
+ comconsaddr = CONADDR;
+ comconsinit = 0;
+}
+
+void
+cominit(bc, ioh, rate)
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ int rate;
+{
+ int s = splhigh();
+ u_char stat;
+
+ bus_io_write_1(bc, ioh, com_lcr, LCR_DLAB);
+ rate = comspeed(comdefaultrate);
+ bus_io_write_1(bc, ioh, com_dlbl, rate);
+ bus_io_write_1(bc, ioh, com_dlbh, rate >> 8);
+ bus_io_write_1(bc, ioh, com_lcr, LCR_8BITS);
+ bus_io_write_1(bc, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
+ bus_io_write_1(bc, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
+ stat = bus_io_read_1(bc, ioh, com_iir);
+ splx(s);
+}
+
+int
+comcngetc(dev)
+ dev_t dev;
+{
+ int s = splhigh();
+ bus_chipset_tag_t bc = comconsbc;
+ bus_io_handle_t ioh = comconsioh;
+ u_char stat, c;
+
+ while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
+ ;
+ c = bus_io_read_1(bc, ioh, com_data);
+ stat = bus_io_read_1(bc, ioh, com_iir);
+ splx(s);
+ return c;
+}
+
+/*
+ * Console kernel output character routine.
+ */
+void
+comcnputc(dev, c)
+ dev_t dev;
+ int c;
+{
+ int s = splhigh();
+ bus_chipset_tag_t bc = comconsbc;
+ bus_io_handle_t ioh = comconsioh;
+ u_char stat;
+ register int timo;
+
+#ifdef KGDB
+ if (dev != kgdb_dev)
+#endif
+ if (comconsinit == 0) {
+ cominit(bc, ioh, comdefaultrate);
+ comconsinit = 1;
+ }
+ /* wait for any pending transmission to finish */
+ timo = 50000;
+ while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
+ ;
+ bus_io_write_1(bc, ioh, com_data, c);
+ /* wait for this transmission to complete */
+ timo = 1500000;
+ while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
+ ;
+ /* clear any interrupts generated by this transmission */
+ stat = bus_io_read_1(bc, ioh, com_iir);
+ splx(s);
+}
+
+void
+comcnpollc(dev, on)
+ dev_t dev;
+ int on;
+{
+
+}
diff --git a/sys/arch/arc/dev/asc.c b/sys/arch/arc/dev/asc.c
new file mode 100644
index 00000000000..0a8af5464b9
--- /dev/null
+++ b/sys/arch/arc/dev/asc.c
@@ -0,0 +1,2074 @@
+/* $OpenBSD: asc.c,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/* $NetBSD: asc.c,v 1.10 1994/12/05 19:11:12 dean Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)asc.c 8.3 (Berkeley) 7/3/94
+ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * HISTORY
+ * Log: scsi_53C94_hdw.c,v
+ * Revision 2.5 91/02/05 17:45:07 mrt
+ * Added author notices
+ * [91/02/04 11:18:43 mrt]
+ *
+ * Changed to use new Mach copyright
+ * [91/02/02 12:17:20 mrt]
+ *
+ * Revision 2.4 91/01/08 15:48:24 rpd
+ * Added continuation argument to thread_block.
+ * [90/12/27 rpd]
+ *
+ * Revision 2.3 90/12/05 23:34:48 af
+ * Recovered from pmax merge.. and from the destruction of a disk.
+ * [90/12/03 23:40:40 af]
+ *
+ * Revision 2.1.1.1 90/11/01 03:39:09 af
+ * Created, from the DEC specs:
+ * "PMAZ-AA TURBOchannel SCSI Module Functional Specification"
+ * Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990.
+ * And from the NCR data sheets
+ * "NCR 53C94, 53C95, 53C96 Advances SCSI Controller"
+ * [90/09/03 af]
+ */
+
+/*
+ * File: scsi_53C94_hdw.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Bottom layer of the SCSI driver: chip-dependent functions
+ *
+ * This file contains the code that is specific to the NCR 53C94
+ * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start
+ * operation, and interrupt routine.
+ */
+
+/*
+ * This layer works based on small simple 'scripts' that are installed
+ * at the start of the command and drive the chip to completion.
+ * The idea comes from the specs of the NCR 53C700 'script' processor.
+ *
+ * There are various reasons for this, mainly
+ * - Performance: identify the common (successful) path, and follow it;
+ * at interrupt time no code is needed to find the current status
+ * - Code size: it should be easy to compact common operations
+ * - Adaptability: the code skeleton should adapt to different chips without
+ * terrible complications.
+ * - Error handling: and it is easy to modify the actions performed
+ * by the scripts to cope with strange but well identified sequences
+ *
+ */
+
+#include <asc.h>
+#if NASC > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/dkstat.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+
+#include <arc/dev/dma.h>
+#include <arc/dev/scsi.h>
+#include <arc/dev/ascreg.h>
+
+#include <arc/pica/pica.h>
+#include <arc/arc/arctype.h>
+
+
+#define readback(a) { register int foo; foo = (a); }
+extern int cputype;
+
+/*
+ * In 4ns ticks.
+ */
+int asc_to_scsi_period[] = {
+ 32,
+ 33,
+ 34,
+ 35,
+ 5,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+};
+
+/*
+ * Internal forward declarations.
+ */
+static void asc_reset();
+static void asc_startcmd();
+
+#ifdef DEBUG
+int asc_debug = 1;
+int asc_debug_cmd;
+int asc_debug_bn;
+int asc_debug_sz;
+#define NLOG 16
+struct asc_log {
+ u_int status;
+ u_char state;
+ u_char msg;
+ int target;
+ int resid;
+} asc_log[NLOG], *asc_logp = asc_log;
+#define PACK(unit, status, ss, ir) \
+ ((unit << 24) | (status << 16) | (ss << 8) | ir)
+#endif
+
+/*
+ * Scripts are entries in a state machine table.
+ * A script has four parts: a pre-condition, an action, a command to the chip,
+ * and an index into asc_scripts for the next state. The first triggers error
+ * handling if not satisfied and in our case it is formed by the
+ * values of the interrupt register and status register, this
+ * basically captures the phase of the bus and the TC and BS
+ * bits. The action part is just a function pointer, and the
+ * command is what the 53C94 should be told to do at the end
+ * of the action processing. This command is only issued and the
+ * script proceeds if the action routine returns TRUE.
+ * See asc_intr() for how and where this is all done.
+ */
+typedef struct script {
+ int condition; /* expected state at interrupt time */
+ int (*action)(); /* extra operations */
+ int command; /* command to the chip */
+ struct script *next; /* index into asc_scripts for next state */
+} script_t;
+
+/* Matching on the condition value */
+#define SCRIPT_MATCH(ir, csr) ((ir) | (((csr) & 0x67) << 8))
+
+/* forward decls of script actions */
+static int script_nop(); /* when nothing needed */
+static int asc_end(); /* all come to an end */
+static int asc_get_status(); /* get status from target */
+static int asc_dma_in(); /* start reading data from target */
+static int asc_last_dma_in(); /* cleanup after all data is read */
+static int asc_resume_in(); /* resume data in after a message */
+static int asc_resume_dma_in(); /* resume DMA after a disconnect */
+static int asc_dma_out(); /* send data to target via dma */
+static int asc_last_dma_out(); /* cleanup after all data is written */
+static int asc_resume_out(); /* resume data out after a message */
+static int asc_resume_dma_out(); /* resume DMA after a disconnect */
+static int asc_sendsync(); /* negotiate sync xfer */
+static int asc_replysync(); /* negotiate sync xfer */
+static int asc_msg_in(); /* process a message byte */
+static int asc_disconnect(); /* process an expected disconnect */
+
+/* Define the index into asc_scripts for various state transitions */
+#define SCRIPT_DATA_IN 0
+#define SCRIPT_CONTINUE_IN 2
+#define SCRIPT_DATA_OUT 3
+#define SCRIPT_CONTINUE_OUT 5
+#define SCRIPT_SIMPLE 6
+#define SCRIPT_GET_STATUS 7
+#define SCRIPT_DONE 8
+#define SCRIPT_MSG_IN 9
+#define SCRIPT_REPLY_SYNC 11
+#define SCRIPT_TRY_SYNC 12
+#define SCRIPT_DISCONNECT 15
+#define SCRIPT_RESEL 16
+#define SCRIPT_RESUME_IN 17
+#define SCRIPT_RESUME_DMA_IN 18
+#define SCRIPT_RESUME_OUT 19
+#define SCRIPT_RESUME_DMA_OUT 20
+#define SCRIPT_RESUME_NO_DATA 21
+
+/*
+ * Scripts
+ */
+script_t asc_scripts[] = {
+ /* start data in */
+ {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAI), /* 0 */
+ asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+ &asc_scripts[SCRIPT_DATA_IN + 1]},
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 1 */
+ asc_last_dma_in, ASC_CMD_I_COMPLETE,
+ &asc_scripts[SCRIPT_GET_STATUS]},
+
+ /* continue data in after a chunk is finished */
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 2 */
+ asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+ &asc_scripts[SCRIPT_DATA_IN + 1]},
+
+ /* start data out */
+ {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAO), /* 3 */
+ asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+ &asc_scripts[SCRIPT_DATA_OUT + 1]},
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 4 */
+ asc_last_dma_out, ASC_CMD_I_COMPLETE,
+ &asc_scripts[SCRIPT_GET_STATUS]},
+
+ /* continue data out after a chunk is finished */
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 5 */
+ asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+ &asc_scripts[SCRIPT_DATA_OUT + 1]},
+
+ /* simple command with no data transfer */
+ {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_STATUS), /* 6 */
+ script_nop, ASC_CMD_I_COMPLETE,
+ &asc_scripts[SCRIPT_GET_STATUS]},
+
+ /* get status and finish command */
+ {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 7 */
+ asc_get_status, ASC_CMD_MSG_ACPT,
+ &asc_scripts[SCRIPT_DONE]},
+ {SCRIPT_MATCH(ASC_INT_DISC, 0), /* 8 */
+ asc_end, ASC_CMD_NOP,
+ &asc_scripts[SCRIPT_DONE]},
+
+ /* message in */
+ {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 9 */
+ asc_msg_in, ASC_CMD_MSG_ACPT,
+ &asc_scripts[SCRIPT_MSG_IN + 1]},
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 10 */
+ script_nop, ASC_CMD_XFER_INFO,
+ &asc_scripts[SCRIPT_MSG_IN]},
+
+ /* send synchonous negotiation reply */
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 11 */
+ asc_replysync, ASC_CMD_XFER_INFO,
+ &asc_scripts[SCRIPT_REPLY_SYNC]},
+
+ /* try to negotiate synchonous transfer parameters */
+ {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 12 */
+ asc_sendsync, ASC_CMD_XFER_INFO,
+ &asc_scripts[SCRIPT_TRY_SYNC + 1]},
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 13 */
+ script_nop, ASC_CMD_XFER_INFO,
+ &asc_scripts[SCRIPT_MSG_IN]},
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_COMMAND), /* 14 */
+ script_nop, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+ &asc_scripts[SCRIPT_RESUME_NO_DATA]},
+
+ /* handle a disconnect */
+ {SCRIPT_MATCH(ASC_INT_DISC, ASC_PHASE_DATAO), /* 15 */
+ asc_disconnect, ASC_CMD_ENABLE_SEL,
+ &asc_scripts[SCRIPT_RESEL]},
+
+ /* reselect sequence: this is just a placeholder so match fails */
+ {SCRIPT_MATCH(0, ASC_PHASE_MSG_IN), /* 16 */
+ script_nop, ASC_CMD_MSG_ACPT,
+ &asc_scripts[SCRIPT_RESEL]},
+
+ /* resume data in after a message */
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 17 */
+ asc_resume_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+ &asc_scripts[SCRIPT_DATA_IN + 1]},
+
+ /* resume partial DMA data in after a message */
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 18 */
+ asc_resume_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+ &asc_scripts[SCRIPT_DATA_IN + 1]},
+
+ /* resume data out after a message */
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 19 */
+ asc_resume_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+ &asc_scripts[SCRIPT_DATA_OUT + 1]},
+
+ /* resume partial DMA data out after a message */
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 20 */
+ asc_resume_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
+ &asc_scripts[SCRIPT_DATA_OUT + 1]},
+
+ /* resume after a message when there is no more data */
+ {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 21 */
+ script_nop, ASC_CMD_I_COMPLETE,
+ &asc_scripts[SCRIPT_GET_STATUS]},
+};
+
+/*
+ * State kept for each active SCSI device.
+ */
+typedef struct scsi_state {
+ script_t *script; /* saved script while processing error */
+ struct scsi_generic cmd;/* storage for scsi command */
+ int statusByte; /* status byte returned during STATUS_PHASE */
+ u_int dmaBufSize; /* DMA buffer size */
+ int dmalen; /* amount to transfer in this chunk */
+ int dmaresid; /* amount not transfered if chunk suspended */
+ int cmdlen; /* length of command in cmd */
+ int buflen; /* total remaining amount of data to transfer */
+ vm_offset_t buf; /* current pointer within scsicmd->buf */
+ int flags; /* see below */
+ int msglen; /* number of message bytes to read */
+ int msgcnt; /* number of message bytes received */
+ u_char sync_period; /* DMA synchronous period */
+ u_char sync_offset; /* DMA synchronous xfer offset or 0 if async */
+ u_char msg_out; /* next MSG_OUT byte to send */
+ u_char msg_in[16]; /* buffer for multibyte messages */
+} State;
+
+/* state flags */
+#define DISCONN 0x001 /* true if currently disconnected from bus */
+#define DMA_IN_PROGRESS 0x002 /* true if data DMA started */
+#define DMA_IN 0x004 /* true if reading from SCSI device */
+#define DMA_OUT 0x010 /* true if writing to SCSI device */
+#define DID_SYNC 0x020 /* true if synchronous offset was negotiated */
+#define TRY_SYNC 0x040 /* true if try neg. synchronous offset */
+#define PARITY_ERR 0x080 /* true if parity error seen */
+#define CHECK_SENSE 0x100 /* true if doing sense command */
+
+/*
+ * State kept for each active SCSI host interface (53C94).
+ */
+struct asc_softc {
+ struct device sc_dev; /* use as a device */
+ asc_regmap_t *regs; /* chip address */
+ dma_softc_t __dma; /* stupid macro..... */
+ dma_softc_t *dma; /* dma control structure */
+ int sc_id; /* SCSI ID of this interface */
+ int myidmask; /* ~(1 << myid) */
+ int state; /* current SCSI connection state */
+ int target; /* target SCSI ID if busy */
+ script_t *script; /* next expected interrupt & action */
+ struct scsi_xfer *cmdq[ASC_NCMD];/* Pointer to queued commands */
+ struct scsi_xfer *cmd[ASC_NCMD];/* Pointer to current active command */
+ State st[ASC_NCMD]; /* state info for each active command */
+ int min_period; /* Min transfer period clk/byte */
+ int max_period; /* Max transfer period clk/byte */
+ int ccf; /* CCF, whatever that really is? */
+ int timeout_250; /* 250ms timeout */
+ int tb_ticks; /* 4ns. ticks/tb channel ticks */
+ struct scsi_link sc_link; /* scsi link struct */
+};
+
+#define ASC_STATE_IDLE 0 /* idle state */
+#define ASC_STATE_BUSY 1 /* selecting or currently connected */
+#define ASC_STATE_TARGET 2 /* currently selected as target */
+#define ASC_STATE_RESEL 3 /* currently waiting for reselect */
+
+typedef struct asc_softc *asc_softc_t;
+
+/*
+ * Autoconfiguration data for config.
+ */
+int ascmatch __P((struct device *, void *, void *));
+void ascattach __P((struct device *, struct device *, void *));
+int ascprint(void *, char *);
+
+int asc_doprobe __P((void *, int, int, struct device *));
+
+struct cfattach asc_ca = {
+ sizeof(struct asc_softc), ascmatch, ascattach
+};
+struct cfdriver asc_cd = {
+ NULL, "asc", DV_DULL, NULL, 0
+};
+
+/*
+ * Glue to the machine dependent scsi
+ */
+int asc_scsi_cmd __P((struct scsi_xfer *));
+void asc_minphys __P((struct buf *));
+
+struct scsi_adapter asc_switch = {
+ asc_scsi_cmd,
+/*XXX*/ asc_minphys, /* no max transfer size, DMA driver negotiates */
+ NULL,
+ NULL,
+};
+
+struct scsi_device asc_dev = {
+/*XXX*/ NULL, /* Use default error handler */
+/*XXX*/ NULL, /* have a queue, served by this */
+/*XXX*/ NULL, /* have no async handler */
+/*XXX*/ NULL, /* Use default 'done' routine */
+};
+
+static int asc_probe();
+static void asc_start();
+static int asc_intr();
+
+/*
+ * Match driver based on name
+ */
+int
+ascmatch(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ struct cfdata *cf = match;
+ struct confargs *ca = aux;
+
+ if(!BUS_MATCHNAME(ca, "asc"))
+ return(0);
+ return(1);
+}
+
+void
+ascattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ register struct confargs *ca = aux;
+ register asc_softc_t asc = (void *)self;
+ register asc_regmap_t *regs;
+ int id, s, i;
+ int bufsiz;
+
+ /*
+ * Initialize hw descriptor, cache some pointers
+ */
+ asc->regs = (asc_regmap_t *)BUS_CVTADDR(ca);
+
+ /*
+ * Set up machine dependencies.
+ * 1) how to do dma
+ * 2) timing based on chip clock frequency
+ */
+ switch (cputype) {
+ case ACER_PICA_61:
+ bufsiz = 63 * 1024; /*XXX check if code handles 0 as 64k */
+ asc->dma = &asc->__dma;
+ asc_dma_init(asc->dma);
+ break;
+ default:
+ bufsiz = 64 * 1024;
+ };
+ /*
+ * Now for timing. The pica has a 25Mhz
+ */
+ switch (cputype) {
+ case ACER_PICA_61:
+ asc->min_period = ASC_MIN_PERIOD25;
+ asc->max_period = ASC_MAX_PERIOD25;
+ asc->ccf = ASC_CCF(25);
+ asc->timeout_250 = ASC_TIMEOUT_250(25, asc->ccf);
+ asc->tb_ticks = 10;
+ break;
+ default:
+ asc->min_period = ASC_MIN_PERIOD12;
+ asc->max_period = ASC_MAX_PERIOD12;
+ asc->ccf = ASC_CCF(13);
+ asc->timeout_250 = ASC_TIMEOUT_250(13, asc->ccf);
+ asc->tb_ticks = 20;
+ break;
+ };
+
+ asc->state = ASC_STATE_IDLE;
+ asc->target = -1;
+
+ regs = asc->regs;
+
+ /*
+ * Reset chip, fully. Note that interrupts are already enabled.
+ */
+ s = splbio();
+
+ /* preserve our ID for now */
+ asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
+ asc->myidmask = ~(1 << asc->sc_id);
+
+ asc_reset(asc, regs);
+
+ /*
+ * Our SCSI id on the bus.
+ * The user can set this via the prom on 3maxen/picaen.
+ * If this changes it is easy to fix: make a default that
+ * can be changed as boot arg.
+ */
+#ifdef unneeded
+ regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) |
+ (scsi_initiator_id[unit] & 0x7);
+ asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
+#endif
+ id = asc->sc_id;
+ splx(s);
+
+ /*
+ * Give each target its DMA buffer region.
+ * The buffer address is the same for all targets,
+ * the allocated dma viritual scatter/gather space.
+ */
+ for (i = 0; i < ASC_NCMD; i++) {
+ asc->st[i].dmaBufSize = bufsiz;
+ }
+
+ /*
+ * Set up interrupt handler.
+ */
+ BUS_INTR_ESTABLISH(ca, asc_intr, (void *)asc);
+
+ printf(": NCR53C94, target %d\n", id);
+
+ /*
+ * Fill in the prototype scsi link.
+ */
+ asc->sc_link.adapter_softc = asc;
+ asc->sc_link.adapter_target = asc->sc_id;
+ asc->sc_link.adapter = &asc_switch;
+ asc->sc_link.device = &asc_dev;
+ asc->sc_link.openings = 2;
+
+ /*
+ * Now try to attach all the sub devices.
+ */
+ config_found(self, &asc->sc_link, ascprint);
+}
+
+int
+ascprint(aux, name)
+ void *aux;
+ char *name;
+{
+ return -1;
+}
+
+/*
+ * Driver breaks down request transfer size.
+ */
+void
+asc_minphys(bp)
+ struct buf *bp;
+{
+}
+
+/*
+ * Start activity on a SCSI device.
+ * We maintain information on each device separately since devices can
+ * connect/disconnect during an operation.
+ */
+int
+asc_scsi_cmd(xs)
+ struct scsi_xfer *xs;
+{
+ struct scsi_link *sc_link = xs->sc_link;
+ struct asc_softc *asc = sc_link->adapter_softc;
+ State *state = &asc->st[sc_link->target];
+
+ int flags, s;
+
+ flags = xs->flags;
+
+ /*
+ * Flush caches for any data buffer
+ */
+ if(xs->datalen != 0) {
+ MachHitFlushDCache(xs->data, xs->datalen);
+ }
+ /*
+ * The hack on the next few lines are to avoid buffers
+ * mapped to UADDR. Realloc to the kva uarea address.
+ */
+ if((u_int)(xs->data) >= UADDR) {
+ xs->data = ((u_int)(xs->data) & ~UADDR) + (u_char *)(curproc->p_addr);
+ }
+
+ /*
+ * Check if another command is already in progress.
+ * We may have to change this if we allow SCSI devices with
+ * separate LUNs.
+ */
+ s = splbio();
+ if (asc->cmd[sc_link->target]) {
+ if (asc->cmdq[sc_link->target]) {
+ splx(s);
+ printf("asc_scsi_cmd: called when target busy");
+ xs->error = XS_DRIVER_STUFFUP;
+ return TRY_AGAIN_LATER;
+ }
+ asc->cmdq[sc_link->target] = xs;
+ splx(s);
+ return SUCCESSFULLY_QUEUED;
+ }
+ asc->cmd[sc_link->target] = xs;
+
+ /*
+ * Going to launch.
+ * Make a local copy of the command and some pointers.
+ */
+ asc_startcmd(asc, sc_link->target);
+
+ /*
+ * If in startup, interrupts not usable yet.
+ */
+ if(flags & SCSI_POLL) {
+ return(asc_poll(asc,sc_link->target));
+ }
+ splx(s);
+ return SUCCESSFULLY_QUEUED;
+}
+
+int
+asc_poll(asc, target)
+ struct asc_softc *asc;
+ int target;
+{
+ struct scsi_xfer *scsicmd = asc->cmd[target];
+ int count = scsicmd->timeout * 10;
+
+ while(count) {
+ if(asc->regs->asc_status &ASC_CSR_INT) {
+ asc_intr(asc);
+ }
+ if(scsicmd->flags & ITSDONE)
+ break;
+ DELAY(5);
+ count--;
+ }
+ if(count == 0) {
+ scsicmd->error = XS_TIMEOUT;
+ asc_end(asc, 0, 0, 0);
+ }
+ return COMPLETE;
+}
+
+static void
+asc_reset(asc, regs)
+ asc_softc_t asc;
+ asc_regmap_t *regs;
+{
+
+ /*
+ * Reset chip and wait till done
+ */
+ regs->asc_cmd = ASC_CMD_RESET;
+ wbflush(); DELAY(25);
+
+ /* spec says this is needed after reset */
+ regs->asc_cmd = ASC_CMD_NOP;
+ wbflush(); DELAY(25);
+
+ /*
+ * Set up various chip parameters
+ */
+ regs->asc_ccf = asc->ccf;
+ wbflush(); DELAY(25);
+ regs->asc_sel_timo = asc->timeout_250;
+ /* restore our ID */
+ regs->asc_cnfg1 = asc->sc_id | ASC_CNFG1_P_CHECK;
+ /* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */
+ regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL;
+ regs->asc_cnfg3 = 0;
+ /* zero anything else */
+ ASC_TC_PUT(regs, 0);
+ regs->asc_syn_p = asc->min_period;
+ regs->asc_syn_o = 0; /* async for now */
+ wbflush();
+}
+
+/*
+ * Start a SCSI command on a target.
+ */
+static void
+asc_startcmd(asc, target)
+ asc_softc_t asc;
+ int target;
+{
+ asc_regmap_t *regs;
+ State *state;
+ struct scsi_xfer *scsicmd;
+ int i, len;
+
+ /*
+ * See if another target is currently selected on this SCSI bus.
+ */
+ if (asc->target >= 0)
+ return;
+
+ regs = asc->regs;
+
+ /*
+ * If a reselection is in progress, it is Ok to ignore it since
+ * the ASC will automatically cancel the command and flush
+ * the FIFO if the ASC is reselected before the command starts.
+ * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if
+ * a reselect occurs before starting the command.
+ */
+
+ asc->state = ASC_STATE_BUSY;
+ asc->target = target;
+
+ /* cache some pointers */
+ scsicmd = asc->cmd[target];
+ state = &asc->st[target];
+
+ /*
+ * Init the chip and target state.
+ */
+ state->flags = state->flags & (DID_SYNC | CHECK_SENSE);
+ state->script = (script_t *)0;
+ state->msg_out = SCSI_NO_OP;
+
+ /*
+ * Set up for DMA of command output. Also need to flush cache.
+ */
+ if(!(state->flags & CHECK_SENSE)) {
+ bcopy(scsicmd->cmd, &state->cmd, scsicmd->cmdlen);
+ state->cmdlen = scsicmd->cmdlen;
+ state->buf = (vm_offset_t)scsicmd->data;
+ state->buflen = scsicmd->datalen;
+ }
+ len = state->cmdlen;
+ state->dmalen = len;
+
+#ifdef DEBUG
+ if (asc_debug > 1) {
+ printf("asc_startcmd: %s target %d cmd %x len %d\n",
+ asc->sc_dev.dv_xname, target,
+ state->cmd.opcode, state->buflen);
+ }
+#endif
+
+ /* check for simple SCSI command with no data transfer */
+ if(state->flags & CHECK_SENSE) {
+ asc->script = &asc_scripts[SCRIPT_DATA_IN];
+ state->flags |= DMA_IN;
+ }
+ else if (scsicmd->flags & SCSI_DATA_OUT) {
+ asc->script = &asc_scripts[SCRIPT_DATA_OUT];
+ state->flags |= DMA_OUT;
+ }
+ else if (scsicmd->flags & SCSI_DATA_IN) {
+ asc->script = &asc_scripts[SCRIPT_DATA_IN];
+ state->flags |= DMA_IN;
+ }
+ else if (state->buflen == 0) {
+ /* check for sync negotiation */
+ if ((scsicmd->flags & /* SCSICMD_USE_SYNC */ 0) &&
+ !(state->flags & DID_SYNC)) {
+ asc->script = &asc_scripts[SCRIPT_TRY_SYNC];
+ state->flags |= TRY_SYNC;
+ } else
+ asc->script = &asc_scripts[SCRIPT_SIMPLE];
+ state->buf = (vm_offset_t)0;
+ }
+
+#ifdef DEBUG
+ asc_debug_cmd = state->cmd.opcode;
+ if (state->cmd.opcode == SCSI_READ_EXT) {
+ asc_debug_bn = (state->cmd.bytes[1] << 24) |
+ (state->cmd.bytes[2] << 16) |
+ (state->cmd.bytes[3] << 8) |
+ state->cmd.bytes[4];
+ asc_debug_sz = (state->cmd.bytes[6] << 8) | state->cmd.bytes[7];
+ }
+ asc_logp->status = PACK(asc->sc_dev.dv_unit, 0, 0, asc_debug_cmd);
+ asc_logp->target = asc->target;
+ asc_logp->state = asc->script - asc_scripts;
+ asc_logp->msg = SCSI_DIS_REC_IDENTIFY;
+ asc_logp->resid = scsicmd->datalen;
+ if (++asc_logp >= &asc_log[NLOG])
+ asc_logp = asc_log;
+#endif
+
+ /* preload the FIFO with the message and command to be sent */
+ regs->asc_fifo = SCSI_DIS_REC_IDENTIFY | (scsicmd->sc_link->lun & 0x07);
+
+ for( i = 0; i < len; i++ ) {
+ regs->asc_fifo = ((caddr_t)&state->cmd)[i];
+ }
+ ASC_TC_PUT(regs, 0);
+ readback(regs->asc_cmd);
+ regs->asc_cmd = ASC_CMD_DMA;
+ readback(regs->asc_cmd);
+
+ regs->asc_dbus_id = target;
+ readback(regs->asc_dbus_id);
+ regs->asc_syn_p = state->sync_period;
+ readback(regs->asc_syn_p);
+ regs->asc_syn_o = state->sync_offset;
+ readback(regs->asc_syn_o);
+
+/*XXX PEFO */
+/* we are not using sync transfer now, need to check this if we will */
+
+ if (state->flags & TRY_SYNC)
+ regs->asc_cmd = ASC_CMD_SEL_ATN_STOP;
+ else
+ regs->asc_cmd = ASC_CMD_SEL_ATN;
+ readback(regs->asc_cmd);
+}
+
+/*
+ * Interrupt routine
+ * Take interrupts from the chip
+ *
+ * Implementation:
+ * Move along the current command's script if
+ * all is well, invoke error handler if not.
+ */
+int
+asc_intr(sc)
+ void *sc;
+{
+ asc_softc_t asc = sc;
+ asc_regmap_t *regs = asc->regs;
+ State *state;
+ script_t *scpt;
+ int ss, ir, status;
+
+ /* collect ephemeral information */
+ status = regs->asc_status;
+ ss = regs->asc_ss;
+
+ if ((status & ASC_CSR_INT) == 0) /* Make shure it's a real interrupt */
+ return;
+
+ ir = regs->asc_intr; /* this resets the previous two */
+ scpt = asc->script;
+
+#ifdef DEBUG
+ asc_logp->status = PACK(asc->sc_dev.dv_unit, status, ss, ir);
+ asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1;
+ asc_logp->state = scpt - asc_scripts;
+ asc_logp->msg = -1;
+ asc_logp->resid = 0;
+ if (++asc_logp >= &asc_log[NLOG])
+ asc_logp = asc_log;
+ if (asc_debug > 2)
+ printf("asc_intr: status %x ss %x ir %x cond %d:%x\n",
+ status, ss, ir, scpt - asc_scripts, scpt->condition);
+#endif
+
+ /* check the expected state */
+ if (SCRIPT_MATCH(ir, status) == scpt->condition) {
+ /*
+ * Perform the appropriate operation, then proceed.
+ */
+ if ((*scpt->action)(asc, status, ss, ir)) {
+ regs->asc_cmd = scpt->command;
+ readback(regs->asc_cmd);
+ asc->script = scpt->next;
+ }
+ goto done;
+ }
+
+ /*
+ * Check for parity error.
+ * Hardware will automatically set ATN
+ * to request the device for a MSG_OUT phase.
+ */
+ if (status & ASC_CSR_PE) {
+ printf("%s: SCSI device %d: incomming parity error seen\n",
+ asc->sc_dev.dv_xname, asc->target);
+ asc->st[asc->target].flags |= PARITY_ERR;
+ }
+
+ /*
+ * Check for gross error.
+ * Probably a bug in a device driver.
+ */
+ if (status & ASC_CSR_GE) {
+ printf("%s: SCSI device %d: gross error\n",
+ asc->sc_dev.dv_xname, asc->target);
+ goto abort;
+ }
+
+ /* check for message in or out */
+ if ((ir & ~ASC_INT_FC) == ASC_INT_BS) {
+ register int len, fifo;
+
+ state = &asc->st[asc->target];
+ switch (ASC_PHASE(status)) {
+ case ASC_PHASE_DATAI:
+ case ASC_PHASE_DATAO:
+ ASC_TC_GET(regs, len);
+ fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+ printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n",
+ state->buflen, state->dmalen, len, fifo);
+ goto abort;
+
+ case ASC_PHASE_MSG_IN:
+ break;
+
+ case ASC_PHASE_MSG_OUT:
+ /*
+ * Check for parity error.
+ * Hardware will automatically set ATN
+ * to request the device for a MSG_OUT phase.
+ */
+ if (state->flags & PARITY_ERR) {
+ state->flags &= ~PARITY_ERR;
+ state->msg_out = SCSI_MESSAGE_PARITY_ERROR;
+ /* reset message in counter */
+ state->msglen = 0;
+ } else
+ state->msg_out = SCSI_NO_OP;
+ regs->asc_fifo = state->msg_out;
+ regs->asc_cmd = ASC_CMD_XFER_INFO;
+ readback(regs->asc_cmd);
+ goto done;
+
+ case ASC_PHASE_STATUS:
+ /* probably an error in the SCSI command */
+ asc->script = &asc_scripts[SCRIPT_GET_STATUS];
+ regs->asc_cmd = ASC_CMD_I_COMPLETE;
+ readback(regs->asc_cmd);
+ goto done;
+
+ default:
+ goto abort;
+ }
+
+ if (state->script)
+ goto abort;
+
+ /*
+ * OK, message coming in clean up whatever is going on.
+ * Get number of bytes left to transfered from byte counter
+ * counter decrements when data is trf on the SCSI bus
+ */
+ ASC_TC_GET(regs, len);
+ fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+ /* flush any data in the FIFO */
+ if (fifo && !(state->flags & DMA_IN_PROGRESS)) {
+printf("asc_intr: fifo flush %d len %d fifo %x\n", fifo, len, regs->asc_fifo);
+ regs->asc_cmd = ASC_CMD_FLUSH;
+ readback(regs->asc_cmd);
+ DELAY(2);
+ }
+ else if (fifo && state->flags & DMA_IN_PROGRESS) {
+ if (state->flags & DMA_OUT) {
+ len += fifo; /* Bytes dma'ed but not sent */
+ }
+ else if (state->flags & DMA_IN) {
+ u_char *cp;
+
+ printf("asc_intr: IN: dmalen %d len %d fifo %d\n",
+ state->dmalen, len, fifo); /* XXX */
+ }
+ regs->asc_cmd = ASC_CMD_FLUSH;
+ readback(regs->asc_cmd);
+ DELAY(2);
+ }
+ if (len && (state->flags & DMA_IN_PROGRESS)) {
+ /* save number of bytes still to be sent or received */
+ state->dmaresid = len;
+ state->flags &= ~DMA_IN_PROGRESS;
+ ASC_TC_PUT(regs, 0);
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].resid = len;
+ else
+ asc_logp[-1].resid = len;
+#endif
+ /* setup state to resume to */
+ if (state->flags & DMA_IN) {
+ /*
+ * Since the ASC_CNFG3_SRB bit of the
+ * cnfg3 register bit is not set,
+ * we just transferred an extra byte.
+ * Since we can't resume on an odd byte
+ * boundary, we copy the valid data out
+ * and resume DMA at the start address.
+ */
+ if (len & 1) {
+ printf("asc_intr: msg in len %d (fifo %d)\n",
+ len, fifo); /* XXX */
+ len = state->dmalen - len;
+ goto do_in;
+ }
+ state->script =
+ &asc_scripts[SCRIPT_RESUME_DMA_IN];
+ } else if (state->flags & DMA_OUT)
+ state->script =
+ &asc_scripts[SCRIPT_RESUME_DMA_OUT];
+ else
+ state->script = asc->script;
+ } else if (state->flags & DMA_IN) {
+ if (len) {
+#ifdef DEBUG
+ printf("asc_intr: 1: bn %d len %d (fifo %d)\n",
+ asc_debug_bn, len, fifo); /* XXX */
+#endif
+ goto abort;
+ }
+ /* setup state to resume to */
+ if (state->flags & DMA_IN_PROGRESS) {
+ len = state->dmalen;
+ state->flags &= ~DMA_IN_PROGRESS;
+ do_in:
+ DMA_END(asc->dma);
+ state->buf += len;
+ state->buflen -= len;
+ }
+ if (state->buflen)
+ state->script =
+ &asc_scripts[SCRIPT_RESUME_IN];
+ else
+ state->script =
+ &asc_scripts[SCRIPT_RESUME_NO_DATA];
+ } else if (state->flags & DMA_OUT) {
+ if (len) {
+ printf("asc_intr: 2: len %d (fifo %d)\n", len,
+ fifo); /* XXX */
+/* XXX THEO */
+#if 1
+ regs->asc_cmd = ASC_CMD_FLUSH;
+ readback(regs->asc_cmd);
+ DELAY(2);
+ len = 0;
+#else
+ goto abort;
+#endif
+ }
+ /*
+ * If this is the last chunk, the next expected
+ * state is to get status.
+ */
+ if (state->flags & DMA_IN_PROGRESS) {
+ state->flags &= ~DMA_IN_PROGRESS;
+ DMA_END(asc->dma);
+ len = state->dmalen;
+ state->buf += len;
+ state->buflen -= len;
+ }
+ if (state->buflen)
+ state->script =
+ &asc_scripts[SCRIPT_RESUME_OUT];
+ else
+ state->script =
+ &asc_scripts[SCRIPT_RESUME_NO_DATA];
+ } else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
+ state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA];
+ else
+ state->script = asc->script;
+
+ /* setup to receive a message */
+ asc->script = &asc_scripts[SCRIPT_MSG_IN];
+ state->msglen = 0;
+ regs->asc_cmd = ASC_CMD_XFER_INFO;
+ readback(regs->asc_cmd);
+ goto done;
+ }
+
+ /* check for SCSI bus reset */
+ if (ir & ASC_INT_RESET) {
+ register int i;
+
+ printf("%s: SCSI bus reset!!\n", asc->sc_dev.dv_xname);
+ /* need to flush any pending commands */
+ for (i = 0; i < ASC_NCMD; i++) {
+ if (!asc->cmd[i])
+ continue;
+ asc->cmd[i]->error = XS_DRIVER_STUFFUP;
+ asc_end(asc, 0, 0, 0);
+ }
+ /* rearbitrate synchronous offset */
+ for (i = 0; i < ASC_NCMD; i++) {
+ asc->st[i].sync_offset = 0;
+ asc->st[i].flags = 0;
+ }
+ asc->target = -1;
+ return;
+ }
+
+ /* check for command errors */
+ if (ir & ASC_INT_ILL)
+ goto abort;
+
+ /* check for disconnect */
+ if (ir & ASC_INT_DISC) {
+ state = &asc->st[asc->target];
+ switch (asc->script - asc_scripts) {
+ case SCRIPT_DONE:
+ case SCRIPT_DISCONNECT:
+ /*
+ * Disconnects can happen normally when the
+ * command is complete with the phase being
+ * either ASC_PHASE_DATAO or ASC_PHASE_MSG_IN.
+ * The SCRIPT_MATCH() only checks for one phase
+ * so we can wind up here.
+ * Perform the appropriate operation, then proceed.
+ */
+ if ((*scpt->action)(asc, status, ss, ir)) {
+ regs->asc_cmd = scpt->command;
+ readback(regs->asc_cmd);
+ asc->script = scpt->next;
+ }
+ goto done;
+
+ case SCRIPT_TRY_SYNC:
+ case SCRIPT_SIMPLE:
+ case SCRIPT_DATA_IN:
+ case SCRIPT_DATA_OUT: /* one of the starting scripts */
+ if (ASC_SS(ss) == 0) {
+ /* device did not respond */
+ if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) {
+ regs->asc_cmd = ASC_CMD_FLUSH;
+ readback(regs->asc_cmd);
+ }
+ asc->cmd[asc->target]->error = XS_DRIVER_STUFFUP;
+ asc_end(asc, status, ss, ir);
+ return;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ printf("%s: SCSI device %d: unexpected disconnect\n",
+ asc->sc_dev.dv_xname, asc->target);
+#ifdef DEBUG
+ asc_DumpLog("asc_disc");
+#endif
+ /*
+ * On rare occasions my RZ24 does a disconnect during
+ * data in phase and the following seems to keep it
+ * happy.
+ * XXX Should a scsi disk ever do this??
+ */
+ asc->script = &asc_scripts[SCRIPT_RESEL];
+ asc->state = ASC_STATE_RESEL;
+ state->flags |= DISCONN;
+ regs->asc_cmd = ASC_CMD_ENABLE_SEL;
+ readback(regs->asc_cmd);
+ return;
+ }
+ }
+
+ /* check for reselect */
+ if (ir & ASC_INT_RESEL) {
+ unsigned fifo, id, msg;
+
+ fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+ if (fifo < 2)
+ goto abort;
+ /* read unencoded SCSI ID and convert to binary */
+ msg = regs->asc_fifo & asc->myidmask;
+ for (id = 0; (msg & 1) == 0; id++)
+ msg >>= 1;
+ /* read identify message */
+ msg = regs->asc_fifo;
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].msg = msg;
+ else
+ asc_logp[-1].msg = msg;
+#endif
+ asc->state = ASC_STATE_BUSY;
+ asc->target = id;
+ state = &asc->st[id];
+ asc->script = state->script;
+ state->script = (script_t *)0;
+ if (!(state->flags & DISCONN))
+ goto abort;
+ state->flags &= ~DISCONN;
+ regs->asc_syn_p = state->sync_period;
+ regs->asc_syn_o = state->sync_offset;
+ regs->asc_cmd = ASC_CMD_MSG_ACPT;
+ readback(regs->asc_cmd);
+ goto done;
+ }
+
+ /* check if we are being selected as a target */
+ if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
+ goto abort;
+
+ /*
+ * 'ir' must be just ASC_INT_FC.
+ * This is normal if canceling an ASC_ENABLE_SEL.
+ */
+
+done:
+ wbflush();
+ /*
+ * If the next interrupt comes in immediatly the interrupt
+ * dispatcher (which we are returning to) will catch it
+ * before returning to the interrupted code.
+ */
+ return;
+
+abort:
+#ifdef DEBUG
+ asc_DumpLog("asc_intr");
+#endif
+#if 0
+ panic("asc_intr");
+#else
+ boot(4); /* XXX */
+#endif
+}
+
+/*
+ * All the many little things that the interrupt
+ * routine might switch to.
+ */
+
+/* ARGSUSED */
+static int
+script_nop(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_get_status(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register int data;
+
+ /*
+ * Get the last two bytes in the FIFO.
+ */
+ if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
+ printf("asc_get_status: cmdreg %x, fifo cnt %d\n",
+ regs->asc_cmd, data); /* XXX */
+#ifdef DEBUG
+ asc_DumpLog("get_status"); /* XXX */
+#endif
+ if (data < 2) {
+ asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
+ readback(asc->regs->asc_cmd);
+ return (0);
+ }
+ do {
+ data = regs->asc_fifo;
+ } while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2);
+ }
+
+ /* save the status byte */
+ asc->st[asc->target].statusByte = data = regs->asc_fifo;
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].msg = data;
+ else
+ asc_logp[-1].msg = data;
+#endif
+
+ /* get the (presumed) command_complete message */
+ if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE)
+ return (1);
+
+#ifdef DEBUG
+ printf("asc_get_status: status %x cmd %x\n",
+ asc->st[asc->target].statusByte, data);
+ asc_DumpLog("asc_get_status");
+#endif
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+asc_end(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ struct scsi_xfer *scsicmd;
+ struct scsi_link *sc_link;
+ State *state;
+ int i, target;
+
+ asc->state = ASC_STATE_IDLE;
+ target = asc->target;
+ asc->target = -1;
+ scsicmd = asc->cmd[target];
+ sc_link = scsicmd->sc_link;
+ asc->cmd[target] = (struct scsi_xfer *)0;
+ state = &asc->st[target];
+
+#ifdef DEBUG
+ if (asc_debug > 1) {
+ printf("asc_end: %s target %d cmd %x err %d resid %d\n",
+ asc->sc_dev.dv_xname, target,
+ state->cmd.opcode, scsicmd->error, state->buflen);
+ }
+#endif
+#ifdef DIAGNOSTIC
+ if (target < 0 || !scsicmd)
+ panic("asc_end");
+#endif
+
+ /* look for disconnected devices */
+ for (i = 0; i < ASC_NCMD; i++) {
+ if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN))
+ continue;
+ asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL;
+ readback(asc->regs->asc_cmd);
+ asc->state = ASC_STATE_RESEL;
+ asc->script = &asc_scripts[SCRIPT_RESEL];
+ break;
+ }
+
+ if(scsicmd->error == XS_NOERROR && !(state->flags & CHECK_SENSE)) {
+ if((state->statusByte & ST_MASK) == SCSI_CHECK) {
+ struct scsi_sense *ss = (void *)&state->cmd;
+ /* Save return values */
+ scsicmd->resid = state->buflen;
+ scsicmd->status = state->statusByte;
+ /* Set up sense request command */
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = sc_link->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+ state->cmdlen = sizeof(*ss);
+ state->buf = (vm_offset_t)&scsicmd->sense;
+ state->buflen = sizeof(struct scsi_sense_data);
+ state->flags |= CHECK_SENSE;
+ MachHitFlushDCache(state->buf, state->buflen);
+ asc->cmd[target] = scsicmd;
+ asc_startcmd(asc, target);
+ return(0);
+ }
+ }
+
+ if(scsicmd->error == XS_NOERROR && (state->flags & CHECK_SENSE)) {
+ scsicmd->error = XS_SENSE;
+ }
+ else {
+ scsicmd->resid = state->buflen;
+ }
+ state->flags &= ~CHECK_SENSE;
+
+ /*
+ * Look for another device that is ready.
+ * May want to keep last one started and increment for fairness
+ * rather than always starting at zero.
+ */
+ for (i = 0; i < ASC_NCMD; i++) {
+ if (asc->cmd[i] == 0 && asc->cmdq[i] != 0) {
+ asc->cmd[i] = asc->cmdq[i];
+ asc->cmdq[i] = 0;
+ }
+ }
+ for (i = 0; i < ASC_NCMD; i++) {
+ /* don't restart a disconnected command */
+ if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
+ continue;
+ asc_startcmd(asc, i);
+ break;
+ }
+
+ /* signal device driver that the command is done */
+ scsicmd->flags |= ITSDONE;
+ scsi_done(scsicmd);
+
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+asc_dma_in(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+ register int len;
+
+ /* check for previous chunk in buffer */
+ if (state->flags & DMA_IN_PROGRESS) {
+ /*
+ * Only count bytes that have been copied to memory.
+ * There may be some bytes in the FIFO if synchonous transfers
+ * are in progress.
+ */
+ DMA_END(asc->dma);
+ ASC_TC_GET(regs, len);
+ len = state->dmalen - len;
+ state->buf += len;
+ state->buflen -= len;
+ }
+
+ /* setup to start reading the next chunk */
+ len = state->buflen;
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].resid = len;
+ else
+ asc_logp[-1].resid = len;
+#endif
+ if (len > state->dmaBufSize)
+ len = state->dmaBufSize;
+ state->dmalen = len;
+ DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
+ ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len);
+#endif
+
+ /* check for next chunk */
+ state->flags |= DMA_IN_PROGRESS;
+ if (len != state->buflen) {
+ regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+ readback(regs->asc_cmd);
+ asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
+ return (0);
+ }
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_last_dma_in(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+ register int len, fifo;
+
+ DMA_END(asc->dma);
+ ASC_TC_GET(regs, len);
+ fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n",
+ state->buflen, state->dmalen, len, fifo);
+#endif
+ if (fifo) {
+ /* device must be trying to send more than we expect */
+ regs->asc_cmd = ASC_CMD_FLUSH;
+ readback(regs->asc_cmd);
+ }
+ state->flags &= ~DMA_IN_PROGRESS;
+ len = state->dmalen - len;
+ state->buflen -= len;
+
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_resume_in(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+ register int len;
+
+ /* setup to start reading the next chunk */
+ len = state->buflen;
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].resid = len;
+ else
+ asc_logp[-1].resid = len;
+#endif
+ if (len > state->dmaBufSize)
+ len = state->dmaBufSize;
+ state->dmalen = len;
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].resid = len;
+ else
+ asc_logp[-1].resid = len;
+#endif
+ DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
+ ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_resume_in: buflen %d, len %d\n", state->buflen,
+ len);
+#endif
+
+ /* check for next chunk */
+ state->flags |= DMA_IN_PROGRESS;
+ if (len != state->buflen) {
+ regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+ readback(regs->asc_cmd);
+ asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
+ return (0);
+ }
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_resume_dma_in(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+ register int len, off;
+
+ /* setup to finish reading the current chunk */
+ len = state->dmaresid;
+ off = state->dmalen - len;
+ if ((off & 1) && state->sync_offset) {
+ printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n",
+ state->dmalen, len, off); /* XXX */
+ regs->asc_res_fifo = ((u_char *)state->buf)[off];
+/*XXX Need to flush cache ? */
+ }
+ DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_FROM_DEV);
+ ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n",
+ state->dmalen, state->buflen, len, off);
+#endif
+
+ /* check for next chunk */
+ state->flags |= DMA_IN_PROGRESS;
+ if (state->dmalen != state->buflen) {
+ regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+ readback(regs->asc_cmd);
+ asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
+ return (0);
+ }
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_dma_out(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+ register int len, fifo;
+
+ if (state->flags & DMA_IN_PROGRESS) {
+ /* check to be sure previous chunk was finished */
+ ASC_TC_GET(regs, len);
+ fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+ if (len || fifo)
+ printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
+ state->buflen, state->dmalen, len, fifo); /* XXX */
+ len += fifo;
+ len = state->dmalen - len;
+ state->buf += len;
+ state->buflen -= len;
+ }
+
+ /* setup for this chunk */
+ len = state->buflen;
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].resid = len;
+ else
+ asc_logp[-1].resid = len;
+#endif
+ if (len > state->dmaBufSize)
+ len = state->dmaBufSize;
+ state->dmalen = len;
+ DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
+ ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len);
+#endif
+
+ /* check for next chunk */
+ state->flags |= DMA_IN_PROGRESS;
+ if (len != state->buflen) {
+ regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+ readback(regs->asc_cmd);
+ asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
+ return (0);
+ }
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_last_dma_out(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+ register int len, fifo;
+
+ ASC_TC_GET(regs, len);
+ fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
+ state->buflen, state->dmalen, len, fifo);
+#endif
+ if (fifo) {
+ len += fifo;
+ regs->asc_cmd = ASC_CMD_FLUSH;
+ readback(regs->asc_cmd);
+ }
+ state->flags &= ~DMA_IN_PROGRESS;
+ len = state->dmalen - len;
+ state->buflen -= len;
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_resume_out(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+ register int len;
+
+ /* setup for this chunk */
+ len = state->buflen;
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].resid = len;
+ else
+ asc_logp[-1].resid = len;
+#endif
+ if (len > state->dmaBufSize)
+ len = state->dmaBufSize;
+ state->dmalen = len;
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].resid = len;
+ else
+ asc_logp[-1].resid = len;
+#endif
+ DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
+ ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_resume_out: buflen %d, len %d\n", state->buflen,
+ len);
+#endif
+
+ /* check for next chunk */
+ state->flags |= DMA_IN_PROGRESS;
+ if (len != state->buflen) {
+ regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+ readback(regs->asc_cmd);
+ asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
+ return (0);
+ }
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_resume_dma_out(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+ register int len, off;
+
+ /* setup to finish writing this chunk */
+ len = state->dmaresid;
+ off = state->dmalen - len;
+ if (off & 1) {
+ printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",
+ state->dmalen, len, off); /* XXX */
+ regs->asc_fifo = ((u_char *)state->buf)[off];
+/*XXX Need to flush Cache ? */
+ off++;
+ len--;
+ }
+ DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_TO_DEV);
+ ASC_TC_PUT(regs, len);
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n",
+ state->dmalen, state->buflen, len, off);
+#endif
+
+ /* check for next chunk */
+ state->flags |= DMA_IN_PROGRESS;
+ if (state->dmalen != state->buflen) {
+ regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
+ readback(regs->asc_cmd);
+ asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
+ return (0);
+ }
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_sendsync(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+
+ /* send the extended synchronous negotiation message */
+ regs->asc_fifo = SCSI_EXTENDED_MSG;
+ wbflush();
+ regs->asc_fifo = 3;
+ wbflush();
+ regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
+ wbflush();
+ regs->asc_fifo = SCSI_MIN_PERIOD;
+ wbflush();
+ regs->asc_fifo = ASC_MAX_OFFSET;
+ /* state to resume after we see the sync reply message */
+ state->script = asc->script + 2;
+ state->msglen = 0;
+ return (1);
+}
+
+/* ARGSUSED */
+static int
+asc_replysync(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_replysync: %x %x\n",
+ asc_to_scsi_period[state->sync_period] * asc->tb_ticks,
+ state->sync_offset);
+#endif
+ /* send synchronous transfer in response to a request */
+ regs->asc_fifo = SCSI_EXTENDED_MSG;
+ wbflush();
+ regs->asc_fifo = 3;
+ wbflush();
+ regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
+ wbflush();
+ regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks;
+ wbflush();
+ regs->asc_fifo = state->sync_offset;
+ regs->asc_cmd = ASC_CMD_XFER_INFO;
+ readback(regs->asc_cmd);
+
+ /* return to the appropriate script */
+ if (!state->script) {
+#ifdef DEBUG
+ asc_DumpLog("asc_replsync");
+#endif
+ panic("asc_replysync");
+ }
+ asc->script = state->script;
+ state->script = (script_t *)0;
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+asc_msg_in(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register asc_regmap_t *regs = asc->regs;
+ register State *state = &asc->st[asc->target];
+ register int msg;
+ int i;
+
+ /* read one message byte */
+ msg = regs->asc_fifo;
+#ifdef DEBUG
+ if (asc_logp == asc_log)
+ asc_log[NLOG - 1].msg = msg;
+ else
+ asc_logp[-1].msg = msg;
+#endif
+
+ /* check for multi-byte message */
+ if (state->msglen != 0) {
+ /* first byte is the message length */
+ if (state->msglen < 0) {
+ state->msglen = msg;
+ return (1);
+ }
+ if (state->msgcnt >= state->msglen)
+ goto abort;
+ state->msg_in[state->msgcnt++] = msg;
+
+ /* did we just read the last byte of the message? */
+ if (state->msgcnt != state->msglen)
+ return (1);
+
+ /* process an extended message */
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_msg_in: msg %x %x %x\n",
+ state->msg_in[0],
+ state->msg_in[1],
+ state->msg_in[2]);
+#endif
+ switch (state->msg_in[0]) {
+ case SCSI_SYNCHRONOUS_XFER:
+ state->flags |= DID_SYNC;
+ state->sync_offset = state->msg_in[2];
+
+ /* convert SCSI period to ASC period */
+ i = state->msg_in[1] / asc->tb_ticks;
+ if (i < asc->min_period)
+ i = asc->min_period;
+ else if (i >= asc->max_period) {
+ /* can't do sync transfer, period too long */
+ printf("%s: SCSI device %d: sync xfer period too long (%d)\n",
+ asc->sc_dev.dv_xname, asc->target, i);
+ i = asc->max_period;
+ state->sync_offset = 0;
+ }
+ if ((i * asc->tb_ticks) != state->msg_in[1])
+ i++;
+ state->sync_period = i & 0x1F;
+
+ /*
+ * If this is a request, check minimums and
+ * send back an acknowledge.
+ */
+ if (!(state->flags & TRY_SYNC)) {
+ regs->asc_cmd = ASC_CMD_SET_ATN;
+ readback(regs->asc_cmd);
+
+ if (state->sync_period < asc->min_period)
+ state->sync_period =
+ asc->min_period;
+ if (state->sync_offset > ASC_MAX_OFFSET)
+ state->sync_offset =
+ ASC_MAX_OFFSET;
+ asc->script = &asc_scripts[SCRIPT_REPLY_SYNC];
+ regs->asc_syn_p = state->sync_period;
+ readback(regs->asc_syn_p);
+ regs->asc_syn_o = state->sync_offset;
+ readback(regs->asc_syn_o);
+ regs->asc_cmd = ASC_CMD_MSG_ACPT;
+ readback(regs->asc_cmd);
+ return (0);
+ }
+
+ regs->asc_syn_p = state->sync_period;
+ readback(regs->asc_syn_p);
+ regs->asc_syn_o = state->sync_offset;
+ readback(regs->asc_syn_o);
+ goto done;
+
+ default:
+ printf("%s: SCSI device %d: rejecting extended message 0x%x\n",
+ asc->sc_dev.dv_xname, asc->target,
+ state->msg_in[0]);
+ goto reject;
+ }
+ }
+
+ /* process first byte of a message */
+#ifdef DEBUG
+ if (asc_debug > 2)
+ printf("asc_msg_in: msg %x\n", msg);
+#endif
+ switch (msg) {
+#if 0
+ case SCSI_MESSAGE_REJECT:
+ printf(" did not like SYNCH xfer "); /* XXX */
+ state->flags |= DID_SYNC;
+ regs->asc_cmd = ASC_CMD_MSG_ACPT;
+ readback(regs->asc_cmd);
+ status = asc_wait(regs, ASC_CSR_INT);
+ ir = regs->asc_intr;
+ /* some just break out here, some dont */
+ if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {
+ regs->asc_fifo = SCSI_ABORT;
+ regs->asc_cmd = ASC_CMD_XFER_INFO;
+ readback(regs->asc_cmd);
+ status = asc_wait(regs, ASC_CSR_INT);
+ ir = regs->asc_intr;
+ }
+ if (ir & ASC_INT_DISC) {
+ asc_end(asc, status, 0, ir);
+ return (0);
+ }
+ goto status;
+#endif /* 0 */
+
+ case SCSI_EXTENDED_MSG: /* read an extended message */
+ /* setup to read message length next */
+ state->msglen = -1;
+ state->msgcnt = 0;
+ return (1);
+
+ case SCSI_NO_OP:
+ break;
+
+ case SCSI_SAVE_DATA_POINTER:
+ /* expect another message */
+ return (1);
+
+ case SCSI_RESTORE_POINTERS:
+ /*
+ * Need to do the following if resuming synchonous data in
+ * on an odd byte boundary.
+ regs->asc_cnfg2 |= ASC_CNFG2_RFB;
+ */
+ break;
+
+ case SCSI_DISCONNECT:
+ if (state->flags & DISCONN)
+ goto abort;
+ state->flags |= DISCONN;
+ regs->asc_cmd = ASC_CMD_MSG_ACPT;
+ readback(regs->asc_cmd);
+ asc->script = &asc_scripts[SCRIPT_DISCONNECT];
+ return (0);
+
+ default:
+ printf("%s: SCSI device %d: rejecting message 0x%x\n",
+ asc->sc_dev.dv_xname, asc->target, msg);
+ reject:
+ /* request a message out before acknowledging this message */
+ state->msg_out = SCSI_MESSAGE_REJECT;
+ regs->asc_cmd = ASC_CMD_SET_ATN;
+ readback(regs->asc_cmd);
+ }
+
+done:
+ /* return to original script */
+ regs->asc_cmd = ASC_CMD_MSG_ACPT;
+ readback(regs->asc_cmd);
+ if (!state->script) {
+ abort:
+#ifdef DEBUG
+ asc_DumpLog("asc_msg_in");
+#endif
+ panic("asc_msg_in");
+ }
+ asc->script = state->script;
+ state->script = (script_t *)0;
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+asc_disconnect(asc, status, ss, ir)
+ register asc_softc_t asc;
+ register int status, ss, ir;
+{
+ register State *state = &asc->st[asc->target];
+
+#ifdef DIAGNOSTIC
+ if (!(state->flags & DISCONN)) {
+ printf("asc_disconnect: device %d: DISCONN not set!\n",
+ asc->target);
+ }
+#endif /* DIAGNOSTIC */
+ asc->target = -1;
+ asc->state = ASC_STATE_RESEL;
+ return (1);
+}
+
+#ifdef DEBUG
+/*
+ * Dump the log buffer.
+ */
+asc_DumpLog(str)
+ char *str;
+{
+ register struct asc_log *lp;
+ register u_int status;
+
+ printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
+ asc_debug_bn, asc_debug_sz);
+ lp = asc_logp;
+ do {
+ status = lp->status;
+ printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n",
+ status >> 24,
+ lp->target,
+ (status >> 16) & 0xFF,
+ (status >> 8) & 0xFF,
+ status & 0XFF,
+ lp->state,
+ asc_scripts[lp->state].condition,
+ lp->msg, lp->resid);
+ if (++lp >= &asc_log[NLOG])
+ lp = asc_log;
+ } while (lp != asc_logp);
+}
+#endif /* DEBUG */
+
+#endif /* NASC > 0 */
diff --git a/sys/arch/arc/dev/ascreg.h b/sys/arch/arc/dev/ascreg.h
new file mode 100644
index 00000000000..c6ff2fb236b
--- /dev/null
+++ b/sys/arch/arc/dev/ascreg.h
@@ -0,0 +1,322 @@
+/* $OpenBSD: ascreg.h,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ascreg.h 8.1 (Berkeley) 6/10/93
+ * $Id: ascreg.h,v 1.1 1996/06/24 09:07:19 pefo Exp $
+ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * HISTORY
+ * Log: scsi_53C94.h,v
+ * Revision 2.4 91/02/05 17:44:59 mrt
+ * Added author notices
+ * [91/02/04 11:18:32 mrt]
+ *
+ * Changed to use new Mach copyright
+ * [91/02/02 12:17:11 mrt]
+ *
+ * Revision 2.3 90/12/05 23:34:46 af
+ * Documented max DMA xfer size.
+ * [90/12/03 23:39:36 af]
+ *
+ * Revision 2.1.1.1 90/11/01 03:38:54 af
+ * Created, from the DEC specs:
+ * "PMAZ-AA TURBOchannel SCSI Module Functional Specification"
+ * Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990.
+ * And from the NCR data sheets
+ * "NCR 53C94, 53C95, 53C96 Advanced SCSI Controller"
+ * [90/09/03 af]
+ */
+
+/*
+ * File: scsi_53C94.h
+ * Author: Alessandro Forin, Carnegie Mellon University
+ * Date: 9/90
+ *
+ * Defines for the NCR 53C94 ASC (SCSI interface)
+ * Some gotcha came from the "86C01/53C94 DMA lab work" written
+ * by Ken Stewart (NCR MED Logic Products Applications Engineer)
+ * courtesy of NCR. Thanks Ken !
+ */
+
+#define ASC_OFFSET_53C94 0x0 /* from module base */
+
+#define ASC_NCMD 7 /* Number of simultaneous cmds */
+
+/*
+ * Synch xfer parameters, and timing conversions
+ */
+#define SCSI_MIN_PERIOD 50 /* in 4 nsecs units */
+#define ASC_MIN_PERIOD40 8 /* in CLKS/BYTE, 1 CLK = 25nsecs */
+#define ASC_MIN_PERIOD25 5 /* in CLKS/BYTE, 1 CLK = 40nsecs */
+#define ASC_MIN_PERIOD12 3 /* in CLKS/BYTE, 1 CLK = 80nsecs */
+#define ASC_MAX_PERIOD40 56 /* in CLKS/BYTE, 1 CLK = 25nsecs */
+#define ASC_MAX_PERIOD25 35 /* in CLKS/BYTE, 1 CLK = 40nsecs */
+#define ASC_MAX_PERIOD12 18 /* in CLKS/BYTE, 1 CLK = 80nsecs */
+#define ASC_MAX_OFFSET 15 /* pure number */
+/*
+ * Register map, padded as needed
+ */
+
+typedef volatile struct {
+ u_char asc_tc_lsb; /* rw: Transfer Counter LSB */
+ u_char asc_tc_msb; /* rw: Transfer Counter MSB */
+ u_char asc_fifo; /* rw: FIFO top */
+ u_char asc_cmd; /* rw: Command */
+ u_char asc_status; /* r: Status */
+#define asc_dbus_id asc_status /* w: Destination Bus ID */
+ u_char asc_intr; /* r: Interrupt */
+#define asc_sel_timo asc_intr /* w: (re)select timeout */
+ u_char asc_ss; /* r: Sequence Step */
+#define asc_syn_p asc_ss /* w: synchronous period */
+ u_char asc_flags; /* r: FIFO flags + seq step */
+#define asc_syn_o asc_flags /* w: synchronous offset */
+ u_char asc_cnfg1; /* rw: Configuration 1 */
+ u_char asc_ccf; /* w: Clock Conv. Factor */
+ u_char asc_test; /* w: Test Mode */
+ u_char asc_cnfg2; /* rw: Configuration 2 */
+ u_char asc_cnfg3; /* rw: Configuration 3 */
+ u_char asc_res_fifo; /* w: Reserve FIFO byte */
+} asc_regmap_t;
+
+/*
+ * Transfer Count: access macros
+ * That a NOP is required after loading the dma counter
+ * I learned on the NCR test code. Sic.
+ */
+
+#define ASC_TC_MAX 0x10000
+
+#define ASC_TC_GET(ptr, val) \
+ val = (ptr)->asc_tc_lsb | ((ptr)->asc_tc_msb << 8)
+#define ASC_TC_PUT(ptr, val) \
+ (ptr)->asc_tc_lsb = (val); \
+ (ptr)->asc_tc_msb = (val) >> 8; \
+ (ptr)->asc_cmd = ASC_CMD_NOP | ASC_CMD_DMA;
+
+/*
+ * Command register (command codes)
+ */
+
+#define ASC_CMD_DMA 0x80
+ /* Miscellaneous */
+#define ASC_CMD_NOP 0x00
+#define ASC_CMD_FLUSH 0x01
+#define ASC_CMD_RESET 0x02
+#define ASC_CMD_BUS_RESET 0x03
+ /* Initiator state */
+#define ASC_CMD_XFER_INFO 0x10
+#define ASC_CMD_I_COMPLETE 0x11
+#define ASC_CMD_MSG_ACPT 0x12
+#define ASC_CMD_XFER_PAD 0x18
+#define ASC_CMD_SET_ATN 0x1a
+#define ASC_CMD_CLR_ATN 0x1b
+ /* Target state */
+#define ASC_CMD_SND_MSG 0x20
+#define ASC_CMD_SND_STATUS 0x21
+#define ASC_CMD_SND_DATA 0x22
+#define ASC_CMD_DISC_SEQ 0x23
+#define ASC_CMD_TERM 0x24
+#define ASC_CMD_T_COMPLETE 0x25
+#define ASC_CMD_DISC 0x27
+#define ASC_CMD_RCV_MSG 0x28
+#define ASC_CMD_RCV_CDB 0x29
+#define ASC_CMD_RCV_DATA 0x2a
+#define ASC_CMD_RCV_CMD 0x2b
+#define ASC_CMD_ABRT_DMA 0x04
+ /* Disconnected state */
+#define ASC_CMD_RESELECT 0x40
+#define ASC_CMD_SEL 0x41
+#define ASC_CMD_SEL_ATN 0x42
+#define ASC_CMD_SEL_ATN_STOP 0x43
+#define ASC_CMD_ENABLE_SEL 0x44
+#define ASC_CMD_DISABLE_SEL 0x45
+#define ASC_CMD_SEL_ATN3 0x46
+
+/*
+ * Status register, and phase encoding
+ */
+
+#define ASC_CSR_INT 0x80
+#define ASC_CSR_GE 0x40
+#define ASC_CSR_PE 0x20
+#define ASC_CSR_TC 0x10
+#define ASC_CSR_VGC 0x08
+#define ASC_CSR_MSG 0x04
+#define ASC_CSR_CD 0x02
+#define ASC_CSR_IO 0x01
+
+#define ASC_PHASE(csr) ((csr) & 0x7)
+#define ASC_PHASE_DATAO 0x0
+#define ASC_PHASE_DATAI 0x1
+#define ASC_PHASE_COMMAND 0x2
+#define ASC_PHASE_STATUS 0x3
+ /* 4..5 ANSI reserved */
+#define ASC_PHASE_MSG_OUT 0x6
+#define ASC_PHASE_MSG_IN 0x7
+
+/*
+ * Destination Bus ID
+ */
+
+#define ASC_DEST_ID_MASK 0x07
+
+/*
+ * Interrupt register
+ */
+
+#define ASC_INT_RESET 0x80
+#define ASC_INT_ILL 0x40
+#define ASC_INT_DISC 0x20
+#define ASC_INT_BS 0x10
+#define ASC_INT_FC 0x08
+#define ASC_INT_RESEL 0x04
+#define ASC_INT_SEL_ATN 0x02
+#define ASC_INT_SEL 0x01
+
+/*
+ * Timeout register:
+ *
+ * val = (timeout * CLK_freq) / (8192 * CCF);
+ */
+
+#define ASC_TIMEOUT_250(clk, ccf) (((clk) * 31) / (ccf))
+
+/*
+ * Sequence Step register
+ */
+
+#define ASC_SS_RESERVED 0xf0
+#define ASC_SS_SOM 0x08
+#define ASC_SS_MASK 0x07
+#define ASC_SS(ss) ((ss) & ASC_SS_MASK)
+
+/*
+ * Synchronous Transfer Period
+ */
+
+#define ASC_STP_MASK 0x1f
+#define ASC_STP_MIN 0x05 /* 5 clk per byte */
+#define ASC_STP_MAX 0x04 /* after ovfl, 35 clk/byte */
+
+/*
+ * FIFO flags
+ */
+
+#define ASC_FLAGS_SEQ_STEP 0xe0
+#define ASC_FLAGS_FIFO_CNT 0x1f
+
+/*
+ * Synchronous offset
+ */
+
+#define ASC_SYNO_MASK 0x0f /* 0 -> asyn */
+
+/*
+ * Configuration 1
+ */
+
+#define ASC_CNFG1_SLOW 0x80
+#define ASC_CNFG1_SRD 0x40
+#define ASC_CNFG1_P_TEST 0x20
+#define ASC_CNFG1_P_CHECK 0x10
+#define ASC_CNFG1_TEST 0x08
+#define ASC_CNFG1_MY_BUS_ID 0x07
+
+/*
+ * CCF register
+ */
+
+#define ASC_CCF(clk) ((((clk) - 1) / 5) + 1)
+
+/*
+ * Test register
+ */
+
+#define ASC_TEST_XXXX 0xf8
+#define ASC_TEST_HI_Z 0x04
+#define ASC_TEST_I 0x02
+#define ASC_TEST_T 0x01
+
+/*
+ * Configuration 2
+ */
+
+#define ASC_CNFG2_RFB 0x80
+#define ASC_CNFG2_EPL 0x40
+#define ASC_CNFG2_EBC 0x20
+#define ASC_CNFG2_DREQ_HIZ 0x10
+#define ASC_CNFG2_SCSI2 0x08
+#define ASC_CNFG2_BPA 0x04
+#define ASC_CNFG2_RPE 0x02
+#define ASC_CNFG2_DPE 0x01
+
+/*
+ * Configuration 3
+ */
+
+#define ASC_CNFG3_RESERVED 0xf8
+#define ASC_CNFG3_SRB 0x04
+#define ASC_CNFG3_ALT_DMA 0x02
+#define ASC_CNFG3_T8 0x01
+
+#define ST_MASK 0x3e
diff --git a/sys/arch/arc/dev/dma.c b/sys/arch/arc/dev/dma.c
new file mode 100644
index 00000000000..20d068480e5
--- /dev/null
+++ b/sys/arch/arc/dev/dma.c
@@ -0,0 +1,395 @@
+/* $OpenBSD: dma.c,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)rz.c 8.1 (Berkeley) 7/29/93
+ * $Id: dma.c,v 1.1 1996/06/24 09:07:19 pefo Exp $
+ */
+
+/*
+ * PICA system dma driver. Handles resource allocation and
+ * logical (viritual) address remaping.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+
+#include <machine/cpu.h>
+#include <machine/autoconf.h>
+#include <machine/pte.h>
+#include <machine/pio.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <arc/pica/pica.h>
+#include <arc/dev/dma.h>
+
+
+extern vm_map_t phys_map;
+
+#define dma_pte_to_pa(x) (((x) - first_dma_pte) * PICA_DMA_PAGE_SIZE)
+
+dma_pte_t *free_dma_pte; /* Pointer to free dma pte list */
+dma_pte_t *first_dma_pte; /* Pointer to first dma pte */
+
+/*
+ * Initialize the dma mapping register area and pool.
+ */
+void
+picaDmaInit()
+{
+ int map = PICA_TL_BASE;
+
+ MachFlushCache(); /* Make shure no map entries are cached */
+
+ bzero((char *)map, PICA_TL_SIZE);
+ free_dma_pte = (dma_pte_t *)map;
+ first_dma_pte = (dma_pte_t *)map;
+ free_dma_pte->queue.next = NULL;
+ free_dma_pte->queue.size = PICA_TL_SIZE / sizeof(dma_pte_t);
+
+ out32(PICA_SYS_TL_BASE, UNCACHED_TO_PHYS(map));
+ out32(PICA_SYS_TL_LIMIT, PICA_TL_SIZE);
+ out32(PICA_SYS_TL_IVALID, 0);
+}
+
+/*
+ * Allocate an array of 'size' dma pte entrys.
+ * Return address to first pte.
+ */
+void
+picaDmaTLBAlloc(dma_softc_t *dma)
+{
+ dma_pte_t *list;
+ dma_pte_t *found;
+ int size;
+ int s;
+
+ found = NULL;
+ size = dma->pte_size;
+ do {
+ list = (dma_pte_t *)&free_dma_pte;
+ s = splhigh();
+ while(list) {
+ if(list->queue.next->queue.size >= size) {
+ found = list->queue.next;
+ break;
+ }
+ }
+/*XXX Wait for release wakeup */
+ } while(found == NULL);
+ if(found->queue.size == size) {
+ list->queue.next = found->queue.next;
+ }
+ else {
+ list->queue.next = found + size;
+ list = found + size;
+ list->queue.next = found->queue.next;
+ list->queue.size = found->queue.size - size;
+ }
+ splx(s);
+ dma->pte_base = found;
+ dma->dma_va = dma_pte_to_pa(found);
+}
+
+/*
+ * Free an array of dma pte entrys.
+ */
+void
+picaDmaTLBFree(dma_softc_t *dma)
+{
+ dma_pte_t *list;
+ dma_pte_t *entry;
+ int size;
+ int s;
+
+ s = splhigh();
+ entry = dma->pte_base;
+ size = dma->pte_size;
+ entry->queue.next = NULL;
+ entry->queue.size = size;
+ if(free_dma_pte == NULL || entry < free_dma_pte) {
+ list = entry;
+ list->queue.next = free_dma_pte;
+ free_dma_pte = entry;
+ }
+ else {
+ list = free_dma_pte;
+ while(list < entry && list->queue.next != NULL) {
+ if(list + list->queue.size == entry) {
+ list->queue.size += size;
+ break;
+ }
+ else if(list->queue.next == NULL) {
+ list->queue.next = entry;
+ break;
+ }
+ else
+ list = list->queue.next;
+ }
+ }
+ if(list->queue.next != NULL) {
+ if(list + list->queue.size == list->queue.next) {
+ list->queue.size += list->queue.next->queue.size;
+ list->queue.next = list->queue.next->queue.next;
+ }
+ }
+ splx(s);
+/*XXX Wakeup waiting */
+}
+
+/*
+ * Map up a viritual address space in dma space given by
+ * the dma control structure and invalidate dma TLB cache.
+ */
+
+picaDmaTLBMap(dma_softc_t *sc)
+{
+ vm_offset_t pa;
+ vm_offset_t va;
+ dma_pte_t *dma_pte;
+ int nbytes;
+
+ va = sc->next_va - sc->dma_va;
+ dma_pte = sc->pte_base + (va / PICA_DMA_PAGE_SIZE);
+ nbytes = dma_page_round(sc->next_size + dma_page_offs(va));
+ va = sc->req_va;
+ while(nbytes > 0) {
+ if(va < VM_MIN_KERNEL_ADDRESS) {
+ pa = CACHED_TO_PHYS(va);
+ }
+ else {
+ pa = pmap_extract(vm_map_pmap(phys_map), va);
+ }
+ pa &= PICA_DMA_PAGE_NUM;
+ if(pa == 0)
+ panic("picaDmaTLBMap: null page frame");
+ dma_pte->entry.lo_addr = pa;
+ dma_pte->entry.hi_addr = 0;
+ dma_pte++;
+ va += PICA_DMA_PAGE_SIZE;
+ nbytes -= PICA_DMA_PAGE_SIZE;
+ }
+}
+
+/*
+ * Start local dma channel.
+ */
+void
+picaDmaStart(sc, addr, size, datain)
+ struct dma_softc *sc;
+ char *addr;
+ size_t size;
+ int datain;
+{
+ int mode;
+ pDmaReg regs = sc->dma_reg;
+
+ /* Halt DMA */
+ regs->dma_enab = 0;
+ regs->dma_mode = 0;
+
+ /* Remap request space va into dma space va */
+
+ sc->req_va = (int)addr;
+ sc->next_va = sc->dma_va + dma_page_offs(addr);
+ sc->next_size = size;
+
+ /* Map up the request viritual dma space */
+ picaDmaTLBMap(sc);
+ out32(PICA_SYS_TL_IVALID, 0); /* Flush dma map cache */
+
+ /* Load new transfer parameters */
+ regs->dma_addr = sc->next_va;
+ regs->dma_count = sc->next_size;
+ regs->dma_mode = sc->mode & PICA_DMA_MODE;
+
+ sc->sc_active = 1;
+ if(datain == DMA_FROM_DEV) {
+ sc->mode &= ~DMA_DIR_WRITE;
+ regs->dma_enab = PICA_DMA_ENAB_RUN | PICA_DMA_ENAB_READ;
+ }
+ else {
+ sc->mode |= DMA_DIR_WRITE;
+ regs->dma_enab = PICA_DMA_ENAB_RUN | PICA_DMA_ENAB_WRITE;
+ }
+ wbflush();
+}
+
+/*
+ * Set up DMA mapper for external dma.
+ * Used by ISA dma and SONIC
+ */
+void
+picaDmaMap(sc, addr, size, offset)
+ struct dma_softc *sc;
+ char *addr;
+ size_t size;
+ int offset;
+{
+ /* Remap request space va into dma space va */
+
+ sc->req_va = (int)addr;
+ sc->next_va = sc->dma_va + dma_page_offs(addr) + offset;
+ sc->next_size = size;
+
+ /* Map up the request viritual dma space */
+ picaDmaTLBMap(sc);
+}
+
+/*
+ * Prepare for new dma by flushing
+ */
+void
+picaDmaFlush(sc, addr, size, datain)
+ struct dma_softc *sc;
+ char *addr;
+ size_t size;
+ int datain;
+{
+ out32(PICA_SYS_TL_IVALID, 0); /* Flush dma map cache */
+}
+
+/*
+ * Stop/Reset a DMA channel
+ */
+void
+picaDmaReset(dma_softc_t *sc)
+{
+ pDmaReg regs = sc->dma_reg;
+
+ /* Halt DMA */
+ regs->dma_enab = 0;
+ regs->dma_mode = 0;
+ sc->sc_active = 0;
+}
+
+/*
+ * End dma operation, return byte count left.
+ */
+int
+picaDmaEnd(dma_softc_t *sc)
+{
+ pDmaReg regs = sc->dma_reg;
+ int res;
+
+ res = regs->dma_count = sc->next_size;
+
+ /* Halt DMA */
+ regs->dma_enab = 0;
+ regs->dma_mode = 0;
+ sc->sc_active = 0;
+
+ return res;
+}
+
+/*
+ * Null call rathole!
+ */
+void
+picaDmaNull(dma_softc_t *sc)
+{
+ pDmaReg regs = sc->dma_reg;
+
+ printf("picaDmaNull called\n");
+}
+
+/*
+ * dma_init..
+ * Called from asc to set up dma
+ */
+void
+asc_dma_init(dma_softc_t *sc)
+{
+ sc->reset = picaDmaReset;
+ sc->enintr = picaDmaNull;
+ sc->start = picaDmaStart;
+ sc->map = picaDmaMap;
+ sc->isintr = (int(*)())picaDmaNull;
+ sc->intr = (int(*)())picaDmaNull;
+ sc->end = picaDmaEnd;
+
+ sc->dma_reg = (pDmaReg)PICA_SYS_DMA0_REGS;
+ sc->pte_size = 32;
+ sc->mode = PICA_DMA_MODE_160NS | PICA_DMA_MODE_16;
+ picaDmaTLBAlloc(sc);
+}
+/*
+ * dma_init..
+ * Called from fdc to set up dma
+ */
+void
+fdc_dma_init(dma_softc_t *sc)
+{
+ sc->reset = picaDmaReset;
+ sc->enintr = picaDmaNull;
+ sc->start = picaDmaStart;
+ sc->map = picaDmaMap;
+ sc->isintr = (int(*)())picaDmaNull;
+ sc->intr = (int(*)())picaDmaNull;
+ sc->end = picaDmaEnd;
+
+ sc->dma_reg = (pDmaReg)PICA_SYS_DMA1_REGS;
+ sc->pte_size = 32;
+ sc->mode = PICA_DMA_MODE_160NS | PICA_DMA_MODE_8;
+ picaDmaTLBAlloc(sc);
+}
+/*
+ * dma_init..
+ * Called from sonic to set up dma
+ */
+void
+sn_dma_init(dma_softc_t *sc, int pages)
+{
+ sc->reset = picaDmaNull;
+ sc->enintr = picaDmaNull;
+ sc->start = picaDmaFlush;
+ sc->map = picaDmaMap;
+ sc->isintr = (int(*)())picaDmaNull;
+ sc->intr = (int(*)())picaDmaNull;
+ sc->end = (int(*)())picaDmaNull;
+
+ sc->dma_reg = (pDmaReg)NULL;
+ sc->pte_size = pages;
+ sc->mode = 0;
+ picaDmaTLBAlloc(sc);
+}
diff --git a/sys/arch/arc/dev/dma.h b/sys/arch/arc/dev/dma.h
new file mode 100644
index 00000000000..949154ca697
--- /dev/null
+++ b/sys/arch/arc/dev/dma.h
@@ -0,0 +1,151 @@
+/* $OpenBSD: dma.h,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)dma.h 8.1 (Berkeley) 6/10/93
+ * $Id: dma.h,v 1.1 1996/06/24 09:07:19 pefo Exp $
+ */
+
+/*
+ * The PICA system has four dma channels capable of scatter/gather
+ * and full memory addressing. The maximum transfer length is 1Mb.
+ * Dma snopes the L2 cache so no precaution is required. However
+ * if L1 cache is cached 'write back' the processor is responible
+ * for flushing/invalidating it.
+ *
+ * The dma mapper has up to 4096 page descriptors.
+ */
+
+#define PICA_TL_BASE 0xa0008000 /* Base of tl register area */
+#define PICA_TL_SIZE 0x00008000 /* Size of tl register area */
+
+/*
+ * Hardware dma registers.
+ */
+typedef volatile struct {
+ int dma_mode;
+ int pad1;
+ int dma_enab;
+ int pad2;
+ int dma_count;
+ int pad3;
+ vm_offset_t dma_addr;
+ int pad4;
+} DmaReg, *pDmaReg;
+
+#define PICA_DMA_MODE_40NS 0x00 /* Device dma timing */
+#define PICA_DMA_MODE_80NS 0x01 /* Device dma timing */
+#define PICA_DMA_MODE_120NS 0x02 /* Device dma timing */
+#define PICA_DMA_MODE_160NS 0x03 /* Device dma timing */
+#define PICA_DMA_MODE_200NS 0x04 /* Device dma timing */
+#define PICA_DMA_MODE_240NS 0x05 /* Device dma timing */
+#define PICA_DMA_MODE_280NS 0x06 /* Device dma timing */
+#define PICA_DMA_MODE_320NS 0x07 /* Device dma timing */
+#define PICA_DMA_MODE_8 0x08 /* Device 8 bit */
+#define PICA_DMA_MODE_16 0x10 /* Device 16 bit */
+#define PICA_DMA_MODE_32 0x18 /* Device 32 bit */
+#define PICA_DMA_MODE_INT 0x20 /* Interrupt when done */
+#define PICA_DMA_MODE_BURST 0x40 /* Burst mode (Rev 2 only) */
+#define PICA_DMA_MODE_FAST 0x80 /* Fast dma cycle (Rev 2 only) */
+#define PICA_DMA_MODE 0xff /* Mode register bits */
+#define DMA_DIR_WRITE 0x100 /* Software direction status */
+#define DMA_DIR_READ 0x000 /* Software direction status */
+
+#define PICA_DMA_ENAB_RUN 0x01 /* Enable dma */
+#define PICA_DMA_ENAB_READ 0x00 /* Read from device */
+#define PICA_DMA_ENAB_WRITE 0x02 /* Write to device */
+#define PICA_DMA_ENAB_TC_IE 0x100 /* Terminal count int enable */
+#define PICA_DMA_ENAB_ME_IE 0x200 /* Memory error int enable */
+#define PICA_DMA_ENAB_TL_IE 0x400 /* Translation limit int enable */
+
+#define PICA_DMA_COUNT_MASK 0x00fffff /* Byte count mask */
+#define PICA_DMA_PAGE_NUM 0xffff000 /* Address page number */
+#define PICA_DMA_PAGE_OFFS 0x0000fff /* Address page offset */
+#define PICA_DMA_PAGE_SIZE 0x0001000 /* Address page size */
+
+
+/*
+ * Dma TLB entry
+ */
+
+typedef union dma_pte {
+ struct {
+ vm_offset_t lo_addr; /* Low part of translation addr */
+ vm_offset_t hi_addr; /* High part of translation addr */
+ } entry;
+ struct bbb {
+ union dma_pte *next; /* Next free translation entry */
+ int size; /* Number of consecutive free entrys */
+ } queue;
+} dma_pte_t;
+
+/*
+ * Structure used to control dma.
+ */
+
+typedef struct dma_softc {
+ struct device sc_dev; /* use as a device */
+ struct esp_softc *sc_esp;
+ vm_offset_t dma_va; /* Viritual address for transfer */
+ int req_va; /* Original request va */
+ vm_offset_t next_va; /* Value to program into dma regs */
+ int next_size; /* Value to program into dma regs */
+ int mode; /* Mode register value and direction */
+ dma_pte_t *pte_base; /* Pointer to dma tlb array */
+ int pte_size; /* Size of pte allocated pte array */
+ pDmaReg dma_reg; /* Pointer to dma registers */
+ int sc_active; /* Active flag */
+ char **sc_dmaaddr; /* Pointer to dma address in dev */
+ int *sc_dmalen; /* Pointer to len counter in dev */
+ void (*reset)(struct dma_softc *); /* Reset routine pointer */
+ void (*enintr)(struct dma_softc *); /* Int enab routine pointer */
+ void (*map)(struct dma_softc *, char *, size_t, int);
+ /* Map a dma viritual area */
+ void (*start)(struct dma_softc *, caddr_t, size_t, int);
+ /* Start routine pointer */
+ int (*isintr)(struct dma_softc *); /* Int check routine pointer */
+ int (*intr)(struct dma_softc *); /* Interrupt routine pointer */
+ int (*end)(struct dma_softc *); /* Interrupt routine pointer */
+} dma_softc_t;
+
+#define DMA_TO_DEV 0
+#define DMA_FROM_DEV 1
+
+#define dma_page_offs(x) ((int)(x) & PICA_DMA_PAGE_OFFS)
+#define dma_page_round(x) (((int)(x) + PICA_DMA_PAGE_OFFS) & PICA_DMA_PAGE_NUM)
+
+#define DMA_RESET(r) ((r->reset)(r))
+#define DMA_START(a, b, c, d) ((a->start)(a, b, c, d))
+#define DMA_MAP(a, b, c, d) ((a->map)(a, b, c, d))
+#define DMA_INTR(r) ((r->intr)(r))
+#define DMA_DRAIN(r)
+#define DMA_END(r) ((r->end)(r))
diff --git a/sys/arch/arc/dev/fd.c b/sys/arch/arc/dev/fd.c
new file mode 100644
index 00000000000..aee3df4d52d
--- /dev/null
+++ b/sys/arch/arc/dev/fd.c
@@ -0,0 +1,1139 @@
+/* $OpenBSD: fd.c,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/* $NetBSD: fd.c,v 1.78 1995/07/04 07:23:09 mycroft 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
+ */
+
+#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/pio.h>
+#include <machine/autoconf.h>
+
+#include <arc/dev/fdreg.h>
+#include <arc/dev/dma.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 */
+
+ struct dma_softc __dma;
+ struct dma_softc *dma;
+
+ int sc_iobase;
+
+ 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 *));
+void fdcattach __P((struct device *, struct device *, void *));
+
+struct cfattach fdc_ca = {
+ sizeof(struct fdc_softc), fdcprobe, fdcattach
+};
+struct cfdriver fdc_cd = {
+ NULL, "fdc", DV_DULL, NULL, 0
+};
+
+/*
+ * 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, NULL, 0
+};
+
+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 confargs *ca = aux;
+ int iobase = (long)BUS_CVTADDR(ca);
+
+ if (!BUS_MATCHNAME(ca, "fdc"))
+ return (0);
+
+ /* 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, 2);
+
+ return 1;
+}
+
+/*
+ * 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 confargs *ca = aux;
+ struct fdc_attach_args fa;
+ int type;
+
+ fdc->sc_iobase = (long)BUS_CVTADDR(ca);
+ fdc->sc_state = DEVIDLE;
+ TAILQ_INIT(&fdc->sc_drives);
+
+ fdc->dma = &fdc->__dma;
+ fdc_dma_init(fdc->dma);
+
+ printf("\n");
+
+ BUS_INTR_ESTABLISH(ca, fdcintr, fdc);
+
+ /*
+ * No way yet to determine default disk types.
+ * we assume 1.44 3.5" type for the moment.
+ */
+ type = 0;
+
+ /* physical limit: two drives per controller. */
+ for (fa.fa_drive = 0; fa.fa_drive < 2; 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;
+
+ /* select drive and turn on motor */
+ outb(iobase + fdout, drive | FDO_FRST | FDO_MOEN(drive));
+ /* wait for motor to spin up */
+ delay(500000);
+ 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;
+ fd->sc_dk.dk_name = fd->sc_dev.dv_xname;
+ fd->sc_dk.dk_driver = &fddkdriver;
+ /* XXX Need to do some more fiddling with sc_dk. */
+ dk_establish(&fd->sc_dk, &fd->sc_dev);
+
+ /* 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;
+#if 0
+ switch (type) {
+ case NVRAM_DISKETTE_NONE:
+ return NULL;
+ case NVRAM_DISKETTE_12M:
+ return &fd_types[1];
+ case NVRAM_DISKETTE_TYPE5:
+ case NVRAM_DISKETTE_TYPE6:
+ /* XXX We really ought to handle 2.88MB format. */
+ case NVRAM_DISKETTE_144M:
+ return &fd_types[0];
+ case NVRAM_DISKETTE_360K:
+ return &fd_types[3];
+ case NVRAM_DISKETTE_720K:
+ return &fd_types[4];
+ default:
+ printf("%s: drive %d: unknown device type 0x%x\n",
+ fdc, drive, type);
+ return NULL;
+ }
+#else
+ return &fd_types[0]; /* Use only 1.44 for now */
+#endif
+}
+
+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;
+
+ /* 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 */
+ 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;
+
+ /* Link into controller queue. */
+ fd->sc_q.b_active = 1;
+ TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
+
+ /* 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;
+ biodone(bp);
+ /* turn off motor 5s from now */
+ timeout(fd_motor_off, fd, 10 * 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 = 400000, /* Empirical, should do at 150 Mhz to */
+ 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 .5s for motor to stabilize. */
+ timeout(fd_motor_on, fd, hz / 2);
+ 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_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
+ MachFlushDCache(bp->b_data + fd->sc_skip, fd->sc_nbytes);
+ read = bp->b_flags & B_READ ? DMA_FROM_DEV : DMA_TO_DEV;
+ DMA_START(fdc->dma, bp->b_data + fd->sc_skip, fd->sc_nbytes, read);
+ 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:
+ DMA_RESET(fdc->dma);
+
+ 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) {
+ DMA_RESET(fdc->dma);
+#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;
+ }
+ DMA_END(fdc->dma);
+ read = bp->b_flags & B_READ;
+ 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;
+ }
+ 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;
+ 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
+}
diff --git a/sys/arch/arc/dev/fdreg.h b/sys/arch/arc/dev/fdreg.h
new file mode 100644
index 00000000000..633ddf816de
--- /dev/null
+++ b/sys/arch/arc/dev/fdreg.h
@@ -0,0 +1,67 @@
+/* $OpenBSD: fdreg.h,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/* $NetBSD: fdreg.h,v 1.8 1995/06/28 04:30:57 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fdreg.h 7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * AT floppy controller registers and bitfields
+ */
+
+/* uses NEC765 controller */
+#include <dev/ic/nec765reg.h>
+
+/* registers */
+#define fdout 2 /* 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 4 /* NEC 765 Main Status Register (R) */
+#define fddata 5 /* NEC 765 Data Register (R/W) */
+
+#define fdctl 7 /* 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 7 /* Digital Input Register (R) */
+#define FDI_DCHG 0x80 /* diskette has been changed */
+
+#define FDC_BSIZE 512
+#define FDC_NPORT 8
+#define FDC_MAXIOSIZE NBPG /* XXX should be MAXBSIZE */
diff --git a/sys/arch/arc/dev/if_sn.c b/sys/arch/arc/dev/if_sn.c
new file mode 100644
index 00000000000..dfe411a6551
--- /dev/null
+++ b/sys/arch/arc/dev/if_sn.c
@@ -0,0 +1,1300 @@
+/* $OpenBSD: if_sn.c,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/*
+ * National Semiconductor SONIC Driver
+ * Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk)
+ * You may use, copy, and modify this program so long as you retain the
+ * copyright line.
+ *
+ * This driver has been substantially modified since Algorithmics donated
+ * it.
+ */
+
+#include "sn.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/buf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <machine/autoconf.h>
+
+#include <net/if.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <vm/vm.h>
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <arc/dev/dma.h>
+
+#define SONICDW 32
+typedef unsigned char uchar;
+
+#include <arc/dev/if_sn.h>
+#define SWR(a, x) (a) = (x)
+#define SRD(a) ((a) & 0xffff)
+
+#include <machine/cpu.h>
+
+/*
+ * Statistics collected over time
+ */
+struct sn_stats {
+ int ls_opacks; /* packets transmitted */
+ int ls_ipacks; /* packets received */
+ int ls_tdr; /* contents of tdr after collision */
+ int ls_tdef; /* packets where had to wait */
+ int ls_tone; /* packets with one retry */
+ int ls_tmore; /* packets with more than one retry */
+ int ls_tbuff; /* transmit buff errors */
+ int ls_tuflo; /* " uflo " */
+ int ls_tlcol;
+ int ls_tlcar;
+ int ls_trtry;
+ int ls_rbuff; /* receive buff errors */
+ int ls_rfram; /* framing */
+ int ls_roflo; /* overflow */
+ int ls_rcrc;
+ int ls_rrng; /* rx ring sequence error */
+ int ls_babl; /* chip babl error */
+ int ls_cerr; /* collision error */
+ int ls_miss; /* missed packet */
+ int ls_merr; /* memory error */
+ int ls_copies; /* copies due to out of range mbufs */
+ int ls_maxmbufs; /* max mbufs on transmit */
+ int ls_maxslots; /* max ring slots on transmit */
+};
+
+struct sn_softc {
+ struct device sc_dev;
+ struct arpcom sc_ac;
+#define sc_if sc_ac.ac_if /* network visible interface */
+#define sc_enaddr sc_ac.ac_enaddr /* hardware ethernet address */
+
+ struct sonic_reg *sc_csr; /* hardware pointer */
+ dma_softc_t __dma; /* stupid macro ... */
+ dma_softc_t *dma; /* dma mapper control */
+ int sc_rxmark; /* position in rx ring for reading buffs */
+
+ int sc_rramark; /* index into rra of wp */
+
+ int sc_txhead; /* index of first TDA passed to chip */
+ int sc_missed; /* missed packet counter */
+ struct RXpkt *sc_lrxp; /* last RDA available to chip */
+ struct sn_stats sc_sum;
+ short sc_iflags;
+} sn_softc;
+
+int snmatch __P((struct device *, void *, void *));
+void snattach __P((struct device *, struct device *, void *));
+
+struct cfattach sn_ca = {
+ sizeof(struct sn_softc), snmatch, snattach
+};
+struct cfdriver sn_cd = {
+ NULL, "sn", DV_IFNET, NULL, 0
+};
+
+#include <assert.h>
+void
+__assert(file, line, failedexpr)
+ const char *file, *failedexpr;
+ int line;
+{
+ (void)printf(
+ "assertion \"%s\" failed: file \"%s\", line %d\n",
+ failedexpr, file, line);
+}
+
+void
+m_check(m)
+ struct mbuf *m;
+{
+ if (m->m_flags & M_EXT) {
+ assert(m->m_len >= 0);
+ assert(m->m_len <= m->m_ext.ext_size);
+ assert(m->m_data >= &m->m_ext.ext_buf[0]);
+ assert(m->m_data <= &m->m_ext.ext_buf[m->m_ext.ext_size]);
+ assert(m->m_data + m->m_len <= &m->m_ext.ext_buf[m->m_ext.ext_size]);
+ } else if (m->m_flags & M_PKTHDR) {
+ assert(m->m_len >= 0);
+ assert(m->m_len <= MHLEN);
+ assert(m->m_data >= m->m_pktdat);
+ assert(m->m_data <= &m->m_pktdat[MHLEN]);
+ assert(m->m_data + m->m_len <= &m->m_pktdat[MHLEN]);
+ } else {
+ assert(m->m_len >= 0);
+ assert(m->m_len <= MLEN);
+ assert(m->m_data >= m->m_dat);
+ assert(m->m_data <= &m->m_dat[MLEN]);
+ assert(m->m_data + m->m_len <= &m->m_dat[MLEN]);
+ }
+}
+
+void
+m_checkm(m)
+ struct mbuf *m;
+{
+ while (m) {
+ m_check(m);
+ m = m->m_next;
+ }
+}
+
+int ethdebug = 0;
+
+int snintr __P((struct sn_softc *));
+int snioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
+void snstart __P((struct ifnet *ifp));
+void snwatchdog __P((struct ifnet *ifp));
+void snreset __P((struct sn_softc *sc));
+
+/*
+ * SONIC buffers need to be aligned 16 or 32 bit aligned.
+ * These macros calculate and verify alignment.
+ */
+#if SONICDW == 32
+#define SONICALIGN 4
+#else
+#define SONICALIGN 2
+#endif
+#define SOALIGN(array) (((int)array+SONICALIGN-1) & ~(SONICALIGN-1))
+#define SOALIGNED(p) (!(((uint)p)&(SONICALIGN-1)))
+
+#define UPPER(x) ((unsigned)(x) >> 16)
+#define LOWER(x) ((unsigned)(x) & 0xffff)
+
+#define NRRA 32 /* # receive resource descriptors */
+#define RRAMASK 0x1f /* why it must be poer of two */
+
+#define NRBA 16 /* # receive buffers < NRRA */
+#define NRDA NRBA /* # receive descriptors */
+#define NTDA 4 /* # transmit descriptors */
+
+#define CDASIZE sizeof(struct CDA)
+#define RRASIZE (NRRA*sizeof(struct RXrsrc))
+#define RDASIZE (NRDA*sizeof(struct RXpkt))
+#define TDASIZE (NTDA*sizeof(struct TXpkt))
+
+#define FCSSIZE 4 /* size of FCS append te received packets */
+
+/*
+ * maximum recieve packet size plus 2 byte pad to make each
+ * one aligned. 4 byte slop (required for eobc)
+ */
+#define RBASIZE (sizeof(struct ether_header) + ETHERMTU + FCSSIZE + 2 + 4)
+
+/*
+ * space requiered for descriptors
+ */
+#define DESC_SIZE (RRASIZE + CDASIZE + RDASIZE + TDASIZE + SONICALIGN - 1)
+
+/*
+ * This should really be 'allocated' but for now we
+ * 'hardwire' it.
+ */
+#define SONICBUF 0xa0010000
+
+/*
+ * Nicely aligned pointers into the sonicbuffers
+ * p_ points at physical (K1_SEG) addresses.
+ * v_ is dma viritual address used by sonic.
+ */
+struct RXrsrc *p_rra; /* receiver resource descriptors */
+struct RXrsrc *v_rra;
+struct RXpkt *p_rda; /* receiver desriptors */
+struct RXpkt *v_rda;
+struct TXpkt *p_tda; /* transmitter descriptors */
+struct TXpkt *v_tda;
+struct CDA *p_cda; /* CAM descriptors */
+struct CDA *v_cda;
+char *p_rba; /* receive buffer area base */
+char *v_rba;
+
+/* Meta transmit descriptors */
+struct mtd {
+ struct mtd *mtd_link;
+ struct TXpkt *mtd_txp;
+ struct mbuf *mtd_mbuf;
+} mtda[NTDA];
+
+struct mtd *mtdfree; /* list of free meta transmit descriptors */
+struct mtd *mtdhead; /* head of descriptors assigned to chip */
+struct mtd *mtdtail; /* tail of descriptors assigned to chip */
+struct mtd *mtdnext; /* next descriptor to give to chip */
+
+void mtd_free __P((struct mtd *));
+struct mtd *mtd_alloc __P((void));
+
+int sngetaddr __P((struct sn_softc *sc));
+int sninit __P((struct sn_softc *sc));
+int snstop __P((struct sn_softc *sc));
+int sonicput __P((struct sn_softc *sc, struct mbuf *m0));
+
+void camdump __P((struct sn_softc *sc));
+
+int
+snmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct cfdata *cf = match;
+ struct confargs *ca = aux;
+
+ /* XXX CHECK BUS */
+ /* make sure that we're looking for this type of device. */
+ if (!BUS_MATCHNAME(ca, "sonic"))
+ return (0);
+
+ return (1);
+}
+
+/*
+ * Interface exists: make available by filling in network interface
+ * record. System will initialize the interface when it is ready
+ * to accept packets.
+ */
+void
+snattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct sn_softc *sc = (void *)self;
+ struct confargs *ca = aux;
+ struct ifnet *ifp = &sc->sc_if;
+ struct cfdata *cf = sc->sc_dev.dv_cfdata;
+ int p, pp;
+
+ sc->sc_csr = (struct sonic_reg *)BUS_CVTADDR(ca);
+
+ sc->dma = &sc->__dma;
+ sn_dma_init(sc->dma, FRAGMAX * NTDA
+ + (NRBA * RBASIZE / PICA_DMA_PAGE_SIZE) + 1
+ + (DESC_SIZE * 2 / PICA_DMA_PAGE_SIZE) + 1);
+
+/*
+ * because the sonic is basicly 16bit device it 'concatenates'
+ * a higher buffer address to a 16 bit offset this will cause wrap
+ * around problems near the end of 64k !!
+ */
+ p = SONICBUF;
+ pp = SONICBUF - (FRAGMAX * NTDA * PICA_DMA_PAGE_SIZE);
+
+ if ((p ^ (p + TDASIZE)) & 0x10000)
+ p = (p + 0x10000) & ~0xffff;
+ p_tda = (struct TXpkt *) p;
+ v_tda = (struct TXpkt *)(p - pp + sc->dma->dma_va);
+ p += TDASIZE;
+
+ if ((p ^ (p + RRASIZE + CDASIZE)) & 0x10000)
+ p = (p + 0x10000) & ~0xffff;
+ p_rra = (struct RXrsrc *) p;
+ v_rra = (struct RXrsrc *)(p - pp + sc->dma->dma_va);
+ p += RRASIZE;
+
+ if ((p ^ (p + RDASIZE)) & 0x10000)
+ p = (p + 0x10000) & ~0xffff;
+ p_rda = (struct RXpkt *) p;
+ v_rda = (struct RXpkt *)(p - pp + sc->dma->dma_va);
+ p += RDASIZE;
+
+ p_cda = (struct CDA *) p;
+ v_cda = (struct CDA *)(p - pp + sc->dma->dma_va);
+ p += CDASIZE;
+
+ p += PICA_DMA_PAGE_SIZE - (p & (PICA_DMA_PAGE_SIZE -1));
+ p_rba = (char *)p;
+ v_rba = (char *)(p - pp + sc->dma->dma_va);
+ p += NRBA * RBASIZE;
+
+ DMA_MAP(sc->dma, (caddr_t)SONICBUF, p - SONICBUF, SONICBUF - pp);
+
+#if 0
+ camdump(sc);
+#endif
+ sngetaddr(sc);
+ printf(" address %s\n", ether_sprintf(sc->sc_enaddr));
+
+#if 0
+printf("\nsonic buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x rba=0x%x\n",
+ p_rra, p_cda, p_rda, p_tda, p_rba);
+printf("sonic buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x rba=0x%x\n",
+ v_rra, v_cda, v_rda, v_tda, v_rba);
+printf("mapped to offset 0x%x size 0x%x\n", SONICBUF - pp, p - SONICBUF);
+#endif
+
+ BUS_INTR_ESTABLISH(ca, (intr_handler_t)snintr, (void *)sc);
+
+ bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+ ifp->if_softc = sc;
+ ifp->if_ioctl = snioctl;
+ ifp->if_start = snstart;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_watchdog = snwatchdog;
+#if NBPFILTER > 0
+ bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+#endif
+ if_attach(ifp);
+ ether_ifattach(ifp);
+}
+
+int
+snioctl(ifp, cmd, data)
+ struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ struct ifaddr *ifa;
+ struct sn_softc *sc = ifp->if_softc;
+ int s = splnet(), err = 0;
+ int temp;
+ int error;
+
+ if ((error = ether_ioctl(ifp, &sc->sc_ac, cmd, data)) > 0) {
+ splx(s);
+ return error;
+ }
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifa = (struct ifaddr *)data;
+ ifp->if_flags |= IFF_UP;
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ (void)sninit(ifp->if_softc);
+ arp_ifinit(&sc->sc_ac, ifa);
+ break;
+#endif
+ default:
+ (void)sninit(ifp->if_softc);
+ break;
+ }
+ break;
+
+ case SIOCSIFFLAGS:
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ ifp->if_flags & IFF_RUNNING) {
+ snstop(ifp->if_softc);
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if (ifp->if_flags & IFF_UP &&
+ (ifp->if_flags & IFF_RUNNING) == 0)
+ (void)sninit(ifp->if_softc);
+ /*
+ * If the state of the promiscuous bit changes, the interface
+ * must be reset to effect the change.
+ */
+ if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) &&
+ (ifp->if_flags & IFF_RUNNING)) {
+ sc->sc_iflags = ifp->if_flags;
+ printf("change in flags\n");
+ temp = sc->sc_if.if_flags & IFF_UP;
+ snreset(sc);
+ sc->sc_if.if_flags |= temp;
+ snstart(ifp);
+ }
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if(cmd == SIOCADDMULTI)
+ err = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
+ else
+ err = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
+
+ if (err == ENETRESET) {
+ /*
+ * Multicast list has changed; set the hardware
+ * filter accordingly. But remember UP flag!
+ */
+ temp = sc->sc_if.if_flags & IFF_UP;
+ snreset(sc);
+ sc->sc_if.if_flags |= temp;
+ err = 0;
+ }
+ break;
+ default:
+ err = EINVAL;
+ }
+ splx(s);
+ return (err);
+}
+
+/*
+ * Encapsulate a packet of type family for the local net.
+ * Use trailer local net encapsulation if enough data in first
+ * packet leaves a multiple of 512 bytes of data in remainder.
+ */
+void
+snstart(ifp)
+ struct ifnet *ifp;
+{
+ struct sn_softc *sc = ifp->if_softc;
+ struct mbuf *m;
+ int len;
+
+ if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
+ return;
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ if (m == 0)
+ return;
+
+ /*
+ * If there is nothing in the o/p queue, and there is room in
+ * the Tx ring, then send the packet directly. Otherwise append
+ * it to the o/p queue.
+ */
+ if (!sonicput(sc, m)) { /* not enough space */
+ IF_PREPEND(&sc->sc_if.if_snd, m);
+ }
+#if NBPFILTER > 0
+ /*
+ * If bpf is listening on this interface, let it
+ * see the packet before we commit it to the wire.
+ */
+ if (sc->sc_if.if_bpf)
+ bpf_mtap(sc->sc_if.if_bpf, m);
+#endif
+
+ sc->sc_if.if_opackets++; /* # of pkts */
+ sc->sc_sum.ls_opacks++; /* # of pkts */
+}
+
+/*
+ * This is called from sonicioctl() when /etc/ifconfig is run to set
+ * the address or switch the i/f on.
+ */
+void caminitialise __P((void));
+void camentry __P((int, u_char *ea));
+void camprogram __P((struct sn_softc *));
+void initialise_tda __P((struct sn_softc *));
+void initialise_rda __P((struct sn_softc *));
+void initialise_rra __P((struct sn_softc *));
+
+/*
+ * reset and restart the SONIC. Called in case of fatal
+ * hardware/software errors.
+ */
+void
+snreset(sc)
+ struct sn_softc *sc;
+{
+ snstop(sc);
+ sninit(sc);
+}
+
+int
+sninit(sc)
+ struct sn_softc *sc;
+{
+ struct sonic_reg *csr = sc->sc_csr;
+ int s, error;
+
+ if (sc->sc_if.if_flags & IFF_RUNNING)
+ /* already running */
+ return (0);
+
+ s = splnet();
+
+ csr->s_cr = CR_RST; /* s_dcr only accessable reset mode! */
+
+ /* config it */
+ csr->s_dcr = DCR_LBR | DCR_SYNC | DCR_WAIT0 | DCR_DW32 | DCR_DMABLOCK |
+ DCR_RFT16 | DCR_TFT16;
+ csr->s_rcr = RCR_BRD | RCR_LBNONE;
+ csr->s_imr = IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_HBLEN | IMR_LCDEN;
+
+ /* clear pending interrupts */
+ csr->s_isr = 0x7fff;
+
+ /* clear tally counters */
+ csr->s_crct = -1;
+ csr->s_faet = -1;
+ csr->s_mpt = -1;
+
+ initialise_tda(sc);
+ initialise_rda(sc);
+ initialise_rra(sc);
+
+ /* enable the chip */
+ csr->s_cr = 0;
+ wbflush();
+
+ /* program the CAM with our address */
+ caminitialise();
+ camentry(0, sc->sc_enaddr);
+ camprogram(sc);
+
+ /* get it to read resource descriptors */
+ csr->s_cr = CR_RRRA;
+ wbflush();
+ while (csr->s_cr & CR_RRRA)
+ continue;
+
+ /* enable rx */
+ csr->s_cr = CR_RXEN;
+ wbflush();
+
+ /* flag interface as "running" */
+ sc->sc_if.if_flags |= IFF_RUNNING;
+
+ splx(s);
+ return (0);
+
+bad:
+ snstop(sc);
+ return (error);
+}
+
+/*
+ * close down an interface and free its buffers
+ * Called on final close of device, or if sninit() fails
+ * part way through.
+ */
+int
+snstop(sc)
+ struct sn_softc *sc;
+{
+ struct mtd *mtd;
+ int s = splnet();
+
+ /* stick chip in reset */
+ sc->sc_csr->s_cr = CR_RST;
+ wbflush();
+
+ /* free all receive buffers (currently static so nothing to do) */
+
+ /* free all pending transmit mbufs */
+ while (mtd = mtdhead) {
+ mtdhead = mtdhead->mtd_link;
+ if (mtd->mtd_mbuf)
+ m_freem(mtd->mtd_mbuf);
+ mtd->mtd_mbuf = 0;
+ mtd_free(mtd);
+ }
+ mtdnext = mtd_alloc();
+
+ sc->sc_if.if_timer = 0;
+ sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP);
+
+ splx(s);
+ return (0);
+}
+
+/*
+ * Called if any Tx packets remain unsent after 5 seconds,
+ * In all cases we just reset the chip, and any retransmission
+ * will be handled by higher level protocol timeouts.
+ */
+void
+snwatchdog(ifp)
+ struct ifnet *ifp;
+{
+ struct sn_softc *sc = ifp->if_softc;
+ int temp;
+
+ if (mtdhead && mtdhead->mtd_mbuf) {
+ /* something still pending for transmit */
+ if (mtdhead->mtd_txp->status == 0)
+ log(LOG_ERR, "%s%d: Tx - timeout\n",
+ sc->sc_if.if_xname, sc->sc_if.if_softc);
+ else
+ log(LOG_ERR, "%s%d: Tx - lost interrupt\n",
+ sc->sc_if.if_xname, sc->sc_if.if_softc);
+ temp = sc->sc_if.if_flags & IFF_UP;
+ snreset(sc);
+ sc->sc_if.if_flags |= temp;
+ }
+}
+/*
+ * stuff packet into sonic (at splnet)
+*/
+int
+sonicput(sc, m0)
+ struct sn_softc *sc;
+ struct mbuf *m0;
+{
+ struct sonic_reg *csr = sc->sc_csr;
+ struct TXpkt *txp;
+ struct mtd *mtdnew;
+ struct mbuf *m;
+ int len = 0, fr = 0;
+ int i;
+ int fragoffset; /* Offset in viritual dma space for fragment */
+
+ /* grab the replacement mtd */
+ if ((mtdnew = mtd_alloc()) == 0)
+ return (0);
+
+ /* this packet goes to mdtnext fill in the TDA */
+ mtdnext->mtd_mbuf = m0;
+ txp = mtdnext->mtd_txp;
+ SWR(txp->config, 0);
+ fragoffset = (txp - p_tda) * FRAGMAX * PICA_DMA_PAGE_SIZE;
+
+ /*
+ * Now fill in the fragments. Each fragment maps to it's
+ * own dma page. Fragments crossing a dma page boundary
+ * are split up in two fragments. This is somewhat stupid
+ * because the dma mapper can do the work, but it helps
+ * keeping the fragments in order. (read lazy programmer).
+ */
+ for (m = m0; m; m = m->m_next) {
+ unsigned va = (unsigned) mtod(m, caddr_t);
+ int resid = m->m_len;
+
+ if(resid != 0) {
+ MachHitFlushDCache(va, resid);
+ DMA_MAP(sc->dma, (caddr_t)va, resid, fragoffset);
+ }
+ len += resid;
+
+ while (resid) {
+ unsigned pa;
+ unsigned n;
+
+ pa = sc->dma->dma_va + (va & PGOFSET) + fragoffset;
+ n = resid;
+ if (n > NBPG - (va & PGOFSET)) {
+ n = NBPG - (va & PGOFSET);
+ }
+ if (fr < FRAGMAX) {
+ SWR(txp->u[fr].frag_ptrlo, LOWER(pa));
+ SWR(txp->u[fr].frag_ptrhi, UPPER(pa));
+ SWR(txp->u[fr].frag_size, n);
+ }
+ fr++;
+ va += n;
+ resid -= n;
+ fragoffset += PICA_DMA_PAGE_SIZE;
+ }
+ }
+ /*
+ * pad out last fragment for minimum size
+ */
+ if (len < ETHERMIN + sizeof(struct ether_header) && fr < FRAGMAX) {
+ int pad = ETHERMIN + sizeof(struct ether_header) - len;
+ static char zeros[64];
+ unsigned pa;
+
+ DMA_MAP(sc->dma, (caddr_t)zeros, pad, fragoffset);
+ pa = sc->dma->dma_va + ((unsigned)zeros & PGOFSET) + fragoffset;
+ SWR(txp->u[fr].frag_ptrlo, LOWER(pa));
+ SWR(txp->u[fr].frag_ptrhi, UPPER(pa));
+ SWR(txp->u[fr].frag_size, pad);
+ fr++;
+ len = ETHERMIN + sizeof(struct ether_header);
+ }
+
+ DMA_START(sc->dma, (caddr_t)0, 0, 0); /* Flush dma tlb */
+
+ if (fr > FRAGMAX) {
+ mtd_free(mtdnew);
+ m_freem(m0);
+ log(LOG_ERR, "%s%d: tx too many fragments %d\n",
+ sc->sc_if.if_xname, sc->sc_if.if_softc, fr);
+ sc->sc_if.if_oerrors++;
+ return (len);
+ }
+
+ SWR(txp->frag_count, fr);
+ SWR(txp->pkt_size, len);
+
+ /* link onto the next mtd that will be used */
+ SWR(txp->u[fr].tlink, LOWER(v_tda + (mtdnew->mtd_txp - p_tda)) | EOL);
+
+ if (mtdhead == 0) {
+ /* no current transmit list start with this one */
+ mtdtail = mtdhead = mtdnext;
+ csr->s_ctda = LOWER(v_tda + (txp - p_tda));
+ } else {
+ /*
+ * have a transmit list append it to end note
+ * mtdnext is already physicaly linked to mtdtail in
+ * mtdtail->mtd_txp->u[mtdtail->mtd_txp->frag_count].tlink
+ */
+ SWR(mtdtail->mtd_txp->u[mtdtail->mtd_txp->frag_count].tlink,
+ SRD(mtdtail->mtd_txp->u[mtdtail->mtd_txp->frag_count].tlink) & ~EOL);
+ mtdtail = mtdnext;
+ }
+ mtdnext->mtd_link = mtdnew;
+ mtdnext = mtdnew;
+
+ /* make sure chip is running */
+ wbflush();
+ csr->s_cr = CR_TXP;
+ wbflush();
+ sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */
+ return (len);
+}
+
+/*
+ * Read out the ethernet address from the cam. It is stored
+ * there by the boot when doing a loopback test. Thus we don't
+ * have to fetch it from nv ram.
+ */
+int
+sngetaddr(sc)
+ struct sn_softc *sc;
+{
+ unsigned i, x, y;
+ char *cp, *ea;
+
+#if 0
+ sc->sc_csr->s_cr = CR_RST;
+ wbflush();
+ sc->sc_csr->s_cep = 0;
+ i = sc->sc_csr->s_cap2;
+ wbflush();
+ sc->sc_enaddr[5] = i >> 8;
+ sc->sc_enaddr[4] = i;
+ i = sc->sc_csr->s_cap1;
+ wbflush();
+ sc->sc_enaddr[3] = i >> 8;
+ sc->sc_enaddr[2] = i;
+ i = sc->sc_csr->s_cap0;
+ wbflush();
+ sc->sc_enaddr[1] = i >> 8;
+ sc->sc_enaddr[0] = i;
+
+ sc->sc_csr->s_cr = 0;
+ wbflush();
+#else
+ sc->sc_enaddr[0] = 0x08;
+ sc->sc_enaddr[1] = 0x00;
+ sc->sc_enaddr[2] = 0x20;
+ sc->sc_enaddr[3] = 0xa0;
+ sc->sc_enaddr[4] = 0x66;
+ sc->sc_enaddr[5] = 0x54;
+#endif
+ return (0);
+}
+
+void sonictxint __P((struct sn_softc *));
+void sonicrxint __P((struct sn_softc *));
+
+int sonic_read __P((struct sn_softc *, struct RXpkt *));
+struct mbuf *sonic_get __P((struct sn_softc *, struct ether_header *, int));
+
+void
+mtd_free(mtd)
+ struct mtd *mtd;
+{
+ mtd->mtd_link = mtdfree;
+ mtdfree = mtd;
+}
+
+struct mtd *
+mtd_alloc()
+{
+ struct mtd *mtd = mtdfree;
+
+ if (mtd) {
+ mtdfree = mtd->mtd_link;
+ mtd->mtd_link = 0;
+ }
+ return (mtd);
+}
+
+/*
+ * CAM support
+ */
+void
+caminitialise()
+{
+ int i;
+
+ for (i = 0; i < MAXCAM; i++)
+ SWR(p_cda->desc[i].cam_ep, i);
+ SWR(p_cda->enable, 0);
+}
+
+void
+camentry(entry, ea)
+ int entry;
+ u_char *ea;
+{
+ SWR(p_cda->desc[entry].cam_ep, entry);
+ SWR(p_cda->desc[entry].cam_ap2, (ea[5] << 8) | ea[4]);
+ SWR(p_cda->desc[entry].cam_ap1, (ea[3] << 8) | ea[2]);
+ SWR(p_cda->desc[entry].cam_ap0, (ea[1] << 8) | ea[0]);
+ SWR(p_cda->enable, SRD(p_cda->enable) | (1 << entry));
+}
+
+void
+camprogram(sc)
+ struct sn_softc *sc;
+{
+ struct sonic_reg *csr;
+ int timeout;
+ int i;
+
+ csr = sc->sc_csr;
+ csr->s_cdp = LOWER(v_cda);
+ csr->s_cdc = MAXCAM;
+ csr->s_cr = CR_LCAM;
+ wbflush();
+
+ timeout = 10000;
+ while (csr->s_cr & CR_LCAM && timeout--)
+ continue;
+ if (timeout == 0) {
+ /* XXX */
+ panic("sonic: CAM initialisation failed\n");
+ }
+ timeout = 10000;
+ while ((csr->s_isr & ISR_LCD) == 0 && timeout--)
+ continue;
+
+ if (csr->s_isr & ISR_LCD)
+ csr->s_isr = ISR_LCD;
+ else
+ printf("sonic: CAM initialisation without interrupt\n");
+}
+
+#if 0
+void
+camdump(sc)
+ struct sn_softc *sc;
+{
+ struct sonic_reg *csr = sc->sc_csr;
+ int i;
+
+ printf("CAM entries:\n");
+ csr->s_cr = CR_RST;
+ wbflush();
+
+ for (i = 0; i < 16; i++) {
+ ushort ap2, ap1, ap0;
+ csr->s_cep = i;
+ wbflush();
+ ap2 = csr->s_cap2;
+ ap1 = csr->s_cap1;
+ ap0 = csr->s_cap0;
+ printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0);
+ }
+ printf("CAM enable 0x%x\n", csr->s_cep);
+
+ csr->s_cr = 0;
+ wbflush();
+}
+#endif
+
+void
+initialise_tda(sc)
+ struct sn_softc *sc;
+{
+ struct sonic_reg *csr;
+ struct mtd *mtd;
+ int i;
+
+ csr = sc->sc_csr;
+
+ mtdfree = mtdhead = mtdtail = (struct mtd *) 0;
+
+ for (i = 0; i < NTDA; i++) {
+ mtd = &mtda[i];
+ mtd->mtd_txp = &p_tda[i];
+ mtd->mtd_mbuf = (struct mbuf *) 0;
+ mtd_free(mtd);
+ }
+ mtdnext = mtd_alloc();
+
+ csr->s_utda = UPPER(v_tda);
+}
+
+void
+initialise_rda(sc)
+ struct sn_softc *sc;
+{
+ struct sonic_reg *csr;
+ int i;
+
+ csr = sc->sc_csr;
+
+ /* link the RDA's together into a circular list */
+ for (i = 0; i < (NRDA - 1); i++) {
+ SWR(p_rda[i].rlink, LOWER(&v_rda[i + 1]));
+ SWR(p_rda[i].in_use, 1);
+ }
+ SWR(p_rda[NRDA - 1].rlink, LOWER(&v_rda[0]) | EOL);
+ SWR(p_rda[NRDA - 1].in_use, 1);
+
+ /* mark end of receive descriptor list */
+ sc->sc_lrxp = &p_rda[NRDA - 1];
+
+ sc->sc_rxmark = 0;
+
+ csr->s_urda = UPPER(&v_rda[0]);
+ csr->s_crda = LOWER(&v_rda[0]);
+ wbflush();
+}
+
+void
+initialise_rra(sc)
+ struct sn_softc *sc;
+{
+ struct sonic_reg *csr;
+ int i;
+
+ csr = sc->sc_csr;
+
+ csr->s_eobc = RBASIZE / 2 - 2; /* must be >= MAXETHERPKT */
+ csr->s_urra = UPPER(v_rra);
+ csr->s_rsa = LOWER(v_rra);
+ csr->s_rea = LOWER(&v_rra[NRRA]);
+ csr->s_rrp = LOWER(v_rra);
+ csr->s_rsc = 0;
+
+ /* fill up SOME of the rra with buffers */
+ for (i = 0; i < NRBA; i++) {
+ SWR(p_rra[i].buff_ptrhi, UPPER(&v_rba[i * RBASIZE]));
+ SWR(p_rra[i].buff_ptrlo, LOWER(&v_rba[i * RBASIZE]));
+ SWR(p_rra[i].buff_wchi, UPPER(RBASIZE / 2));
+ SWR(p_rra[i].buff_wclo, LOWER(RBASIZE / 2));
+ }
+ sc->sc_rramark = NRBA;
+ csr->s_rwp = LOWER(&v_rra[sc->sc_rramark]);
+ wbflush();
+}
+
+int
+snintr(sc)
+ struct sn_softc *sc;
+{
+ struct sonic_reg *csr = sc->sc_csr;
+ int isr;
+
+ while (isr = (csr->s_isr & ISR_ALL)) {
+ /* scrub the interrupts that we are going to service */
+ csr->s_isr = isr;
+ wbflush();
+
+ if (isr & (ISR_BR | ISR_LCD | ISR_PINT | ISR_TC))
+ printf("sonic: unexpected interrupt status 0x%x\n", isr);
+
+ if (isr & (ISR_TXDN | ISR_TXER))
+ sonictxint(sc);
+
+ if (isr & ISR_PKTRX)
+ sonicrxint(sc);
+
+ if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
+ if (isr & ISR_HBL)
+ printf("sonic: no heartbeat\n");
+ if (isr & ISR_RDE)
+ printf("sonic: receive descriptors exhausted\n");
+ if (isr & ISR_RBE)
+ printf("sonic: receive buffers exhausted\n");
+ if (isr & ISR_RBAE)
+ printf("sonic: receive buffer area exhausted\n");
+ if (isr & ISR_RFO)
+ printf("sonic: receive FIFO overrun\n");
+ }
+ if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) {
+#ifdef notdef
+ if (isr & ISR_CRC)
+ sc->sc_crctally++;
+ if (isr & ISR_FAE)
+ sc->sc_faetally++;
+ if (isr & ISR_MP)
+ sc->sc_mptally++;
+#endif
+ }
+ }
+ return (1);
+}
+
+/*
+ * Transmit interrupt routine
+ */
+void
+sonictxint(sc)
+ struct sn_softc *sc;
+{
+ struct TXpkt *txp;
+ struct sonic_reg *csr;
+ struct mtd *mtd;
+
+ if (mtdhead == (struct mtd *) 0)
+ return;
+
+ csr = sc->sc_csr;
+
+ while (mtd = mtdhead) {
+ struct mbuf *m = mtd->mtd_mbuf;
+
+ if (m == 0)
+ break;
+
+ txp = mtd->mtd_txp;
+
+ if (SRD(txp->status) == 0) /* it hasn't really gone yet */
+ return;
+
+ if (ethdebug) {
+ struct ether_header *eh = mtod(m, struct ether_header *);
+ printf("xmit status=0x%x len=%d type=0x%x from %s",
+ txp->status,
+ txp->pkt_size,
+ htons(eh->ether_type),
+ ether_sprintf(eh->ether_shost));
+ printf(" (to %s)\n", ether_sprintf(eh->ether_dhost));
+ }
+ m_freem(m);
+ mtd->mtd_mbuf = 0;
+ mtdhead = mtd->mtd_link;
+
+ mtd_free(mtd);
+
+ if ((SRD(txp->status) & TCR_PTX) == 0) {
+ printf("sonic: Tx packet status=0x%x\n", txp->status);
+
+ if (mtdhead != mtdnext) {
+ printf("resubmitting remaining packets\n");
+ csr->s_ctda = LOWER(mtdhead->mtd_txp);
+ csr->s_cr = CR_TXP;
+ wbflush();
+ return;
+ }
+ }
+ }
+ /* mtdhead should be at mtdnext (go) */
+ assert(mtdhead == mtdnext);
+ assert(mtdhead->mtd_link == 0);
+ mtdhead = 0;
+
+ /* and start feeding any queued packets to chip */
+ while (1) {
+ struct mbuf *m;
+
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ if (m == 0) /* nothing left to send */
+ break;
+ if (!sonicput(sc, m)) { /* not enough space */
+ IF_PREPEND(&sc->sc_if.if_snd, m);
+ break;
+ }
+ }
+}
+
+/*
+ * Receive interrupt routine
+ */
+void
+sonicrxint(sc)
+ struct sn_softc *sc;
+{
+ struct sonic_reg *csr = sc->sc_csr;
+ struct RXpkt *rxp;
+ u_long addr;
+ int orra;
+
+ rxp = &p_rda[sc->sc_rxmark];
+
+ while (SRD(rxp->in_use) == 0) {
+ unsigned status = SRD(rxp->status);
+ if ((status & RCR_LPKT) == 0)
+ printf("sonic: more than one packet in RBA!\n");
+ assert(PSNSEQ(SRD(rxp->seq_no)) == 0);
+
+ if (status & RCR_PRX) {
+ if (sonic_read(sc, rxp)) {
+ sc->sc_if.if_ipackets++;
+ sc->sc_sum.ls_ipacks++;
+ sc->sc_missed = 0;
+ }
+ } else
+ sc->sc_if.if_ierrors++;
+
+ /*
+ * give receive buffer area back to chip XXX what buffer
+ * did the sonic use for this descriptor answer look at
+ * the rba sequence number !!
+ */
+ orra = RBASEQ(SRD(rxp->seq_no)) & RRAMASK;
+
+ assert(SRD(rxp->pkt_ptrhi) == SRD(p_rra[orra].buff_ptrhi));
+ assert(SRD(rxp->pkt_ptrlo) == SRD(p_rra[orra].buff_ptrlo));
+if(SRD(rxp->pkt_ptrlo) != SRD(p_rra[orra].buff_ptrlo))
+printf("%x,%x\n",SRD(rxp->pkt_ptrlo),SRD(p_rra[orra].buff_ptrlo));
+ assert(SRD(p_rra[orra].buff_wclo));
+
+ /*
+ * orra is now empty of packets and can be freed if
+ * sonic read didnt copy it out then we would have to
+ * wait !!
+ * (dont bother add it back in again straight away)
+ */
+ p_rra[sc->sc_rramark] = p_rra[orra];
+
+ /* zap old rra for fun */
+ p_rra[orra].buff_wchi = 0;
+ p_rra[orra].buff_wclo = 0;
+
+ sc->sc_rramark = (sc->sc_rramark + 1) & RRAMASK;
+ csr->s_rwp = LOWER(&v_rra[sc->sc_rramark]);
+ wbflush();
+
+ /*
+ * give recieve descriptor back to chip simple
+ * list is circular
+ */
+ SWR(rxp->in_use, 1);
+ SWR(rxp->rlink, SRD(rxp->rlink) | EOL);
+ SWR(sc->sc_lrxp->rlink, SRD(sc->sc_lrxp->rlink) & ~EOL);
+ sc->sc_lrxp = rxp;
+
+ if (++sc->sc_rxmark >= NRDA)
+ sc->sc_rxmark = 0;
+ rxp = &p_rda[sc->sc_rxmark];
+ }
+}
+
+/*
+ * sonic_read -- pull packet off interface and forward to
+ * appropriate protocol handler
+ */
+int
+sonic_read(sc, rxp)
+ struct sn_softc *sc;
+ struct RXpkt *rxp;
+{
+ struct ifnet *ifp = &sc->sc_if;
+ /*extern char *ether_sprintf();*/
+ struct ether_header *et;
+ struct mbuf *m;
+ int len, off, i;
+ caddr_t pkt;
+
+ /*
+ * Get input data length.
+ * Get pointer to ethernet header (in input buffer).
+ * Deal with trailer protocol: if type is PUP trailer
+ * get true type from first 16-bit word past data.
+ * Remember that type was trailer by setting off.
+ */
+
+ len = SRD(rxp->byte_count) - sizeof(struct ether_header) - FCSSIZE;
+ pkt = (caddr_t)((SRD(rxp->pkt_ptrhi) << 16) | SRD(rxp->pkt_ptrlo));
+ pkt = pkt - v_rba + p_rba;
+ et = (struct ether_header *)pkt;
+
+ if (ethdebug) {
+ printf("rcvd 0x%x status=0x%x, len=%d type=0x%x from %s",
+ et, rxp->status, len, htons(et->ether_type),
+ ether_sprintf(et->ether_shost));
+ printf(" (to %s)\n", ether_sprintf(et->ether_dhost));
+ }
+ if (len < ETHERMIN || len > ETHERMTU) {
+ printf("sonic: invalid packet length %d bytes\n", len);
+ return (0);
+ }
+
+#if NBPFILTER > 0
+ /*
+ * Check if there's a bpf filter listening on this interface.
+ * If so, hand off the raw packet to enet, then discard things
+ * not destined for us (but be sure to keep broadcast/multicast).
+ */
+ if (sc->sc_if.if_bpf) {
+ bpf_tap(sc->sc_if.if_bpf, pkt,
+ len + sizeof(struct ether_header));
+ if ((ifp->if_flags & IFF_PROMISC) != 0 &&
+ (et->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
+ bcmp(et->ether_dhost, sc->sc_enaddr,
+ sizeof(et->ether_dhost)) != 0)
+ return;
+ }
+#endif
+ m = sonic_get(sc, et, len);
+ if (m == NULL)
+ return (0);
+ ether_input(ifp, et, m);
+ return(1);
+}
+
+#define sonicdataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
+
+/*
+ * munge the recieved packet into an mbuf chain
+ * because we are using stupif buffer management this
+ * is slow.
+*/
+struct mbuf *
+sonic_get(sc, eh, datalen)
+ struct sn_softc *sc;
+ struct ether_header *eh;
+ int datalen;
+{
+ struct mbuf *m;
+ struct mbuf *top = 0, **mp = &top;
+ int len;
+ char *spkt = sonicdataaddr(eh, 0, caddr_t);
+ char *epkt = spkt + datalen;
+ char *cp = spkt;
+
+ epkt = cp + datalen;
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == 0)
+ return (0);
+ m->m_pkthdr.rcvif = &sc->sc_if;
+ m->m_pkthdr.len = datalen;
+ m->m_len = MHLEN;
+
+ while (datalen > 0) {
+ if (top) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == 0) {
+ m_freem(top);
+ return (0);
+ }
+ m->m_len = MLEN;
+ }
+ len = min(datalen, epkt - cp);
+ if (len >= MINCLSIZE) {
+ MCLGET(m, M_DONTWAIT);
+ if (m->m_flags & M_EXT)
+ m->m_len = len = min(len, MCLBYTES);
+ else
+ len = m->m_len;
+ } else {
+ /*
+ * Place initial small packet/header at end of mbuf.
+ */
+ if (len < m->m_len) {
+ if (top == 0 && len + max_linkhdr <= m->m_len)
+ m->m_data += max_linkhdr;
+ m->m_len = len;
+ } else
+ len = m->m_len;
+ }
+ bcopy(cp, mtod(m, caddr_t), (unsigned) len);
+ cp += len;
+ *mp = m;
+ mp = &m->m_next;
+ datalen -= len;
+ if (cp == epkt)
+ cp = spkt;
+ }
+ return (top);
+}
diff --git a/sys/arch/arc/dev/if_sn.h b/sys/arch/arc/dev/if_sn.h
new file mode 100644
index 00000000000..c2018fb43e5
--- /dev/null
+++ b/sys/arch/arc/dev/if_sn.h
@@ -0,0 +1,347 @@
+/* $OpenBSD: if_sn.h,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/*
+ * Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk)
+ * You may use, copy, and modify this program so long as you retain the
+ * copyright line.
+ */
+
+/*
+ * if_sonic.h -- National Semiconductor DP83932BVF (SONIC)
+ */
+
+/*
+ * Accessing SONIC data structures and registers as 32 bit values
+ * makes code endianess independent. The SONIC is however always in
+ * bigendian mode so it is necessary to ensure that data structures shared
+ * between the CPU and the SONIC are always in bigendian order.
+ */
+
+/*
+ * Receive Resource Descriptor
+ * This structure describes the buffers into which packets
+ * will be received. Note that more than one packet may be
+ * packed into a single buffer if constraints permit.
+ */
+#if SONICDW == 32
+struct RXrsrc {
+ u_long buff_ptrlo; /* buffer address LO */
+ u_long buff_ptrhi; /* buffer address HI */
+ u_long buff_wclo; /* buffer size (16bit words) LO */
+ u_long buff_wchi; /* buffer size (16bit words) HI */
+};
+#endif
+
+/*
+ * Receive Descriptor
+ * This structure holds information about packets received.
+ */
+#if SONICDW == 32
+struct RXpkt {
+ u_long status; /* + receive status */
+ u_long byte_count; /* + packet byte count (including FCS) */
+ u_long pkt_ptrlo; /* + packet data LO (in RBA) */
+ u_long pkt_ptrhi; /* + packet data HI (in RBA) */
+ u_long seq_no; /* + RBA sequence numbers */
+ u_long rlink; /* link to next receive descriptor */
+ u_long in_use; /* + packet available to SONIC */
+ u_long pad; /* pad to multiple of 16 bytes */
+};
+#endif
+#define RBASEQ(x) (((x)>>8)&0xff)
+#define PSNSEQ(x) ((x) & 0xff)
+
+/*
+ * Transmit Descriptor
+ * This structure holds information about packets to be transmitted.
+ */
+#define FRAGMAX 31 /* maximum number of fragments in a packet */
+#if SONICDW == 32
+struct TXpkt {
+ u_long status; /* + transmitted packet status */
+ u_long config; /* transmission configuration */
+ u_long pkt_size; /* entire packet size in bytes */
+ u_long frag_count; /* # fragments in packet */
+ union {
+ struct {
+ u_long _frag_ptrlo; /* pointer to packet fragment LO */
+ u_long _frag_ptrhi; /* pointer to packet fragment HI */
+ u_long _frag_size; /* fragment size */
+ } u_frag;
+ struct {
+ u_long _tlink; /* link to next transmit descriptor */
+ } u_link;
+ } u[FRAGMAX+1]; /* +1 makes tcp->u[FRAGMAX].u_link.link valid! */
+};
+#endif
+
+#define frag_ptrlo u_frag._frag_ptrlo
+#define frag_ptrhi u_frag._frag_ptrhi
+#define frag_size u_frag._frag_size
+#define tlink u_link._tlink
+
+#define EOL 0x0001 /* end of list marker for link fields */
+
+#define MAXCAM 16 /* number of user entries in CAM */
+#if SONICDW == 32
+struct CDA {
+ struct {
+ u_long cam_ep; /* CAM Entry Pointer */
+ u_long cam_ap0; /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
+ u_long cam_ap1; /* CAM Address Port 1 xx-xx-YY-YY-xxxx */
+ u_long cam_ap2; /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
+ } desc[MAXCAM];
+ u_long enable; /* mask enabling CAM entries */
+};
+#endif
+
+/*
+ * SONIC registers as seen by the processor
+ */
+struct sonic_reg {
+ volatile u_long s_cr; /* 00: Command */
+ volatile u_long s_dcr; /* 01: Data Configuration */
+ volatile u_long s_rcr; /* 02: Receive Control */
+ volatile u_long s_tcr; /* 03: Transmit Control */
+ volatile u_long s_imr; /* 04: Interrupt Mask */
+ volatile u_long s_isr; /* 05: Interrupt Status */
+ volatile u_long s_utda; /* 06: Upper Transmit Descriptor Address */
+ volatile u_long s_ctda; /* 07: Current Transmit Descriptor Address */
+ volatile u_long _s_tps; /* 08* Transmit Packet Size */
+ volatile u_long _s_tfc; /* 09* Transmit Fragment Count */
+ volatile u_long _s_tsa0; /* 0a* Transmit Start Address 0 */
+ volatile u_long _s_tsa1; /* 0b* Transmit Start Address 1 */
+ volatile u_long _s_tfs; /* 0c* Transmit Fragment Size */
+ volatile u_long s_urda; /* 0d: Upper Receive Descriptor Address */
+ volatile u_long s_crda; /* 0e: Current Receive Descriptor Address */
+ volatile u_long _s_crba0; /* 0f* Current Receive Buffer Address 0 */
+ volatile u_long _s_crba1; /* 10* Current Receive Buffer Address 1 */
+ volatile u_long _s_rbwc0; /* 11* Remaining Buffer Word Count 0 */
+ volatile u_long _s_rbwc1; /* 12* Remaining Buffer Word Count 1 */
+ volatile u_long s_eobc; /* 13: End Of Buffer Word Count */
+ volatile u_long s_urra; /* 14: Upper Receive Resource Address */
+ volatile u_long s_rsa; /* 15: Resource Start Address */
+ volatile u_long s_rea; /* 16: Resource End Address */
+ volatile u_long s_rrp; /* 17: Resource Read Pointer */
+ volatile u_long s_rwp; /* 18: Resource Write Pointer */
+ volatile u_long _s_trba0; /* 19* Temporary Receive Buffer Address 0 */
+ volatile u_long _s_trba1; /* 1a* Temporary Receive Buffer Address 1 */
+ volatile u_long _s_tbwc0; /* 1b* Temporary Buffer Word Count 0 */
+ volatile u_long _s_tbwc1; /* 1c* Temporary Buffer Word Count 1 */
+ volatile u_long _s_addr0; /* 1d* Address Generator 0 */
+ volatile u_long _s_addr1; /* 1e* Address Generator 1 */
+ volatile u_long _s_llfa; /* 1f* Last Link Field Address */
+ volatile u_long _s_ttda; /* 20* Temp Transmit Descriptor Address */
+ volatile u_long s_cep; /* 21: CAM Entry Pointer */
+ volatile u_long s_cap2; /* 22: CAM Address Port 2 */
+ volatile u_long s_cap1; /* 23: CAM Address Port 1 */
+ volatile u_long s_cap0; /* 24: CAM Address Port 0 */
+ volatile u_long s_ce; /* 25: CAM Enable */
+ volatile u_long s_cdp; /* 26: CAM Descriptor Pointer */
+ volatile u_long s_cdc; /* 27: CAM Descriptor Count */
+ volatile u_long s_sr; /* 28: Silicon Revision */
+ volatile u_long s_wt0; /* 29: Watchdog Timer 0 */
+ volatile u_long s_wt1; /* 2a: Watchdog Timer 1 */
+ volatile u_long s_rsc; /* 2b: Receive Sequence Counter */
+ volatile u_long s_crct; /* 2c: CRC Error Tally */
+ volatile u_long s_faet; /* 2d: FAE Tally */
+ volatile u_long s_mpt; /* 2e: Missed Packet Tally */
+ volatile u_long _s_mdt; /* 2f* Maximum Deferral Timer */
+ volatile u_long _s_rtc; /* 30* Receive Test Control */
+ volatile u_long _s_ttc; /* 31* Transmit Test Control */
+ volatile u_long _s_dtc; /* 32* DMA Test Control */
+ volatile u_long _s_cc0; /* 33* CAM Comparison 0 */
+ volatile u_long _s_cc1; /* 34* CAM Comparison 1 */
+ volatile u_long _s_cc2; /* 35* CAM Comparison 2 */
+ volatile u_long _s_cm; /* 36* CAM Match */
+ volatile u_long :32; /* 37* reserved */
+ volatile u_long :32; /* 38* reserved */
+ volatile u_long _s_rbc; /* 39* Receiver Byte Count */
+ volatile u_long :32; /* 3a* reserved */
+ volatile u_long _s_tbo; /* 3b* Transmitter Backoff Counter */
+ volatile u_long _s_trc; /* 3c* Transmitter Random Counter */
+ volatile u_long _s_tbm; /* 3d* Transmitter Backoff Mask */
+ volatile u_long :32; /* 3e* Reserved */
+ volatile u_long s_dcr2; /* 3f Data Configuration 2 (AVF) */
+};
+
+/*
+ * Register Interpretations
+ */
+
+/*
+ * The command register is used for issuing commands to the SONIC.
+ * With the exception of CR_RST, the bit is reset when the operation
+ * completes.
+ */
+#define CR_LCAM 0x0200 /* load CAM with descriptor at s_cdp */
+#define CR_RRRA 0x0100 /* read next RRA descriptor at s_rrp */
+#define CR_RST 0x0080 /* software reset */
+#define CR_ST 0x0020 /* start timer */
+#define CR_STP 0x0010 /* stop timer */
+#define CR_RXEN 0x0008 /* receiver enable */
+#define CR_RXDIS 0x0004 /* receiver disable */
+#define CR_TXP 0x0002 /* transmit packets */
+#define CR_HTX 0x0001 /* halt transmission */
+
+/*
+ * The data configuration register establishes the SONIC's bus cycle
+ * operation. This register can only be accessed when the SONIC is in
+ * reset mode (s_cr.CR_RST is set.)
+ */
+#define DCR_EXBUS 0x8000 /* extended bus mode (AVF) */
+#define DCR_LBR 0x2000 /* latched bus retry */
+#define DCR_PO1 0x1000 /* programmable output 1 */
+#define DCR_PO0 0x0800 /* programmable output 0 */
+#define DCR_STERM 0x0400 /* synchronous termination */
+#define DCR_USR1 0x0200 /* reflects USR1 input pin */
+#define DCR_USR0 0x0100 /* reflects USR0 input pin */
+#define DCR_WC1 0x0080 /* wait state control 1 */
+#define DCR_WC0 0x0040 /* wait state control 0 */
+#define DCR_DW 0x0020 /* data width select */
+#define DCR_BMS 0x0010 /* DMA block mode select */
+#define DCR_RFT1 0x0008 /* receive FIFO threshold control 1 */
+#define DCR_RFT0 0x0004 /* receive FIFO threshold control 0 */
+#define DCR_TFT1 0x0002 /* transmit FIFO threshold control 1 */
+#define DCR_TFT0 0x0001 /* transmit FIFO threshold control 0 */
+
+/* data configuration register aliases */
+#define DCR_SYNC DCR_STERM /* synchronous (memory cycle 2 clocks) */
+#define DCR_ASYNC 0 /* asynchronous (memory cycle 3 clocks) */
+
+#define DCR_WAIT0 0 /* 0 wait states added */
+#define DCR_WAIT1 DCR_WC0 /* 1 wait state added */
+#define DCR_WAIT2 DCR_WC1 /* 2 wait states added */
+#define DCR_WAIT3 (DCR_WC1|DCR_WC0) /* 3 wait states added */
+
+#define DCR_DW16 0 /* use 16-bit DMA accesses */
+#define DCR_DW32 DCR_DW /* use 32-bit DMA accesses */
+
+#define DCR_DMAEF 0 /* DMA until TX/RX FIFO has emptied/filled */
+#define DCR_DMABLOCK DCR_BMS /* DMA until RX/TX threshold crossed */
+
+#define DCR_RFT4 0 /* receive threshold 4 bytes */
+#define DCR_RFT8 DCR_RFT0 /* receive threshold 8 bytes */
+#define DCR_RFT16 DCR_RFT1 /* receive threshold 16 bytes */
+#define DCR_RFT24 (DCR_RFT1|DCR_RFT0) /* receive threshold 24 bytes */
+
+#define DCR_TFT8 0 /* transmit threshold 8 bytes */
+#define DCR_TFT16 DCR_TFT0 /* transmit threshold 16 bytes */
+#define DCR_TFT24 DCR_TFT1 /* transmit threshold 24 bytes */
+#define DCR_TFT28 (DCR_TFT1|DCR_TFT0) /* transmit threshold 28 bytes */
+
+/*
+ * The receive control register is used to filter incoming packets and
+ * provides status information on packets received.
+ * The contents of the register are copied into the RXpkt.status field
+ * when a packet is received. RCR_MC - RCR_PRX are then reset.
+ */
+#define RCR_ERR 0x8000 /* accept packets with CRC errors */
+#define RCR_RNT 0x4000 /* accept runt (length < 64) packets */
+#define RCR_BRD 0x2000 /* accept broadcast packets */
+#define RCR_PRO 0x1000 /* accept all physical address packets */
+#define RCR_AMC 0x0800 /* accept all multicast packets */
+#define RCR_LB1 0x0400 /* loopback control 1 */
+#define RCR_LB0 0x0200 /* loopback control 0 */
+#define RCR_MC 0x0100 /* multicast packet received */
+#define RCR_BC 0x0080 /* broadcast packet received */
+#define RCR_LPKT 0x0040 /* last packet in RBA (RBWC < EOBC) */
+#define RCR_CRS 0x0020 /* carrier sense activity */
+#define RCR_COL 0x0010 /* collision activity */
+#define RCR_CRC 0x0008 /* CRC error */
+#define RCR_FAE 0x0004 /* frame alignment error */
+#define RCR_LBK 0x0002 /* loopback packet received */
+#define RCR_PRX 0x0001 /* packet received without errors */
+
+/* receiver control register aliases */
+/* the loopback control bits provide the following options */
+#define RCR_LBNONE 0 /* no loopback - normal operation */
+#define RCR_LBMAC RCR_LB0 /* MAC loopback */
+#define RCR_LBENDEC RCR_LB1 /* ENDEC loopback */
+#define RCR_LBTRANS (RCR_LB1|RCR_LB0) /* transceiver loopback */
+
+/*
+ * The transmit control register controls the SONIC's transmit operations.
+ * TCR_PINT - TCR_EXDIS are loaded from the TXpkt.config field at the
+ * start of transmission. TCR_EXD-TCR_PTX are cleared at the beginning
+ * of transmission and updated when the transmission is completed.
+ */
+#define TCR_PINT 0x8000 /* interrupt when transmission starts */
+#define TCR_POWC 0x4000 /* program out of window collision timer */
+#define TCR_CRCI 0x2000 /* transmit packet without 4 byte FCS */
+#define TCR_EXDIS 0x1000 /* disable excessive deferral timer */
+#define TCR_EXD 0x0400 /* excessive deferrals occurred (>3.2ms) */
+#define TCR_DEF 0x0200 /* deferred transmissions occurred */
+#define TCR_NCRS 0x0100 /* carrier not present during transmission */
+#define TCR_CRSL 0x0080 /* carrier lost during transmission */
+#define TCR_EXC 0x0040 /* excessive collisions (>16) detected */
+#define TCR_OWC 0x0020 /* out of window (bad) collision occurred */
+#define TCR_PMB 0x0008 /* packet monitored bad - the tansmitted
+ * packet had a bad source address or CRC */
+#define TCR_FU 0x0004 /* FIFO underrun (memory access failed) */
+#define TCR_BCM 0x0002 /* byte count mismatch (TXpkt.pkt_size
+ * != sum(TXpkt.frag_size) */
+#define TCR_PTX 0x0001 /* packet transmitted without errors */
+
+/* transmit control register aliases */
+#define TCR_OWCSFD 0 /* start after start of frame delimiter */
+#define TCR_OWCPRE TCR_POWC /* start after first bit of preamble */
+
+
+/*
+ * The interrupt mask register masks the interrupts that
+ * are generated from the interrupt status register.
+ * All reserved bits should be written with 0.
+ */
+#define IMR_BREN 0x4000 /* bus retry occurred enable */
+#define IMR_HBLEN 0x2000 /* heartbeat lost enable */
+#define IMR_LCDEN 0x1000 /* load CAM done interrupt enable */
+#define IMR_PINTEN 0x0800 /* programmable interrupt enable */
+#define IMR_PRXEN 0x0400 /* packet received enable */
+#define IMR_PTXEN 0x0200 /* packet transmitted enable */
+#define IMR_TXEREN 0x0100 /* transmit error enable */
+#define IMR_TCEN 0x0080 /* timer complete enable */
+#define IMR_RDEEN 0x0040 /* receive descriptors exhausted enable */
+#define IMR_RBEEN 0x0020 /* receive buffers exhausted enable */
+#define IMR_RBAEEN 0x0010 /* receive buffer area exceeded enable */
+#define IMR_CRCEN 0x0008 /* CRC tally counter rollover enable */
+#define IMR_FAEEN 0x0004 /* FAE tally counter rollover enable */
+#define IMR_MPEN 0x0002 /* MP tally counter rollover enable */
+#define IMR_RFOEN 0x0001 /* receive FIFO overrun enable */
+
+
+/*
+ * The interrupt status register indicates the source of an interrupt when
+ * the INT pin goes active. The interrupt is acknowledged by writing
+ * the appropriate bit(s) in this register.
+ */
+#define ISR_ALL 0xffff /* all interrupts */
+#define ISR_BR 0x4000 /* bus retry occurred */
+#define ISR_HBL 0x2000 /* CD heartbeat lost */
+#define ISR_LCD 0x1000 /* load CAM command has completed */
+#define ISR_PINT 0x0800 /* programmed interrupt from TXpkt.config */
+#define ISR_PKTRX 0x0400 /* packet received */
+#define ISR_TXDN 0x0200 /* no remaining packets to be transmitted */
+#define ISR_TXER 0x0100 /* packet transmission caused error */
+#define ISR_TC 0x0080 /* timer complete */
+#define ISR_RDE 0x0040 /* receive descriptors exhausted */
+#define ISR_RBE 0x0020 /* receive buffers exhausted */
+#define ISR_RBAE 0x0010 /* receive buffer area exceeded */
+#define ISR_CRC 0x0008 /* CRC tally counter rollover */
+#define ISR_FAE 0x0004 /* FAE tally counter rollover */
+#define ISR_MP 0x0002 /* MP tally counter rollover */
+#define ISR_RFO 0x0001 /* receive FIFO overrun */
+
+/*
+ * The second data configuration register allows additional user defined
+ * pins to be controlled. These bits are only available if s_dcr.DCR_EXBUS
+ * is set.
+ */
+#define DCR2_EXPO3 0x8000 /* EXUSR3 output */
+#define DCR2_EXPO2 0x4000 /* EXUSR2 output */
+#define DCR2_EXPO1 0x2000 /* EXUSR1 output */
+#define DCR2_EXPO0 0x1000 /* EXUSR0 output */
+#define DCR2_PHL 0x0010 /* extend HOLD signal by 1/2 clock */
+#define DCR2_LRDY 0x0008 /* set latched ready mode */
+#define DCR2_PCM 0x0004 /* packet compress on match */
+#define DCR2_PCNM 0x0002 /* packet compress on mismatch */
+#define DCR2_RJM 0x0001 /* reject on match */
diff --git a/sys/arch/arc/dev/lpt.c b/sys/arch/arc/dev/lpt.c
new file mode 100644
index 00000000000..da3e62733ba
--- /dev/null
+++ b/sys/arch/arc/dev/lpt.c
@@ -0,0 +1,676 @@
+/* $OpenBSD: lpt.c,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/* $NetBSD: lpt.c,v 1.39 1996/05/12 23:53:06 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1993, 1994 Charles Hannum.
+ * Copyright (c) 1990 William F. Jolitz, TeleMuse
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This software is a component of "386BSD" developed by
+ * William F. Jolitz, TeleMuse.
+ * 4. Neither the name of the developer nor the name "386BSD"
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
+ * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
+ * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
+ * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
+ * NOT MAKE USE OF THIS WORK.
+ *
+ * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
+ * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
+ * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
+ * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
+ * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
+ * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
+ * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
+ * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Device Driver for AT parallel printer port
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/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/conf.h>
+#include <sys/syslog.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/lptreg.h>
+
+#include <lpt.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(DEBUG) || !defined(notdef)
+#define LPRINTF(a)
+#else
+#define LPRINTF if (lptdebug) printf a
+int lptdebug = 1;
+#endif
+
+struct lpt_softc {
+ struct device sc_dev;
+ void *sc_ih;
+
+ size_t sc_count;
+ struct buf *sc_inbuf;
+ u_char *sc_cp;
+ int sc_spinmax;
+ int sc_iobase;
+ bus_chipset_tag_t sc_bc;
+ bus_io_handle_t sc_ioh;
+ 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 */
+ 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;
+};
+
+/* XXX does not belong here */
+cdev_decl(lpt);
+
+int lptintr __P((void *));
+
+#if NLPT_ISA
+int lpt_isa_probe __P((struct device *, void *, void *));
+void lpt_isa_attach __P((struct device *, struct device *, void *));
+struct cfattach lpt_ca = {
+ sizeof(struct lpt_softc), lpt_isa_probe, lpt_isa_attach
+};
+#endif
+
+#if NLPT_PICA
+int lpt_pica_probe __P((struct device *, void *, void *));
+void lpt_pica_attach __P((struct device *, struct device *, void *));
+struct cfattach lpt_pica_ca = {
+ sizeof(struct lpt_softc), lpt_pica_probe, lpt_pica_attach
+};
+#endif
+
+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() ((bus_io_read_1(bc, ioh, lpt_status) ^ LPS_INVERT) & LPS_MASK)
+#define NOT_READY_ERR() not_ready(bus_io_read_1(bc, ioh, 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 *));
+
+int lpt_port_test __P((bus_chipset_tag_t, bus_io_handle_t, bus_io_addr_t,
+ bus_io_size_t, u_char, u_char));
+
+/*
+ * Internal routine to lptprobe to do port tests of one byte value.
+ */
+int
+lpt_port_test(bc, ioh, base, off, data, mask)
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ bus_io_addr_t base;
+ bus_io_size_t off;
+ u_char data, mask;
+{
+ int timeout;
+ u_char temp;
+
+ data &= mask;
+ bus_io_write_1(bc, ioh, off, data);
+ timeout = 1000;
+ do {
+ delay(10);
+ temp = bus_io_read_1(bc, ioh, off) & mask;
+ } while (temp != data && --timeout);
+ LPRINTF(("lpt: port=0x%x out=0x%x in=0x%x timeout=%d\n", base + off,
+ 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
+ */
+#if NLPT_ISA
+int
+lpt_isa_probe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct isa_attach_args *ia = aux;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ u_long base;
+ u_char mask, data;
+ int i, rv;
+
+#ifdef DEBUG
+#define ABORT do {printf("lptprobe: mask %x data %x failed\n", mask, data); \
+ goto out;} while (0)
+#else
+#define ABORT goto out
+#endif
+
+ bc = ia->ia_bc;
+ base = ia->ia_iobase;
+ if (bus_io_map(bc, base, LPT_NPORTS, &ioh))
+ return 0;
+
+ rv = 0;
+ mask = 0xff;
+
+ data = 0x55; /* Alternating zeros */
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
+ ABORT;
+
+ data = 0xaa; /* Alternating ones */
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
+ ABORT;
+
+ for (i = 0; i < CHAR_BIT; i++) { /* Walking zero */
+ data = ~(1 << i);
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
+ ABORT;
+ }
+
+ for (i = 0; i < CHAR_BIT; i++) { /* Walking one */
+ data = (1 << i);
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
+ ABORT;
+ }
+
+ bus_io_write_1(bc, ioh, lpt_data, 0);
+ bus_io_write_1(bc, ioh, lpt_control, 0);
+
+ ia->ia_iosize = LPT_NPORTS;
+ ia->ia_msize = 0;
+
+ rv = 1;
+
+out:
+ bus_io_unmap(bc, ioh, LPT_NPORTS);
+ return rv;
+}
+#endif
+
+#if NLPT_PICA
+int
+lpt_pica_probe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct confargs *ca = aux;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ u_long base;
+ 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
+
+ if(!BUS_MATCHNAME(ca, "lpt"))
+ return(0);
+
+ bc = 0;
+ base = (int)BUS_CVTADDR(ca);
+ ioh = base;
+
+ mask = 0xff;
+
+ data = 0x55; /* Alternating zeros */
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
+ ABORT;
+
+ data = 0xaa; /* Alternating ones */
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
+ ABORT;
+
+ for (i = 0; i < CHAR_BIT; i++) { /* Walking zero */
+ data = ~(1 << i);
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
+ ABORT;
+ }
+
+ for (i = 0; i < CHAR_BIT; i++) { /* Walking one */
+ data = (1 << i);
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
+ ABORT;
+ }
+
+ bus_io_write_1(bc, ioh, lpt_data, 0);
+ bus_io_write_1(bc, ioh, lpt_control, 0);
+
+ return 1;
+}
+#endif
+
+#if NLPT_ISA
+void
+lpt_isa_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct lpt_softc *sc = (void *)self;
+ struct isa_attach_args *ia = aux;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+
+ if (ia->ia_irq != IRQUNK)
+ printf("\n");
+ else
+ printf(": polled\n");
+
+ sc->sc_iobase = ia->ia_iobase;
+ sc->sc_irq = ia->ia_irq;
+ sc->sc_state = 0;
+
+ bc = sc->sc_bc = ia->ia_bc;
+ if (bus_io_map(bc, sc->sc_iobase, LPT_NPORTS, &ioh))
+ panic("lptattach: couldn't map I/O ports");
+ sc->sc_ioh = ioh;
+
+ bus_io_write_1(bc, ioh, lpt_control, LPC_NINIT);
+
+ if (ia->ia_irq != IRQUNK)
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_TTY, lptintr, sc, sc->sc_dev.dv_xname);
+}
+#endif
+
+#if NLPT_PICA
+void
+lpt_pica_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct lpt_softc *sc = (void *)self;
+ struct confargs *ca = aux;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+
+ printf("\n");
+
+ sc->sc_iobase = (int)BUS_CVTADDR(ca);
+ sc->sc_irq = 0;
+ sc->sc_state = 0;
+
+ bc = sc->sc_bc = 0;
+ sc->sc_ioh = sc->sc_iobase;
+
+ bus_io_write_1(bc, ioh, lpt_control, LPC_NINIT);
+
+ BUS_INTR_ESTABLISH(ca, lptintr, sc);
+}
+#endif
+
+/*
+ * Reset the printer, then wait until it's selected and not busy.
+ */
+int
+lptopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ int unit = LPTUNIT(dev);
+ u_char flags = LPTFLAGS(dev);
+ struct lpt_softc *sc;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ 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));
+ bc = sc->sc_bc;
+ ioh = sc->sc_ioh;
+
+ if ((flags & LPT_NOPRIME) == 0) {
+ /* assert INIT for 100 usec to start up printer */
+ bus_io_write_1(bc, ioh, lpt_control, LPC_SELECT);
+ delay(100);
+ }
+
+ control = LPC_SELECT | LPC_NINIT;
+ bus_io_write_1(bc, ioh, 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 */
+ error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptopen", STEP);
+ if (error != 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;
+ bus_io_write_1(bc, ioh, 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.
+ */
+int
+lptclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ int unit = LPTUNIT(dev);
+ struct lpt_softc *sc = lpt_cd.cd_devs[unit];
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
+
+ if (sc->sc_count)
+ (void) pushbytes(sc);
+
+ if ((sc->sc_flags & LPT_NOINTR) == 0)
+ untimeout(lptwakeup, sc);
+
+ bus_io_write_1(bc, ioh, lpt_control, LPC_NINIT);
+ sc->sc_state = 0;
+ bus_io_write_1(bc, ioh, 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;
+{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
+ 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;
+ }
+
+ bus_io_write_1(bc, ioh, lpt_data, *sc->sc_cp++);
+ bus_io_write_1(bc, ioh, lpt_control, control | LPC_STROBE);
+ sc->sc_count--;
+ bus_io_write_1(bc, ioh, 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);
+ }
+ error = tsleep((caddr_t)sc, LPTPRI | PCATCH,
+ "lptwrite2", 0);
+ if (error)
+ 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.
+ */
+int
+lptwrite(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ struct lpt_softc *sc = lpt_cd.cd_devs[LPTUNIT(dev)];
+ size_t n;
+ int error = 0;
+
+ while ((n = min(LPT_BSIZE, uio->uio_resid)) != 0) {
+ 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;
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
+
+ if (((sc->sc_state & LPT_OPEN) == 0 && sc->sc_count == 0) || (sc->sc_flags & LPT_NOINTR))
+ return 0;
+
+ /* is printer online and ready for output */
+ if (NOT_READY() && NOT_READY_ERR())
+ return -1;
+
+ if (sc->sc_count) {
+ u_char control = sc->sc_control;
+ /* send char */
+ bus_io_write_1(bc, ioh, lpt_data, *sc->sc_cp++);
+ bus_io_write_1(bc, ioh, lpt_control, control | LPC_STROBE);
+ sc->sc_count--;
+ bus_io_write_1(bc, ioh, 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, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ int error = 0;
+
+ switch (cmd) {
+ default:
+ error = ENODEV;
+ }
+
+ return error;
+}
diff --git a/sys/arch/arc/dev/pccons.c b/sys/arch/arc/dev/pccons.c
new file mode 100644
index 00000000000..edc39878791
--- /dev/null
+++ b/sys/arch/arc/dev/pccons.c
@@ -0,0 +1,2094 @@
+/* $OpenBSD: pccons.c,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/* $NetBSD: pccons.c,v 1.89 1995/05/04 19:35:20 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994, 1995 Charles Hannum. All rights reserved.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz and Don Ahn.
+ *
+ * Copyright (c) 1994 Charles Hannum.
+ * Copyright (c) 1992, 1993 Erik Forsberg.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with 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.
+ *
+ * @(#)pccons.c 5.11 (Berkeley) 5/21/91
+ */
+
+/*
+ * code to work keyboard & display for PC-style console
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/tty.h>
+#include <sys/uio.h>
+#include <sys/callout.h>
+#include <sys/syslog.h>
+#include <sys/vnode.h>
+#include <sys/device.h>
+#include <sys/file.h>
+
+#include <dev/cons.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+#include <machine/autoconf.h>
+#include <machine/display.h>
+#include <machine/pccons.h>
+#include <arc/pica/pica.h>
+
+#include <dev/isa/isavar.h>
+#include <machine/kbdreg.h>
+
+#define XFREE86_BUG_COMPAT
+
+#ifndef BEEP_FREQ
+#define BEEP_FREQ 1600
+#endif
+#ifndef BEEP_TIME
+#define BEEP_TIME (hz/5)
+#endif
+
+#define PCBURST 128
+
+static u_short *Crtat; /* pointer to backing store */
+static u_short *crtat; /* pointer to current char */
+static u_char async, kernel, polling; /* Really, you don't want to know. */
+static u_char lock_state = 0x00, /* all off */
+ old_lock_state = 0xff,
+ typematic_rate = 0xff, /* don't update until set by user */
+ old_typematic_rate = 0xff;
+static u_short cursor_shape = 0xffff, /* don't update until set by user */
+ old_cursor_shape = 0xffff;
+static keymap_t scan_codes[KB_NUM_KEYS];/* keyboard translation table */
+int pc_xmode = 0;
+
+/*
+ * Keyboard output queue.
+ */
+int kb_oq_put = 0;
+int kb_oq_get = 0;
+u_char kb_oq[8];
+
+#define PCUNIT(x) (minor(x))
+
+static struct video_state {
+ int cx, cy; /* escape parameters */
+ int row, col; /* current cursor position */
+ int nrow, ncol, nchr; /* current screen geometry */
+ u_char state; /* parser state */
+#define VSS_ESCAPE 1
+#define VSS_EBRACE 2
+#define VSS_EPARAM 3
+ char so; /* in standout mode? */
+ char color; /* color or mono display */
+ char at; /* normal attributes */
+ char so_at; /* standout attributes */
+} vs;
+
+struct pc_softc {
+ struct device sc_dev;
+ struct tty *sc_tty;
+};
+
+struct pms_softc { /* driver status information */
+ struct device sc_dev;
+
+ struct clist sc_q;
+ struct selinfo sc_rsel;
+ u_char sc_state; /* mouse driver state */
+#define PMS_OPEN 0x01 /* device is open */
+#define PMS_ASLP 0x02 /* waiting for mouse data */
+ u_char sc_status; /* mouse button status */
+ int sc_x, sc_y; /* accumulated motion in the X,Y axis */
+};
+
+int pcprobe __P((struct device *, void *, void *));
+void pcattach __P((struct device *, struct device *, void *));
+int pcintr __P((void *));
+
+struct cfattach pc_ca = {
+ sizeof(struct pc_softc), pcprobe, pcattach
+};
+struct cfdriver pc_cd = {
+ NULL, "pc", DV_TTY, NULL, 0
+};
+
+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_TTY, NULL, 0
+};
+
+#define PMSUNIT(dev) (minor(dev))
+
+#define COL 80
+#define ROW 25
+#define CHR 2
+
+static unsigned int addr_6845 = MONO_BASE;
+
+char *sget __P((void));
+void sput __P((u_char *, int));
+
+void pcstart();
+int pcparam();
+char partab[];
+
+extern pcopen(dev_t, int, int, struct proc *);
+
+#define KBD_DELAY \
+ DELAY(10);
+
+static inline int
+kbd_wait_output()
+{
+ u_int i;
+
+ for (i = 100000; i; i--)
+ if ((inb(KBSTATP) & KBS_IBF) == 0) {
+ KBD_DELAY;
+ return 1;
+ }
+ return 0;
+}
+
+static inline int
+kbd_wait_input()
+{
+ u_int i;
+
+ for (i = 100000; i; i--)
+ if ((inb(KBSTATP) & KBS_DIB) != 0) {
+ KBD_DELAY;
+ return 1;
+ }
+ return 0;
+}
+
+static inline void
+kbd_flush_input()
+{
+ u_char c;
+
+ while (c = inb(KBSTATP) & 0x03)
+ if ((c & KBS_DIB) == KBS_DIB) {
+ /* XXX - delay is needed to prevent some keyboards from
+ wedging when the system boots */
+ delay(6);
+ (void) inb(KBDATAP);
+ }
+}
+
+
+#if 1
+/*
+ * Get the current command byte.
+ */
+static u_char
+kbc_get8042cmd()
+{
+
+ if (!kbd_wait_output())
+ return -1;
+ outb(KBCMDP, K_RDCMDBYTE);
+ if (!kbd_wait_input())
+ return -1;
+ return inb(KBDATAP);
+}
+#endif
+
+/*
+ * Pass command byte to keyboard controller (8042).
+ */
+static int
+kbc_put8042cmd(val)
+ u_char val;
+{
+
+ if (!kbd_wait_output())
+ return 0;
+ outb(KBCMDP, K_LDCMDBYTE);
+ if (!kbd_wait_output())
+ return 0;
+ outb(KBOUTP, val);
+ return 1;
+}
+
+/*
+ * Pass command to keyboard itself
+ */
+int
+kbd_cmd(val, polling)
+ u_char val;
+ u_char polling;
+{
+ u_int retries = 3;
+ register u_int i;
+
+ if(!polling) {
+ i = spltty();
+ if(kb_oq_get == kb_oq_put) {
+ outb(KBOUTP, val);
+ }
+ kb_oq[kb_oq_put] = val;
+ kb_oq_put = (kb_oq_put + 1) & 7;
+ splx(i);
+ return(1);
+ }
+ else do {
+ if (!kbd_wait_output())
+ return 0;
+ outb(KBOUTP, val);
+ for (i = 100000; i; i--) {
+ if (inb(KBSTATP) & KBS_DIB) {
+ register u_char c;
+
+ KBD_DELAY;
+ c = inb(KBDATAP);
+ if (c == KBR_ACK || c == KBR_ECHO) {
+ return 1;
+ }
+ if (c == KBR_RESEND) {
+ break;
+ }
+#ifdef DIAGNOSTIC
+ printf("kbd_cmd: input char %x lost\n", c);
+#endif
+ }
+ }
+ } while (--retries);
+ return 0;
+}
+
+void
+set_cursor_shape()
+{
+ register int iobase = addr_6845;
+
+ outb(iobase, 10);
+ outb(iobase+1, cursor_shape >> 8);
+ outb(iobase, 11);
+ outb(iobase+1, cursor_shape);
+ old_cursor_shape = cursor_shape;
+}
+
+void
+get_cursor_shape()
+{
+ register int iobase = addr_6845;
+
+ outb(iobase, 10);
+ cursor_shape = inb(iobase+1) << 8;
+ outb(iobase, 11);
+ cursor_shape |= inb(iobase+1);
+
+ /*
+ * real 6845's, as found on, MDA, Hercules or CGA cards, do
+ * not support reading the cursor shape registers. the 6845
+ * tri-states it's data bus. This is _normally_ read by the
+ * cpu as either 0x00 or 0xff.. in which case we just use
+ * a line cursor.
+ */
+ if (cursor_shape == 0x0000 || cursor_shape == 0xffff)
+ cursor_shape = 0x0b10;
+ else
+ cursor_shape &= 0x1f1f;
+}
+
+void
+do_async_update(poll)
+ u_char poll;
+{
+ int pos;
+ static int old_pos = -1;
+
+ async = 0;
+
+ if (lock_state != old_lock_state) {
+ old_lock_state = lock_state;
+ if (!kbd_cmd(KBC_MODEIND, poll) ||
+ !kbd_cmd(lock_state, poll)) {
+ printf("pc: timeout updating leds\n");
+ (void) kbd_cmd(KBC_ENABLE, poll);
+ }
+ }
+ if (typematic_rate != old_typematic_rate) {
+ old_typematic_rate = typematic_rate;
+ if (!kbd_cmd(KBC_TYPEMATIC, poll) ||
+ !kbd_cmd(typematic_rate, poll)) {
+ printf("pc: timeout updating typematic rate\n");
+ (void) kbd_cmd(KBC_ENABLE, poll);
+ }
+ }
+
+ if (pc_xmode > 0)
+ return;
+
+ pos = crtat - Crtat;
+ if (pos != old_pos) {
+ register int iobase = addr_6845;
+ outb(iobase, 14);
+ outb(iobase+1, pos >> 8);
+ outb(iobase, 15);
+ outb(iobase+1, pos);
+ old_pos = pos;
+ }
+ if (cursor_shape != old_cursor_shape)
+ set_cursor_shape();
+}
+
+void
+async_update()
+{
+
+ if (kernel || polling) {
+ if (async)
+ untimeout(do_async_update, NULL);
+ do_async_update(1);
+ } else {
+ if (async)
+ return;
+ async = 1;
+ timeout(do_async_update, NULL, 1);
+ }
+}
+
+/*
+ * these are both bad jokes
+ */
+int
+pcprobe(parent, cfdata, aux)
+ struct device *parent;
+ void *cfdata, *aux;
+{
+ struct confargs *ca = aux;
+ u_int i;
+
+ /* Make shure we're looking for this type of device */
+ if(!BUS_MATCHNAME(ca, "pc"))
+ return(0);
+
+ /* Enable interrupts and keyboard, etc. */
+ if (!kbc_put8042cmd(CMDBYTE)) {
+ printf("pcprobe: command error\n");
+ return 0;
+ }
+
+#if 1
+ /* Flush any garbage. */
+ kbd_flush_input();
+ /* Reset the keyboard. */
+ if (!kbd_cmd(KBC_RESET, 1)) {
+ printf("pcprobe: reset error %d\n", 1);
+ goto lose;
+ }
+ for (i = 600000; i; i--)
+ if ((inb(KBSTATP) & KBS_DIB) != 0) {
+ KBD_DELAY;
+ break;
+ }
+ if (i == 0 || inb(KBDATAP) != KBR_RSTDONE) {
+ printf("pcprobe: reset error %d\n", 2);
+ goto lose;
+ }
+ /*
+ * Some keyboards seem to leave a second ack byte after the reset.
+ * This is kind of stupid, but we account for them anyway by just
+ * flushing the buffer.
+ */
+ kbd_flush_input();
+ /* Just to be sure. */
+ if (!kbd_cmd(KBC_ENABLE, 1)) {
+ printf("pcprobe: reset error %d\n", 3);
+ goto lose;
+ }
+
+ /*
+ * Some keyboard/8042 combinations do not seem to work if the keyboard
+ * is set to table 1; in fact, it would appear that some keyboards just
+ * ignore the command altogether. So by default, we use the AT scan
+ * codes and have the 8042 translate them. Unfortunately, this is
+ * known to not work on some PS/2 machines. We try desparately to deal
+ * with this by checking the (lack of a) translate bit in the 8042 and
+ * attempting to set the keyboard to XT mode. If this all fails, well,
+ * tough luck.
+ *
+ * XXX It would perhaps be a better choice to just use AT scan codes
+ * and not bother with this.
+ */
+ if (kbc_get8042cmd() & KC8_TRANS) {
+ /* The 8042 is translating for us; use AT codes. */
+ if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(2, 1)) {
+ printf("pcprobe: reset error %d\n", 4);
+ goto lose;
+ }
+ } else {
+ /* Stupid 8042; set keyboard to XT codes. */
+ if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(1, 1)) {
+ printf("pcprobe: reset error %d\n", 5);
+ goto lose;
+ }
+ }
+
+lose:
+ /*
+ * Technically, we should probably fail the probe. But we'll be nice
+ * and allow keyboard-less machines to boot with the console.
+ */
+#endif
+
+ return 1;
+}
+
+void
+pcattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct confargs *ca = aux;
+ struct pc_softc *sc = (void *)self;
+
+ printf(": %s\n", vs.color ? "color" : "mono");
+ do_async_update(1);
+
+ BUS_INTR_ESTABLISH(ca, pcintr, (void *)(long)sc);
+}
+
+int
+pcopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ struct pc_softc *sc;
+ int unit = PCUNIT(dev);
+ struct tty *tp;
+
+ if (unit >= pc_cd.cd_ndevs)
+ return ENXIO;
+ sc = pc_cd.cd_devs[unit];
+ if (sc == 0)
+ return ENXIO;
+
+ if (!sc->sc_tty) {
+ tp = sc->sc_tty = ttymalloc();
+ }
+ else {
+ tp = sc->sc_tty;
+ }
+
+ tp->t_oproc = pcstart;
+ tp->t_param = pcparam;
+ 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;
+ pcparam(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;
+
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
+}
+
+int
+pcclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
+ struct tty *tp = sc->sc_tty;
+
+ (*linesw[tp->t_line].l_close)(tp, flag);
+ ttyclose(tp);
+#ifdef notyet /* XXX */
+ ttyfree(tp);
+#endif
+ return(0);
+}
+
+int
+pcread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
+ struct tty *tp = sc->sc_tty;
+
+ return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
+}
+
+int
+pcwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
+ struct tty *tp = sc->sc_tty;
+
+ return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
+}
+
+struct tty *
+pctty(dev)
+ dev_t dev;
+{
+ struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
+ struct tty *tp = sc->sc_tty;
+
+ return (tp);
+}
+
+/*
+ * Got a console receive interrupt -
+ * the console processor wants to give us a character.
+ * Catch the character, and see who it goes to.
+ */
+int
+pcintr(arg)
+ void *arg;
+{
+ struct pc_softc *sc = arg;
+ register struct tty *tp = sc->sc_tty;
+ u_char *cp;
+
+ if ((inb(KBSTATP) & KBS_DIB) == 0)
+ return 0;
+ if (polling)
+ return 1;
+ do {
+ cp = sget();
+ if (!tp || (tp->t_state & TS_ISOPEN) == 0)
+ return 1;
+ if (cp)
+ do
+ (*linesw[tp->t_line].l_rint)(*cp++, tp);
+ while (*cp);
+ } while (inb(KBSTATP) & KBS_DIB);
+ return 1;
+}
+
+int
+pcioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
+ struct tty *tp = sc->sc_tty;
+ 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 CONSOLE_X_MODE_ON:
+ pc_xmode_on();
+ return 0;
+ case CONSOLE_X_MODE_OFF:
+ pc_xmode_off();
+ return 0;
+ case CONSOLE_X_BELL:
+ /*
+ * If set, data is a pointer to a length 2 array of
+ * integers. data[0] is the pitch in Hz and data[1]
+ * is the duration in msec.
+ */
+ if (data)
+ sysbeep(((int*)data)[0],
+ (((int*)data)[1] * hz) / 1000);
+ else
+ sysbeep(BEEP_FREQ, BEEP_TIME);
+ return 0;
+ case CONSOLE_SET_TYPEMATIC_RATE: {
+ u_char rate;
+
+ if (!data)
+ return EINVAL;
+ rate = *((u_char *)data);
+ /*
+ * Check that it isn't too big (which would cause it to be
+ * confused with a command).
+ */
+ if (rate & 0x80)
+ return EINVAL;
+ typematic_rate = rate;
+ async_update();
+ return 0;
+ }
+ case CONSOLE_SET_KEYMAP: {
+ keymap_t *map = (keymap_t *) data;
+ int i;
+
+ if (!data)
+ return EINVAL;
+ for (i = 0; i < KB_NUM_KEYS; i++)
+ if (map[i].unshift[KB_CODE_SIZE-1] ||
+ map[i].shift[KB_CODE_SIZE-1] ||
+ map[i].ctl[KB_CODE_SIZE-1] ||
+ map[i].altgr[KB_CODE_SIZE-1] ||
+ map[i].shift_altgr[KB_CODE_SIZE-1])
+ return EINVAL;
+
+ bcopy(data,scan_codes,sizeof(keymap_t[KB_NUM_KEYS]));
+ return 0;
+ }
+ case CONSOLE_GET_KEYMAP:
+ if (!data)
+ return EINVAL;
+ bcopy(scan_codes,data,sizeof(keymap_t[KB_NUM_KEYS]));
+ return 0;
+
+ default:
+ return ENOTTY;
+ }
+
+#ifdef DIAGNOSTIC
+ panic("pcioctl: impossible");
+#endif
+}
+
+void
+pcstart(tp)
+ struct tty *tp;
+{
+ struct clist *cl;
+ int s, len, n;
+ u_char buf[PCBURST];
+
+ s = spltty();
+ if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
+ goto out;
+ tp->t_state |= TS_BUSY;
+ splx(s);
+ /*
+ * We need to do this outside spl since it could be fairly
+ * expensive and we don't want our serial ports to overflow.
+ */
+ cl = &tp->t_outq;
+ len = q_to_b(cl, buf, PCBURST);
+ sput(buf, len);
+ 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);
+ }
+out:
+ splx(s);
+}
+
+void
+pcstop(tp, flag)
+ struct tty *tp;
+ int flag;
+{
+
+}
+
+void
+pccnprobe(cp)
+ struct consdev *cp;
+{
+ int maj;
+
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == pcopen)
+ break;
+
+ /* initialize required fields */
+ cp->cn_dev = makedev(maj, 0);
+ cp->cn_pri = CN_INTERNAL;
+}
+
+/* ARGSUSED */
+void
+pccninit(cp)
+ struct consdev *cp;
+{
+
+ /*
+ * For now, don't screw with it.
+ */
+ /* crtat = 0; */
+}
+
+/* ARGSUSED */
+void
+pccnputc(dev, c)
+ dev_t dev;
+ char c;
+{
+ u_char oldkernel = kernel;
+
+ kernel = 1;
+ if (c == '\n')
+ sput("\r\n", 2);
+ else
+ sput(&c, 1);
+ kernel = oldkernel;
+}
+
+/* ARGSUSED */
+pccngetc(dev)
+ dev_t dev;
+{
+ register char *cp;
+
+ if (pc_xmode > 0)
+ return 0;
+
+ do {
+ /* wait for byte */
+ while ((inb(KBSTATP) & KBS_DIB) == 0);
+ /* see if it's worthwhile */
+ cp = sget();
+ } while (!cp);
+ if (*cp == '\r')
+ return '\n';
+ return *cp;
+}
+
+void
+pccnpollc(dev, on)
+ dev_t dev;
+ int on;
+{
+
+ polling = on;
+ if (!on) {
+ int unit;
+ struct pc_softc *sc;
+ int s;
+
+ /*
+ * If disabling polling on a device that's been configured,
+ * make sure there are no bytes left in the FIFO, holding up
+ * the interrupt line. Otherwise we won't get any further
+ * interrupts.
+ */
+ unit = PCUNIT(dev);
+ if (pc_cd.cd_ndevs > unit) {
+ sc = pc_cd.cd_devs[unit];
+ if (sc != 0) {
+ s = spltty();
+ pcintr(sc);
+ splx(s);
+ }
+ }
+ }
+}
+
+/*
+ * Set line parameters.
+ */
+int
+pcparam(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;
+}
+
+#define wrtchar(c, at) do {\
+ char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \
+} while (0)
+
+/* translate ANSI color codes to standard pc ones */
+static char fgansitopc[] = {
+ FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
+ FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
+};
+
+static char bgansitopc[] = {
+ BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
+ BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
+};
+
+static u_char iso2ibm437[] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xff, 0xad, 0x9b, 0x9c, 0, 0x9d, 0, 0x40,
+ 0x6f, 0x63, 0x61, 0xae, 0, 0, 0, 0,
+ 0xf8, 0xf1, 0xfd, 0x33, 0, 0xe6, 0, 0xfa,
+ 0, 0x31, 0x6f, 0xaf, 0xac, 0xab, 0, 0xa8,
+ 0x41, 0x41, 0x41, 0x41, 0x8e, 0x8f, 0x92, 0x80,
+ 0x45, 0x90, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
+ 0x81, 0xa5, 0x4f, 0x4f, 0x4f, 0x4f, 0x99, 0x4f,
+ 0x4f, 0x55, 0x55, 0x55, 0x9a, 0x59, 0, 0xe1,
+ 0x85, 0xa0, 0x83, 0x61, 0x84, 0x86, 0x91, 0x87,
+ 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b,
+ 0, 0xa4, 0x95, 0xa2, 0x93, 0x6f, 0x94, 0x6f,
+ 0x6f, 0x97, 0xa3, 0x96, 0x81, 0x98, 0, 0
+};
+
+/*
+ * `pc3' termcap emulation.
+ */
+void
+sput(cp, n)
+ u_char *cp;
+ int n;
+{
+ u_char c, scroll = 0;
+
+ if (pc_xmode > 0)
+ return;
+
+ if (crtat == 0) {
+ u_short volatile *cp;
+ u_short was;
+ unsigned cursorat;
+
+ cp = (u_short *)CGA_BUF;
+ was = *cp;
+ *cp = (u_short) 0xA55A;
+ if (*cp != 0xA55A) {
+ cp = (u_short *)MONO_BUF;
+ addr_6845 = MONO_BASE;
+ vs.color = 0;
+ } else {
+ *cp = was;
+ addr_6845 = CGA_BASE;
+ vs.color = 1;
+ }
+
+ /* Extract cursor location */
+ outb(addr_6845, 14);
+ cursorat = inb(addr_6845+1) << 8;
+ outb(addr_6845, 15);
+ cursorat |= inb(addr_6845+1);
+
+#ifdef FAT_CURSOR
+ cursor_shape = 0x0012;
+#else
+ get_cursor_shape();
+#endif
+
+ Crtat = (u_short *)cp;
+ crtat = (u_short *)(cp + cursorat);
+
+ vs.ncol = COL;
+ vs.nrow = ROW;
+ vs.nchr = COL * ROW;
+ vs.at = FG_LIGHTGREY | BG_BLACK;
+
+ if (vs.color == 0)
+ vs.so_at = FG_BLACK | BG_LIGHTGREY;
+ else
+ vs.so_at = FG_YELLOW | BG_BLACK;
+
+ fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
+ }
+
+ while (n--) {
+ if (!(c = *cp++))
+ continue;
+
+ switch (c) {
+ case 0x1B:
+ if (vs.state >= VSS_ESCAPE) {
+ wrtchar(c, vs.so_at);
+ vs.state = 0;
+ goto maybe_scroll;
+ } else
+ vs.state = VSS_ESCAPE;
+ break;
+
+ case '\t': {
+ int inccol = 8 - (vs.col & 7);
+ crtat += inccol;
+ vs.col += inccol;
+ }
+ maybe_scroll:
+ if (vs.col >= COL) {
+ vs.col -= COL;
+ scroll = 1;
+ }
+ break;
+
+ case '\010':
+ if (crtat <= Crtat)
+ break;
+ --crtat;
+ if (--vs.col < 0)
+ vs.col += COL; /* non-destructive backspace */
+ break;
+
+ case '\r':
+ crtat -= vs.col;
+ vs.col = 0;
+ break;
+
+ case '\n':
+ crtat += vs.ncol;
+ scroll = 1;
+ break;
+
+ default:
+ bypass:
+ switch (vs.state) {
+ case 0:
+ if (c == '\a')
+ sysbeep(BEEP_FREQ, BEEP_TIME);
+ else {
+ /*
+ * If we're outputting multiple printed
+ * characters, just blast them to the
+ * screen until we reach the end of the
+ * buffer or a control character. This
+ * saves time by short-circuiting the
+ * switch.
+ * If we reach the end of the line, we
+ * break to do a scroll check.
+ */
+ for (;;) {
+ if (c & 0x80)
+ c = iso2ibm437[c&0x7f];
+
+ if (vs.so)
+ wrtchar(c, vs.so_at);
+ else
+ wrtchar(c, vs.at);
+ if (vs.col >= vs.ncol) {
+ vs.col = 0;
+ scroll = 1;
+ break;
+ }
+ if (!n || (c = *cp) < ' ')
+ break;
+ n--, cp++;
+ }
+ }
+ break;
+ case VSS_ESCAPE:
+ if (c == '[') { /* Start ESC [ sequence */
+ vs.cx = vs.cy = 0;
+ vs.state = VSS_EBRACE;
+ } else if (c == 'c') { /* Clear screen & home */
+ fillw((vs.at << 8) | ' ', Crtat,
+ vs.nchr);
+ crtat = Crtat;
+ vs.col = 0;
+ vs.state = 0;
+ } else { /* Invalid, clear state */
+ wrtchar(c, vs.so_at);
+ vs.state = 0;
+ goto maybe_scroll;
+ }
+ break;
+ default: /* VSS_EBRACE or VSS_EPARAM */
+ switch (c) {
+ int pos;
+ case 'm':
+ if (!vs.cx)
+ vs.so = 0;
+ else
+ vs.so = 1;
+ vs.state = 0;
+ break;
+ case 'A': { /* back cx rows */
+ int cx = vs.cx;
+ if (cx <= 0)
+ cx = 1;
+ else
+ cx %= vs.nrow;
+ pos = crtat - Crtat;
+ pos -= vs.ncol * cx;
+ if (pos < 0)
+ pos += vs.nchr;
+ crtat = Crtat + pos;
+ vs.state = 0;
+ break;
+ }
+ case 'B': { /* down cx rows */
+ int cx = vs.cx;
+ if (cx <= 0)
+ cx = 1;
+ else
+ cx %= vs.nrow;
+ pos = crtat - Crtat;
+ pos += vs.ncol * cx;
+ if (pos >= vs.nchr)
+ pos -= vs.nchr;
+ crtat = Crtat + pos;
+ vs.state = 0;
+ break;
+ }
+ case 'C': { /* right cursor */
+ int cx = vs.cx,
+ col = vs.col;
+ if (cx <= 0)
+ cx = 1;
+ else
+ cx %= vs.ncol;
+ pos = crtat - Crtat;
+ pos += cx;
+ col += cx;
+ if (col >= vs.ncol) {
+ pos -= vs.ncol;
+ col -= vs.ncol;
+ }
+ vs.col = col;
+ crtat = Crtat + pos;
+ vs.state = 0;
+ break;
+ }
+ case 'D': { /* left cursor */
+ int cx = vs.cx,
+ col = vs.col;
+ if (cx <= 0)
+ cx = 1;
+ else
+ cx %= vs.ncol;
+ pos = crtat - Crtat;
+ pos -= cx;
+ col -= cx;
+ if (col < 0) {
+ pos += vs.ncol;
+ col += vs.ncol;
+ }
+ vs.col = col;
+ crtat = Crtat + pos;
+ vs.state = 0;
+ break;
+ }
+ case 'J': /* Clear ... */
+ switch (vs.cx) {
+ case 0:
+ /* ... to end of display */
+ fillw((vs.at << 8) | ' ', crtat,
+ Crtat + vs.nchr - crtat);
+ break;
+ case 1:
+ /* ... to next location */
+ fillw((vs.at << 8) | ' ', Crtat,
+ crtat - Crtat + 1);
+ break;
+ case 2:
+ /* ... whole display */
+ fillw((vs.at << 8) | ' ', Crtat,
+ vs.nchr);
+ break;
+ }
+ vs.state = 0;
+ break;
+ case 'K': /* Clear line ... */
+ switch (vs.cx) {
+ case 0:
+ /* ... current to EOL */
+ fillw((vs.at << 8) | ' ', crtat,
+ vs.ncol - vs.col);
+ break;
+ case 1:
+ /* ... beginning to next */
+ fillw((vs.at << 8) | ' ',
+ crtat - vs.col,
+ vs.col + 1);
+ break;
+ case 2:
+ /* ... entire line */
+ fillw((vs.at << 8) | ' ',
+ crtat - vs.col, vs.ncol);
+ break;
+ }
+ vs.state = 0;
+ break;
+ case 'f': /* in system V consoles */
+ case 'H': { /* Cursor move */
+ int cx = vs.cx,
+ cy = vs.cy;
+ if (!cx || !cy) {
+ crtat = Crtat;
+ vs.col = 0;
+ } else {
+ if (cx > vs.nrow)
+ cx = vs.nrow;
+ if (cy > vs.ncol)
+ cy = vs.ncol;
+ crtat = Crtat +
+ (cx - 1) * vs.ncol + cy - 1;
+ vs.col = cy - 1;
+ }
+ vs.state = 0;
+ break;
+ }
+ case 'M': { /* delete cx rows */
+ u_short *crtAt = crtat - vs.col;
+ int cx = vs.cx,
+ row = (crtAt - Crtat) / vs.ncol,
+ nrow = vs.nrow - row;
+ if (cx <= 0)
+ cx = 1;
+ else if (cx > nrow)
+ cx = nrow;
+ if (cx < nrow)
+ bcopy(crtAt + vs.ncol * cx,
+ crtAt, vs.ncol * (nrow -
+ cx) * CHR);
+ fillw((vs.at << 8) | ' ',
+ crtAt + vs.ncol * (nrow - cx),
+ vs.ncol * cx);
+ vs.state = 0;
+ break;
+ }
+ case 'S': { /* scroll up cx lines */
+ int cx = vs.cx;
+ if (cx <= 0)
+ cx = 1;
+ else if (cx > vs.nrow)
+ cx = vs.nrow;
+ if (cx < vs.nrow)
+ bcopy(Crtat + vs.ncol * cx,
+ Crtat, vs.ncol * (vs.nrow -
+ cx) * CHR);
+ fillw((vs.at << 8) | ' ',
+ Crtat + vs.ncol * (vs.nrow - cx),
+ vs.ncol * cx);
+ /* crtat -= vs.ncol * cx; /* XXX */
+ vs.state = 0;
+ break;
+ }
+ case 'L': { /* insert cx rows */
+ u_short *crtAt = crtat - vs.col;
+ int cx = vs.cx,
+ row = (crtAt - Crtat) / vs.ncol,
+ nrow = vs.nrow - row;
+ if (cx <= 0)
+ cx = 1;
+ else if (cx > nrow)
+ cx = nrow;
+ if (cx < nrow)
+ bcopy(crtAt,
+ crtAt + vs.ncol * cx,
+ vs.ncol * (nrow - cx) *
+ CHR);
+ fillw((vs.at << 8) | ' ', crtAt,
+ vs.ncol * cx);
+ vs.state = 0;
+ break;
+ }
+ case 'T': { /* scroll down cx lines */
+ int cx = vs.cx;
+ if (cx <= 0)
+ cx = 1;
+ else if (cx > vs.nrow)
+ cx = vs.nrow;
+ if (cx < vs.nrow)
+ bcopy(Crtat,
+ Crtat + vs.ncol * cx,
+ vs.ncol * (vs.nrow - cx) *
+ CHR);
+ fillw((vs.at << 8) | ' ', Crtat,
+ vs.ncol * cx);
+ /* crtat += vs.ncol * cx; /* XXX */
+ vs.state = 0;
+ break;
+ }
+ case ';': /* Switch params in cursor def */
+ vs.state = VSS_EPARAM;
+ break;
+ case 'r':
+ vs.so_at = (vs.cx & FG_MASK) |
+ ((vs.cy << 4) & BG_MASK);
+ vs.state = 0;
+ break;
+ case 'x': /* set attributes */
+ switch (vs.cx) {
+ case 0:
+ vs.at = FG_LIGHTGREY | BG_BLACK;
+ break;
+ case 1:
+ /* ansi background */
+ if (!vs.color)
+ break;
+ vs.at &= FG_MASK;
+ vs.at |= bgansitopc[vs.cy & 7];
+ break;
+ case 2:
+ /* ansi foreground */
+ if (!vs.color)
+ break;
+ vs.at &= BG_MASK;
+ vs.at |= fgansitopc[vs.cy & 7];
+ break;
+ case 3:
+ /* pc text attribute */
+ if (vs.state >= VSS_EPARAM)
+ vs.at = vs.cy;
+ break;
+ }
+ vs.state = 0;
+ break;
+
+ default: /* Only numbers valid here */
+ if ((c >= '0') && (c <= '9')) {
+ if (vs.state >= VSS_EPARAM) {
+ vs.cy *= 10;
+ vs.cy += c - '0';
+ } else {
+ vs.cx *= 10;
+ vs.cx += c - '0';
+ }
+ } else
+ vs.state = 0;
+ break;
+ }
+ break;
+ }
+ }
+ if (scroll) {
+ scroll = 0;
+ /* scroll check */
+ if (crtat >= Crtat + vs.nchr) {
+ if (!kernel) {
+ int s = spltty();
+ if (lock_state & KB_SCROLL)
+ tsleep((caddr_t)&lock_state,
+ PUSER, "pcputc", 0);
+ splx(s);
+ }
+ bcopy(Crtat + vs.ncol, Crtat,
+ (vs.nchr - vs.ncol) * CHR);
+ fillw((vs.at << 8) | ' ',
+ Crtat + vs.nchr - vs.ncol, vs.ncol);
+ crtat -= vs.ncol;
+ }
+ }
+ }
+ async_update();
+}
+
+static keymap_t scan_codes[KB_NUM_KEYS] = {
+/* type unshift shift control altgr shift_altgr scancode */
+ KB_NONE, "", "", "", "", "", /* 0 unused */
+ KB_ASCII, "\033", "\033", "\033", "", "", /* 1 ESCape */
+ KB_ASCII, "1", "!", "!", "", "", /* 2 1 */
+ KB_ASCII, "2", "@", "\000", "", "", /* 3 2 */
+ KB_ASCII, "3", "#", "#", "", "", /* 4 3 */
+ KB_ASCII, "4", "$", "$", "", "", /* 5 4 */
+ KB_ASCII, "5", "%", "%", "", "", /* 6 5 */
+ KB_ASCII, "6", "^", "\036", "", "", /* 7 6 */
+ KB_ASCII, "7", "&", "&", "", "", /* 8 7 */
+ KB_ASCII, "8", "*", "\010", "", "", /* 9 8 */
+ KB_ASCII, "9", "(", "(", "", "", /* 10 9 */
+ KB_ASCII, "0", ")", ")", "", "", /* 11 0 */
+ KB_ASCII, "-", "_", "\037", "", "", /* 12 - */
+ KB_ASCII, "=", "+", "+", "", "", /* 13 = */
+ KB_ASCII, "\177", "\177", "\010", "", "", /* 14 backspace */
+ KB_ASCII, "\t", "\t", "\t", "", "", /* 15 tab */
+ KB_ASCII, "q", "Q", "\021", "", "", /* 16 q */
+ KB_ASCII, "w", "W", "\027", "", "", /* 17 w */
+ KB_ASCII, "e", "E", "\005", "", "", /* 18 e */
+ KB_ASCII, "r", "R", "\022", "", "", /* 19 r */
+ KB_ASCII, "t", "T", "\024", "", "", /* 20 t */
+ KB_ASCII, "y", "Y", "\031", "", "", /* 21 y */
+ KB_ASCII, "u", "U", "\025", "", "", /* 22 u */
+ KB_ASCII, "i", "I", "\011", "", "", /* 23 i */
+ KB_ASCII, "o", "O", "\017", "", "", /* 24 o */
+ KB_ASCII, "p", "P", "\020", "", "", /* 25 p */
+ KB_ASCII, "[", "{", "\033", "", "", /* 26 [ */
+ KB_ASCII, "]", "}", "\035", "", "", /* 27 ] */
+ KB_ASCII, "\r", "\r", "\n", "", "", /* 28 return */
+ KB_CTL, "", "", "", "", "", /* 29 control */
+ KB_ASCII, "a", "A", "\001", "", "", /* 30 a */
+ KB_ASCII, "s", "S", "\023", "", "", /* 31 s */
+ KB_ASCII, "d", "D", "\004", "", "", /* 32 d */
+ KB_ASCII, "f", "F", "\006", "", "", /* 33 f */
+ KB_ASCII, "g", "G", "\007", "", "", /* 34 g */
+ KB_ASCII, "h", "H", "\010", "", "", /* 35 h */
+ KB_ASCII, "j", "J", "\n", "", "", /* 36 j */
+ KB_ASCII, "k", "K", "\013", "", "", /* 37 k */
+ KB_ASCII, "l", "L", "\014", "", "", /* 38 l */
+ KB_ASCII, ";", ":", ";", "", "", /* 39 ; */
+ KB_ASCII, "'", "\"", "'", "", "", /* 40 ' */
+ KB_ASCII, "`", "~", "`", "", "", /* 41 ` */
+ KB_SHIFT, "", "", "", "", "", /* 42 shift */
+ KB_ASCII, "\\", "|", "\034", "", "", /* 43 \ */
+ KB_ASCII, "z", "Z", "\032", "", "", /* 44 z */
+ KB_ASCII, "x", "X", "\030", "", "", /* 45 x */
+ KB_ASCII, "c", "C", "\003", "", "", /* 46 c */
+ KB_ASCII, "v", "V", "\026", "", "", /* 47 v */
+ KB_ASCII, "b", "B", "\002", "", "", /* 48 b */
+ KB_ASCII, "n", "N", "\016", "", "", /* 49 n */
+ KB_ASCII, "m", "M", "\r", "", "", /* 50 m */
+ KB_ASCII, ",", "<", "<", "", "", /* 51 , */
+ KB_ASCII, ".", ">", ">", "", "", /* 52 . */
+ KB_ASCII, "/", "?", "\037", "", "", /* 53 / */
+ KB_SHIFT, "", "", "", "", "", /* 54 shift */
+ KB_KP, "*", "*", "*", "", "", /* 55 kp * */
+ KB_ALT, "", "", "", "", "", /* 56 alt */
+ KB_ASCII, " ", " ", "\000", "", "", /* 57 space */
+ KB_CAPS, "", "", "", "", "", /* 58 caps */
+ KB_FUNC, "\033[M", "\033[Y", "\033[k", "", "", /* 59 f1 */
+ KB_FUNC, "\033[N", "\033[Z", "\033[l", "", "", /* 60 f2 */
+ KB_FUNC, "\033[O", "\033[a", "\033[m", "", "", /* 61 f3 */
+ KB_FUNC, "\033[P", "\033[b", "\033[n", "", "", /* 62 f4 */
+ KB_FUNC, "\033[Q", "\033[c", "\033[o", "", "", /* 63 f5 */
+ KB_FUNC, "\033[R", "\033[d", "\033[p", "", "", /* 64 f6 */
+ KB_FUNC, "\033[S", "\033[e", "\033[q", "", "", /* 65 f7 */
+ KB_FUNC, "\033[T", "\033[f", "\033[r", "", "", /* 66 f8 */
+ KB_FUNC, "\033[U", "\033[g", "\033[s", "", "", /* 67 f9 */
+ KB_FUNC, "\033[V", "\033[h", "\033[t", "", "", /* 68 f10 */
+ KB_NUM, "", "", "", "", "", /* 69 num lock */
+ KB_SCROLL, "", "", "", "", "", /* 70 scroll lock */
+ KB_KP, "7", "\033[H", "7", "", "", /* 71 kp 7 */
+ KB_KP, "8", "\033[A", "8", "", "", /* 72 kp 8 */
+ KB_KP, "9", "\033[I", "9", "", "", /* 73 kp 9 */
+ KB_KP, "-", "-", "-", "", "", /* 74 kp - */
+ KB_KP, "4", "\033[D", "4", "", "", /* 75 kp 4 */
+ KB_KP, "5", "\033[E", "5", "", "", /* 76 kp 5 */
+ KB_KP, "6", "\033[C", "6", "", "", /* 77 kp 6 */
+ KB_KP, "+", "+", "+", "", "", /* 78 kp + */
+ KB_KP, "1", "\033[F", "1", "", "", /* 79 kp 1 */
+ KB_KP, "2", "\033[B", "2", "", "", /* 80 kp 2 */
+ KB_KP, "3", "\033[G", "3", "", "", /* 81 kp 3 */
+ KB_KP, "0", "\033[L", "0", "", "", /* 82 kp 0 */
+ KB_KP, ",", "\177", ",", "", "", /* 83 kp , */
+ KB_NONE, "", "", "", "", "", /* 84 0 */
+ KB_NONE, "", "", "", "", "", /* 85 0 */
+ KB_NONE, "", "", "", "", "", /* 86 0 */
+ KB_FUNC, "\033[W", "\033[i", "\033[u", "", "", /* 87 f11 */
+ KB_FUNC, "\033[X", "\033[j", "\033[v", "", "", /* 88 f12 */
+ KB_NONE, "", "", "", "", "", /* 89 0 */
+ KB_NONE, "", "", "", "", "", /* 90 0 */
+ KB_NONE, "", "", "", "", "", /* 91 0 */
+ KB_NONE, "", "", "", "", "", /* 92 0 */
+ KB_NONE, "", "", "", "", "", /* 93 0 */
+ KB_NONE, "", "", "", "", "", /* 94 0 */
+ KB_NONE, "", "", "", "", "", /* 95 0 */
+ KB_NONE, "", "", "", "", "", /* 96 0 */
+ KB_NONE, "", "", "", "", "", /* 97 0 */
+ KB_NONE, "", "", "", "", "", /* 98 0 */
+ KB_NONE, "", "", "", "", "", /* 99 0 */
+ KB_NONE, "", "", "", "", "", /* 100 */
+ KB_NONE, "", "", "", "", "", /* 101 */
+ KB_NONE, "", "", "", "", "", /* 102 */
+ KB_NONE, "", "", "", "", "", /* 103 */
+ KB_NONE, "", "", "", "", "", /* 104 */
+ KB_NONE, "", "", "", "", "", /* 105 */
+ KB_NONE, "", "", "", "", "", /* 106 */
+ KB_NONE, "", "", "", "", "", /* 107 */
+ KB_NONE, "", "", "", "", "", /* 108 */
+ KB_NONE, "", "", "", "", "", /* 109 */
+ KB_NONE, "", "", "", "", "", /* 110 */
+ KB_NONE, "", "", "", "", "", /* 111 */
+ KB_NONE, "", "", "", "", "", /* 112 */
+ KB_NONE, "", "", "", "", "", /* 113 */
+ KB_NONE, "", "", "", "", "", /* 114 */
+ KB_NONE, "", "", "", "", "", /* 115 */
+ KB_NONE, "", "", "", "", "", /* 116 */
+ KB_NONE, "", "", "", "", "", /* 117 */
+ KB_NONE, "", "", "", "", "", /* 118 */
+ KB_NONE, "", "", "", "", "", /* 119 */
+ KB_NONE, "", "", "", "", "", /* 120 */
+ KB_NONE, "", "", "", "", "", /* 121 */
+ KB_NONE, "", "", "", "", "", /* 122 */
+ KB_NONE, "", "", "", "", "", /* 123 */
+ KB_NONE, "", "", "", "", "", /* 124 */
+ KB_NONE, "", "", "", "", "", /* 125 */
+ KB_NONE, "", "", "", "", "", /* 126 */
+ KB_NONE, "", "", "", "", "" /* 127 */
+};
+
+/*
+ * Get characters from the keyboard. If none are present, return NULL.
+ */
+char *
+sget()
+{
+ u_char dt;
+ static u_char extended = 0, shift_state = 0;
+ static u_char capchar[2];
+
+top:
+ KBD_DELAY;
+ dt = inb(KBDATAP);
+
+ switch (dt) {
+ case KBR_ACK: case KBR_ECHO:
+ kb_oq_get = (kb_oq_get + 1) & 7;
+ if(kb_oq_get != kb_oq_put) {
+ outb(KBOUTP, kb_oq[kb_oq_get]);
+ }
+ goto loop;
+ case KBR_RESEND:
+ outb(KBOUTP, kb_oq[kb_oq_get]);
+ goto loop;
+ }
+
+ if (pc_xmode > 0) {
+#if defined(DDB) && defined(XSERVER_DDB)
+ /* F12 enters the debugger while in X mode */
+ if (dt == 88)
+ Debugger();
+#endif
+ capchar[0] = dt;
+ capchar[1] = 0;
+ /*
+ * Check for locking keys.
+ *
+ * XXX Setting the LEDs this way is a bit bogus. What if the
+ * keyboard has been remapped in X?
+ */
+ switch (scan_codes[dt & 0x7f].type) {
+ case KB_NUM:
+ if (dt & 0x80) {
+ shift_state &= ~KB_NUM;
+ break;
+ }
+ if (shift_state & KB_NUM)
+ break;
+ shift_state |= KB_NUM;
+ lock_state ^= KB_NUM;
+ async_update();
+ break;
+ case KB_CAPS:
+ if (dt & 0x80) {
+ shift_state &= ~KB_CAPS;
+ break;
+ }
+ if (shift_state & KB_CAPS)
+ break;
+ shift_state |= KB_CAPS;
+ lock_state ^= KB_CAPS;
+ async_update();
+ break;
+ case KB_SCROLL:
+ if (dt & 0x80) {
+ shift_state &= ~KB_SCROLL;
+ break;
+ }
+ if (shift_state & KB_SCROLL)
+ break;
+ shift_state |= KB_SCROLL;
+ lock_state ^= KB_SCROLL;
+ if ((lock_state & KB_SCROLL) == 0)
+ wakeup((caddr_t)&lock_state);
+ async_update();
+ break;
+ }
+ return capchar;
+ }
+
+ switch (dt) {
+ case KBR_EXTENDED:
+ extended = 1;
+ goto loop;
+ }
+
+#ifdef DEBUG
+ /*
+ * Check for cntl-alt-esc.
+ */
+ if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
+ mdbpanic();
+ dt |= 0x80; /* discard esc (ddb discarded ctl-alt) */
+ }
+#endif
+
+ /*
+ * Check for make/break.
+ */
+ if (dt & 0x80) {
+ /*
+ * break
+ */
+ dt &= 0x7f;
+ switch (scan_codes[dt].type) {
+ case KB_NUM:
+ shift_state &= ~KB_NUM;
+ break;
+ case KB_CAPS:
+ shift_state &= ~KB_CAPS;
+ break;
+ case KB_SCROLL:
+ shift_state &= ~KB_SCROLL;
+ break;
+ case KB_SHIFT:
+ shift_state &= ~KB_SHIFT;
+ break;
+ case KB_ALT:
+ if (extended)
+ shift_state &= ~KB_ALTGR;
+ else
+ shift_state &= ~KB_ALT;
+ break;
+ case KB_CTL:
+ shift_state &= ~KB_CTL;
+ break;
+ }
+ } else {
+ /*
+ * make
+ */
+ switch (scan_codes[dt].type) {
+ /*
+ * locking keys
+ */
+ case KB_NUM:
+ if (shift_state & KB_NUM)
+ break;
+ shift_state |= KB_NUM;
+ lock_state ^= KB_NUM;
+ async_update();
+ break;
+ case KB_CAPS:
+ if (shift_state & KB_CAPS)
+ break;
+ shift_state |= KB_CAPS;
+ lock_state ^= KB_CAPS;
+ async_update();
+ break;
+ case KB_SCROLL:
+ if (shift_state & KB_SCROLL)
+ break;
+ shift_state |= KB_SCROLL;
+ lock_state ^= KB_SCROLL;
+ if ((lock_state & KB_SCROLL) == 0)
+ wakeup((caddr_t)&lock_state);
+ async_update();
+ break;
+ /*
+ * non-locking keys
+ */
+ case KB_SHIFT:
+ shift_state |= KB_SHIFT;
+ break;
+ case KB_ALT:
+ if (extended)
+ shift_state |= KB_ALTGR;
+ else
+ shift_state |= KB_ALT;
+ break;
+ case KB_CTL:
+ shift_state |= KB_CTL;
+ break;
+ case KB_ASCII:
+ /* control has highest priority */
+ if (shift_state & KB_CTL)
+ capchar[0] = scan_codes[dt].ctl[0];
+ else if (shift_state & KB_ALTGR) {
+ if (shift_state & KB_SHIFT)
+ capchar[0] = scan_codes[dt].shift_altgr[0];
+ else
+ capchar[0] = scan_codes[dt].altgr[0];
+ }
+ else {
+ if (shift_state & KB_SHIFT)
+ capchar[0] = scan_codes[dt].shift[0];
+ else
+ capchar[0] = scan_codes[dt].unshift[0];
+ }
+ if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
+ capchar[0] <= 'z') {
+ capchar[0] -= ('a' - 'A');
+ }
+ capchar[0] |= (shift_state & KB_ALT);
+ extended = 0;
+ return capchar;
+ case KB_NONE:
+printf("keycode %d\n",dt);
+ break;
+ case KB_FUNC: {
+ char *more_chars;
+ if (shift_state & KB_SHIFT)
+ more_chars = scan_codes[dt].shift;
+ else if (shift_state & KB_CTL)
+ more_chars = scan_codes[dt].ctl;
+ else
+ more_chars = scan_codes[dt].unshift;
+ extended = 0;
+ return more_chars;
+ }
+ case KB_KP: {
+ char *more_chars;
+ if (shift_state & (KB_SHIFT | KB_CTL) ||
+ (lock_state & KB_NUM) == 0 || extended)
+ more_chars = scan_codes[dt].shift;
+ else
+ more_chars = scan_codes[dt].unshift;
+ extended = 0;
+ return more_chars;
+ }
+ }
+ }
+
+ extended = 0;
+loop:
+ if ((inb(KBSTATP) & KBS_DIB) == 0)
+ return 0;
+ goto top;
+}
+
+int
+pcmmap(dev, offset, nprot)
+ dev_t dev;
+ int offset;
+ int nprot;
+{
+
+ if (offset >= 0xa0000 && offset < 0xc0000)
+ return pica_btop(PICA_P_LOCAL_VIDEO + offset);
+ if (offset >= 0x0000 && offset < 0x10000)
+ return pica_btop(PICA_P_LOCAL_VIDEO_CTRL + offset);
+ if (offset >= 0x40000000 && offset < 0x40800000)
+ return pica_btop(PICA_P_LOCAL_VIDEO + offset - 0x40000000);
+ return -1;
+}
+
+pc_xmode_on()
+{
+ if (pc_xmode)
+ return;
+ pc_xmode = 1;
+
+#ifdef XFREE86_BUG_COMPAT
+ /* If still unchanged, get current shape. */
+ if (cursor_shape == 0xffff)
+ get_cursor_shape();
+#endif
+}
+
+pc_xmode_off()
+{
+ if (pc_xmode == 0)
+ return;
+ pc_xmode = 0;
+
+#ifdef XFREE86_BUG_COMPAT
+ /* XXX It would be hard to justify why the X server doesn't do this. */
+ set_cursor_shape();
+#endif
+ async_update();
+}
+/* $NetBSD: pms.c,v 1.21 1995/04/18 02:25:18 mycroft Exp $ */
+
+#include <machine/mouse.h>
+
+/* status bits */
+#define PMS_OBUF_FULL 0x01
+#define PMS_IBUF_FULL 0x02
+
+/* controller commands */
+#define PMS_INT_ENABLE 0x47 /* enable controller interrupts */
+#define PMS_INT_DISABLE 0x65 /* disable controller interrupts */
+#define PMS_AUX_ENABLE 0xa7 /* enable auxiliary port */
+#define PMS_AUX_DISABLE 0xa8 /* disable auxiliary port */
+#define PMS_MAGIC_1 0xa9 /* XXX */
+
+#define PMS_8042_CMD 0x65
+
+/* 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 1020 /* buffer size */
+
+
+static inline void
+pms_dev_cmd(value)
+ u_char value;
+{
+ kbd_flush_input();
+ outb(KBCMDP, 0xd4);
+ kbd_flush_input();
+ outb(KBDATAP, value);
+}
+
+static inline void
+pms_aux_cmd(value)
+ u_char value;
+{
+ kbd_flush_input();
+ outb(KBCMDP, value);
+}
+
+static inline void
+pms_pit_cmd(value)
+ u_char value;
+{
+ kbd_flush_input();
+ outb(KBCMDP, 0x60);
+ kbd_flush_input();
+ outb(KBDATAP, value);
+}
+
+int
+pmsprobe(parent, probe, aux)
+ struct device *parent;
+ void *probe, *aux;
+{
+ struct confargs *ca = aux;
+ u_char x;
+
+ /* Make shure we're looking for this type of device */
+ if(!BUS_MATCHNAME(ca, "pms"))
+ return(0);
+
+ pms_dev_cmd(KBC_RESET);
+ pms_aux_cmd(PMS_MAGIC_1);
+ delay(10000);
+ x = inb(KBDATAP);
+ pms_pit_cmd(PMS_INT_DISABLE);
+ if (x & 0x04)
+ return 0;
+
+ return 1;
+}
+
+void
+pmsattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pms_softc *sc = (void *)self;
+ struct confargs *ca = aux;
+
+ printf("\n");
+
+ /* Other initialization was done by pmsprobe. */
+ sc->sc_state = 0;
+
+ BUS_INTR_ESTABLISH(ca, pmsintr, (void *)(long)sc);
+}
+
+int
+pmsopen(dev, flag)
+ dev_t dev;
+ int flag;
+{
+ 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->sc_state |= PMS_OPEN;
+ sc->sc_status = 0;
+ sc->sc_x = sc->sc_y = 0;
+
+ /* Enable interrupts. */
+ pms_dev_cmd(PMS_DEV_ENABLE);
+ pms_aux_cmd(PMS_AUX_ENABLE);
+ pms_dev_cmd(PMS_SET_RES);
+ pms_dev_cmd(3); /* 8 counts/mm */
+ pms_dev_cmd(PMS_SET_SCALE21);
+#if 0
+ pms_dev_cmd(PMS_SET_SAMPLE);
+ pms_dev_cmd(100); /* 100 samples/sec */
+ pms_dev_cmd(PMS_SET_STREAM);
+#endif
+ pms_pit_cmd(PMS_INT_ENABLE);
+
+ return 0;
+}
+
+int
+pmsclose(dev, flag)
+ dev_t dev;
+ int flag;
+{
+ struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+
+ /* Disable interrupts. */
+ pms_dev_cmd(PMS_DEV_DISABLE);
+ pms_pit_cmd(PMS_INT_DISABLE);
+ pms_aux_cmd(PMS_AUX_DISABLE);
+
+ sc->sc_state &= ~PMS_OPEN;
+
+ 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;
+ 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, "pmsrea", 0)) {
+ sc->sc_state &= ~PMS_ASLP;
+ 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
+pmsioctl(dev, cmd, addr, flag)
+ dev_t dev;
+ u_long cmd;
+ caddr_t addr;
+ int flag;
+{
+ struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+ struct mouseinfo info;
+ int s;
+ int error;
+
+ switch (cmd) {
+ case MOUSEIOCREAD:
+ s = spltty();
+
+ info.status = sc->sc_status;
+ if (sc->sc_x || sc->sc_y)
+ info.status |= MOVEMENT;
+
+ if (sc->sc_x > 127)
+ info.xmotion = 127;
+ else if (sc->sc_x < -127)
+ /* Bounding at -127 avoids a bug in XFree86. */
+ info.xmotion = -127;
+ else
+ info.xmotion = sc->sc_x;
+
+ if (sc->sc_y > 127)
+ info.ymotion = 127;
+ else if (sc->sc_y < -127)
+ info.ymotion = -127;
+ else
+ info.ymotion = sc->sc_y;
+
+ /* Reset historical information. */
+ sc->sc_x = sc->sc_y = 0;
+ sc->sc_status &= ~BUTCHNGMASK;
+ ndflush(&sc->sc_q, sc->sc_q.c_cc);
+
+ splx(s);
+ error = copyout(&info, addr, sizeof(struct mouseinfo));
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+/* Masks for the first byte of a packet */
+#define PS2LBUTMASK 0x01
+#define PS2RBUTMASK 0x02
+#define PS2MBUTMASK 0x04
+
+int
+pmsintr(arg)
+ void *arg;
+{
+ struct pms_softc *sc = arg;
+ static int state = 0;
+ static u_char buttons;
+ u_char changed;
+ u_char mbutt;
+ static char dx, dy;
+ u_char buffer[5];
+
+ if ((sc->sc_state & PMS_OPEN) == 0) {
+ /* Interrupts are not expected. Discard the byte. */
+ kbd_flush_input();
+ return 0;
+ }
+
+ switch (state) {
+
+ case 0:
+ buttons = inb(KBDATAP);
+ if ((buttons & 0xc0) == 0)
+ ++state;
+ break;
+
+ case 1:
+ dx = inb(KBDATAP);
+ /* Bounding at -127 avoids a bug in XFree86. */
+ dx = (dx == -128) ? -127 : dx;
+ ++state;
+ break;
+
+ case 2:
+ dy = inb(KBDATAP);
+ dy = (dy == -128) ? -127 : dy;
+ state = 0;
+
+ mbutt = buttons;
+ buttons = ((buttons & PS2LBUTMASK) << 2) |
+ ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1);
+ changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3;
+ sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed;
+
+ if (dx || dy || changed) {
+ /* Update accumulated movements. */
+ sc->sc_x += dx;
+ sc->sc_y += dy;
+
+ /* Add this event to the queue. */
+ buffer[0] = 0x80 | (mbutt & BUTSTATMASK);
+ if(dx < 0)
+ buffer[0] |= 0x10;
+ buffer[1] = dx & 0x7f;
+ if(dy < 0)
+ buffer[0] |= 0x20;
+ buffer[2] = dy & 0x7f;
+ buffer[3] = buffer[4] = 0;
+ (void) b_to_q(buffer, sizeof buffer, &sc->sc_q);
+
+ if (sc->sc_state & PMS_ASLP) {
+ sc->sc_state &= ~PMS_ASLP;
+ wakeup((caddr_t)sc);
+ }
+ selwakeup(&sc->sc_rsel);
+ }
+
+ break;
+ }
+
+ return -1;
+}
+
+int
+pmsselect(dev, rw, p)
+ dev_t dev;
+ int rw;
+ struct proc *p;
+{
+ struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)];
+ int s;
+ int ret;
+
+ if (rw == FWRITE)
+ return 0;
+
+ s = spltty();
+ if (!sc->sc_q.c_cc) {
+ selrecord(p, &sc->sc_rsel);
+ ret = 0;
+ } else
+ ret = 1;
+ splx(s);
+
+ return ret;
+}
diff --git a/sys/arch/arc/dev/scsi.h b/sys/arch/arc/dev/scsi.h
new file mode 100644
index 00000000000..963617add65
--- /dev/null
+++ b/sys/arch/arc/dev/scsi.h
@@ -0,0 +1,559 @@
+/* $OpenBSD: scsi.h,v 1.1 1996/06/24 09:07:19 pefo Exp $ */
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)scsi.h 8.1 (Berkeley) 6/10/93
+ * $Id: scsi.h,v 1.1 1996/06/24 09:07:19 pefo Exp $
+ *
+ * scsi.h --
+ *
+ * Common declarations for SCSI command formaters. This file only covers
+ * definitions pertaining to the SCSI common command set that are
+ * common to all SCSI device types (ie disk, tapes, WORM, printers, etc).
+ * Some of the references from the proceedings of the
+ * 1984 Mini/Micro Northeast conference might help in understanding SCSI.
+ *
+ * from: Header: /sprite/src/kernel/dev/RCS/scsi.h,
+ * v 9.1 90/02/13 23:11:24 jhh Exp SPRITE (Berkeley)
+ * $Id: scsi.h,v 1.1 1996/06/24 09:07:19 pefo Exp $
+ */
+
+#ifndef _SCSI_H
+#define _SCSI_H
+
+/*
+ * "Standard" SCSI Commands.
+ * SCSI commands are divided into 8 groups as follows:
+ * Group0 (0x00 - 0x1f). Basic commands. 6 bytes long
+ * Group1 (0x20 - 0x3f). Extended command. 10 bytes.
+ * Group2 (0x40 - 0x5f). Reserved.
+ * Group2 (0x60 - 0x7f). Reserved.
+ * Group2 (0x80 - 0x9f). Reserved.
+ * Group2 (0xa0 - 0xbf). Reserved.
+ * Group6 (0xc0 - 0xdf). Vendor Unique
+ * Group7 (0xe0 - 0xff). Vendor Unique
+ */
+
+/*
+ * Scsi Group0 commands all are 6 bytes and have a format according to
+ * struct ScsiGroup0Cmd.
+ */
+#define SCSI_TEST_UNIT_READY 0x00
+#define SCSI_REZERO_UNIT 0x01
+#define SCSI_REWIND 0x01
+#define SCSI_REQUEST_SENSE 0x03
+#define SCSI_FORMAT_UNIT 0x04
+#define SCSI_READ_BLOCK_LIMITS 0x05
+#define SCSI_REASSIGN_BLOCKS 0x07
+#define SCSI_READ 0x08
+#define SCSI_WRITE 0x0a
+#define SCSI_SEEK 0x0b
+#define SCSI_TRACK_SELECT 0x0b
+#define SCSI_READ_REVERSE 0x0f
+#define SCSI_WRITE_EOF 0x10
+#define SCSI_SPACE 0x11
+#define SCSI_INQUIRY 0x12
+#define SCSI_VERIFY 0x13
+#define SCSI_READ_BUFFER 0x14
+#define SCSI_MODE_SELECT 0x15
+#define SCSI_RESERVE_UNIT 0x16
+#define SCSI_RELEASE_UNIT 0x17
+#define SCSI_COPY 0x18
+#define SCSI_ERASE_TAPE 0x19
+#define SCSI_MODE_SENSE 0x1a
+#define SCSI_START_STOP 0x1b
+#define SCSI_LOAD_UNLOAD 0x1b
+#define SCSI_RECV_DIAG_RESULTS 0x1c
+#define SCSI_SEND_DIAGNOSTIC 0x1d
+#define SCSI_PREVENT_ALLOW 0x1e
+
+/*
+ * Group1 commands are all 10 bytes and have a format according to
+ * struct ScsiGroup1Cmd.
+ */
+#define SCSI_READ_CAPACITY 0x25
+#define SCSI_READ_EXT 0x28
+#define SCSI_WRITE_EXT 0x2a
+#define SCSI_SEEK_EXT 0x2b
+#define SCSI_WRITE_VERIFY 0x2e
+#define SCSI_VERIFY_EXT 0x2f
+#define SCSI_SEARCH_HIGH 0x30
+#define SCSI_SEARCH_EQUAL 0x31
+#define SCSI_SEARCH_LOW 0x32
+#define SCSI_SET_LIMITS 0x33
+#define SCSI_COMPARE 0x39
+#define SCSI_COPY_VERIFY 0x3a
+
+/*
+ * Control byte flags for Group0 and Group1 commands.
+ *
+ * SCSI_CTRL_LINK - This is used to prevent a bus free phase between commands.
+ * If the command terminates successfully, a SCSI_LINKED_CMD_COMPLETE
+ * message is returned instead of the normal SCSI_COMMAND_COMPLETE message. * The last command in a chain should not have this bit set
+ * (and consequently gets a normal SCSI_COMMAND_COMPLETE message).
+ * SCSI_CTRL_LINK_FLAG - This bit should only set when SCSI_CTRL_LINK is set and
+ * causes a SCSI_LINKED_FLAGED_CMD_COMPLETE to be returned instead of
+ * a SCSI_LINKED_CMD_COMPLETE.
+ */
+#define SCSI_CTRL_LINK 0x01 /* Link commands (no bus free phase) */
+#define SCSI_CTRL_LINK_INTR 0x02 /* Interrupt after linked command */
+
+/*
+ * The standard group0 6-byte SCSI control block. Note that the
+ * fields between highAddr and blockCount inclusive are command dependent.
+ * The definitions Addr and BlockCount cover most of the commands we will
+ * use.
+ */
+typedef struct ScsiGroup0Cmd {
+ u_char command; /* command code, defined below. The
+ * upper three bits of this are zero
+ * to indicate the control block is
+ * only 6 bytes long */
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char unitNumber :3; /* Logical Unit (LUN) to which to
+ * pass the command. The device
+ * has already been selected using
+ * the "targetID" bit. */
+ u_char highAddr :5; /* High bits of address */
+#else
+ u_char highAddr :5; /* High bits of address */
+ u_char unitNumber :3; /* Logical Unit (LUN) to which to
+ * pass the command. The device
+ * has already been selected using
+ * the "targetID" bit. */
+#endif
+ u_char midAddr; /* Middle bits of address */
+ u_char lowAddr; /* Low bits of address */
+ u_char blockCount; /* Blocks to transfer */
+ u_char control; /* See flags for common bits */
+} ScsiGroup0Cmd;
+
+/*
+ * Format of a SCSI_START_STOP command. This is a group 0 command, but
+ * the command contents are different.
+ */
+typedef struct ScsiStartStopCmd {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char command; /* command code, defined below. The
+ * upper three bits of this are zero
+ * to indicate the control block is
+ * only 6 bytes long */
+ u_char unitNumber :3; /* Logical Unit (LUN) to which to
+ * pass the command. The device
+ * has already been selected using
+ * the "targetID" bit. */
+ u_char pad1 :4; /* Reserved */
+ u_char immed :1; /* Immediate status bit */
+ u_char pad2; /* Reserved */
+ u_char pad3; /* Reserved */
+ u_char pad4 :6; /* Reserved */
+ u_char loadEject :1; /* Load or eject medium */
+ u_char start :1; /* Start or stop medium */
+ u_char control; /* See flags for common bits */
+#else
+ u_char command; /* command code, defined below. The
+ * upper three bits of this are zero
+ * to indicate the control block is
+ * only 6 bytes long */
+ u_char immed :1; /* Immediate status bit */
+ u_char pad1 :4; /* Reserved */
+ u_char unitNumber :3; /* Logical Unit (LUN) to which to
+ * pass the command. The device
+ * has already been selected using
+ * the "targetID" bit. */
+ u_char pad2; /* Reserved */
+ u_char pad3; /* Reserved */
+ u_char start :1; /* Start or stop medium */
+ u_char loadEject :1; /* Load or eject medium */
+ u_char pad4 :6; /* Reserved */
+ u_char control; /* See flags for common bits */
+#endif
+} ScsiStartStopCmd;
+
+/*
+ * The standard group1 10-byte SCSI control block. Note that the
+ * fields between highAddr and blockCount inclusive are command dependent.
+ * The definitions Addr and BlockCount cover most of the commands we will
+ * use.
+ */
+typedef struct ScsiGroup1Cmd {
+ u_char command; /* command code, defined below. The
+ * upper three bits of this are zero
+ * to indicate the control block is
+ * only 6 bytes long */
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char unitNumber :3; /* Logical Unit (LUN) to which to
+ * pass the command. The device
+ * has already been selected using
+ * the "targetID" bit. */
+ u_char pad1 :5; /* Reserved */
+#else
+ u_char pad1 :5; /* Reserved */
+ u_char unitNumber :3; /* Logical Unit (LUN) to which to
+ * pass the command. The device
+ * has already been selected using
+ * the "targetID" bit. */
+#endif
+ u_char highAddr; /* High bits of address */
+ u_char midHighAddr; /* Middle high bits of address */
+ u_char midLowAddr; /* Middle low bits of address */
+ u_char lowAddr; /* Low bits of address */
+ u_char pad2; /* Reserved */
+ u_char highBlockCount; /* High bits of blocks to transfer */
+ u_char lowBlockCount; /* Low bits of blocks to transfer */
+ u_char control; /* See flags for common bits */
+} ScsiGroup1Cmd;
+
+/*
+ * SCSI status completion information.
+ * This is returned by the device when a command completes.
+ */
+#define SCSI_STATUS_CHECKCOND 0x02 /* Check Condition (ie., read sense) */
+#define SCSI_STATUS_CONDMET 0x04 /* Condition Met (ie., search worked) */
+#define SCSI_STATUS_BUSY 0x08
+#define SCSI_STATUS_INTERMED 0x10 /* Intermediate status sent */
+#define SCSI_STATUS_EXT 0x80 /* Extended status valid */
+
+/*
+ * Sense information provided after some errors. This is divided into
+ * two kinds, classes 0-6, and class 7. This is 30 bytes big to allow
+ * for the drive specific sense bytes that follow the standard 4 byte header.
+ *
+ * For extended sense, this buffer may be cast into another type. Also
+ * The actual size of the sense data returned is used to detect what
+ * kind of tape drive is out there. Kludgy, but true.
+ */
+typedef struct ScsiClass0Sense {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char valid :1; /* Sense data is valid */
+ u_char error :7; /* 3 bits class and 4 bits code */
+#else
+ u_char error :7; /* 3 bits class and 4 bits code */
+ u_char valid :1; /* Sense data is valid */
+#endif
+ u_char highAddr; /* High byte of block address */
+ u_char midAddr; /* Middle byte of block address */
+ u_char lowAddr; /* Low byte of block address */
+ u_char sense[26]; /* Target specific sense data */
+} ScsiClass0Sense;
+
+/*
+ * Definitions for errors in the sense data. The error field is specified
+ * as a 3 bit class and 4 bit code, but it is easier to treat it as a
+ * single 7 bit field.
+ */
+#define SCSI_NO_SENSE_DATA 0x00
+#define SCSI_NOT_READY 0x04
+#define SCSI_NOT_LOADED 0x09
+#define SCSI_INSUF_CAPACITY 0x0a
+#define SCSI_HARD_DATA_ERROR 0x11
+#define SCSI_WRITE_PROTECT 0x17
+#define SCSI_CORRECTABLE_ERROR 0x18
+#define SCSI_FILE_MARK 0x1c
+#define SCSI_INVALID_COMMAND 0x20
+#define SCSI_UNIT_ATTENTION 0x30
+#define SCSI_END_OF_MEDIA 0x34
+
+/*
+ * The standard "extended" sense data returned by SCSI devices. This
+ * has an error field of 0x70, for a "class 7" error.
+ */
+typedef struct ScsiClass7Sense {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char valid :1; /* Sense data is valid */
+ u_char error7 :7; /* == 0x70 */
+ u_char pad1; /* Also "segment number" for copy */
+ u_char fileMark :1; /* File mark on device */
+ u_char endOfMedia :1; /* End of media reached */
+ u_char badBlockLen :1; /* Block length mis-match (Exabyte) */
+ u_char pad2 :1;
+ u_char key :4; /* Sense keys defined below */
+ u_char info1; /* Information byte 1 */
+ u_char info2; /* Information byte 2 */
+ u_char info3; /* Information byte 3 */
+ u_char info4; /* Information byte 4 */
+ u_char length; /* Number of additional info bytes */
+#else
+ u_char error7 :7; /* == 0x70 */
+ u_char valid :1; /* Sense data is valid */
+ u_char pad1; /* Also "segment number" for copy */
+ u_char key :4; /* Sense keys defined below */
+ u_char pad2 :1;
+ u_char badBlockLen :1; /* Block length mis-match (Exabyte) */
+ u_char endOfMedia :1; /* End of media reached */
+ u_char fileMark :1; /* File mark on device */
+ u_char info1; /* Information byte 1 */
+ u_char info2; /* Information byte 2 */
+ u_char info3; /* Information byte 3 */
+ u_char info4; /* Information byte 4 */
+ u_char length; /* Number of additional info bytes */
+#endif
+} ScsiClass7Sense; /* 8 Bytes */
+
+/*
+ * Key values for standardized sense class 7.
+ */
+#define SCSI_CLASS7_NO_SENSE 0
+#define SCSI_CLASS7_RECOVERABLE 1
+#define SCSI_CLASS7_NOT_READY 2
+#define SCSI_CLASS7_MEDIA_ERROR 3
+#define SCSI_CLASS7_HARDWARE_ERROR 4
+#define SCSI_CLASS7_ILLEGAL_REQUEST 5
+
+/*
+ * These seem to have different meanings to different vendors....
+ */
+#define SCSI_CLASS7_MEDIA_CHANGE 6
+#define SCSI_CLASS7_UNIT_ATTN 6
+
+#define SCSI_CLASS7_WRITE_PROTECT 7
+#define SCSI_CLASS7_BLANK_CHECK 8
+#define SCSI_CLASS7_VENDOR 9
+#define SCSI_CLASS7_POWER_UP_FAILURE 10
+#define SCSI_CLASS7_ABORT 11
+#define SCSI_CLASS7_EQUAL 12
+#define SCSI_CLASS7_OVERFLOW 13
+#define SCSI_CLASS7_RESERVED_14 14
+#define SCSI_CLASS7_RESERVED_15 15
+
+/*
+ * Data return by the SCSI inquiry command.
+ */
+typedef struct ScsiInquiryData {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char type; /* Peripheral Device type. See below. */
+ u_char rmb:1; /* Removable Medium bit. */
+ u_char qualifier:7; /* Device type qualifier. */
+ u_char version; /* Version info. */
+ u_char reserved:4; /* reserved. */
+ u_char format:4; /* Response format. */
+ u_char length; /* length of data returned. */
+ u_char reserved2[2]; /* Reserved */
+ u_char flags; /* SCSI II flags (see below) */
+ u_char vendorID[8]; /* Vendor ID (ASCII) */
+ u_char productID[16]; /* Product ID (ASCII) */
+ u_char revLevel[4]; /* Revision level (ASCII) */
+ u_char revData[8]; /* Revision data (ASCII) */
+#else
+ u_char type; /* Peripheral Device type. See below. */
+ u_char qualifier:7; /* Device type qualifier. */
+ u_char rmb:1; /* Removable Medium bit. */
+ u_char version; /* Version info. */
+ u_char format:4; /* Response format. */
+ u_char reserved:4; /* reserved. */
+ u_char length; /* length of data returned. */
+ u_char reserved2[2]; /* Reserved */
+ u_char flags; /* SCSI II flags (see below) */
+ u_char vendorID[8]; /* Vendor ID (ASCII) */
+ u_char productID[16]; /* Product ID (ASCII) */
+ u_char revLevel[4]; /* Revision level (ASCII) */
+ u_char revData[8]; /* Revision data (ASCII) */
+#endif
+} ScsiInquiryData;
+
+/*
+ * The SCSI Peripheral type ID codes as return by the SCSI_INQUIRY command.
+ *
+ * SCSI_DISK_TYPE - Direct Access Device.
+ * SCSI_TAPE_TYPE - Sequential Access Device.
+ * SCSI_PRINTER_TYPE - Printer Device.
+ * SCSI_HOST_TYPE - Processor Device.
+ * SCSI_WORM_TYPE - Write-Once Read-Multiple Device.
+ * SCSI_ROM_TYPE - Read-Only Direct Access Device.
+ * SCSI_SCANNER_TYPE - Scanner device.
+ * SCSI_OPTICAL_MEM_TYPE - Optical memory device.
+ * SCSI_MEDIUM_CHANGER_TYPE - Medium changer device.
+ * SCSI_COMMUNICATIONS_TYPE - Communications device.
+ * SCSI_NODEVICE_TYPE - Logical Unit not present or implemented.
+ *
+ * Note that codes 0xa-0x7e are reserved and 0x80-0xff are vendor unique.
+ */
+#define SCSI_DISK_TYPE 0
+#define SCSI_TAPE_TYPE 1
+#define SCSI_PRINTER_TYPE 2
+#define SCSI_HOST_TYPE 3
+#define SCSI_WORM_TYPE 4
+#define SCSI_ROM_TYPE 5
+#define SCSI_SCANNER_TYPE 6
+#define SCSI_OPTICAL_MEM_TYPE 7
+#define SCSI_MEDIUM_CHANGER_TYPE 8
+#define SCSI_COMMUNICATIONS_TYPE 9
+#define SCSI_NODEVICE_TYPE 0x7f
+
+/*
+ * The SCSI I & II inquiry flags.
+ *
+ * SCSI_REL_ADR - Relative addressing supported.
+ * SCSI_WIDE_32 - 32 bit wide SCSI bus transfers supported.
+ * SCSI_WIDE_16 - 16 bit wide SCSI bus transfers supported.
+ * SCSI_SYNC - Synchronous data transfers supported.
+ * SCSI_LINKED - Linked commands supported.
+ * SCSI_CMD_QUEUE - Tagged command queuing supported.
+ * SCSI_SOFT_RESET - Soft RESET alternative suported.
+ */
+#define SCSI_REL_ADR 0x80
+#define SCSI_WIDE_32 0x40
+#define SCSI_WIDE_16 0x20
+#define SCSI_SYNC 0x10
+#define SCSI_LINKED 0x08
+#define SCSI_CMD_QUEUE 0x02
+#define SCSI_SOFT_RESET 0x01
+
+/*
+ * Standard header for SCSI_MODE_SENSE and SCSI_MODE_SELECT commands for tapes.
+ */
+typedef struct ScsiTapeModeSelectHdr {
+ u_char len; /* length */
+ u_char media; /* media type */
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char writeprot:1; /* Write protected media */
+ u_char bufferedMode:3; /* Type of buffer to be done. */
+ u_char speed:4; /* Drive speed. */
+#else
+ u_char speed:4; /* Drive speed. */
+ u_char bufferedMode:3; /* Type of buffer to be done. */
+ u_char writeprot:1; /* Write protected media */
+#endif
+ u_char length; /* Block descriptor length. */
+ u_char density; /* tape density code */
+ u_char blocks_2; /* number of blocks (MSB) */
+ u_char blocks_1; /* number of blocks */
+ u_char blocks_0; /* number of blocks (LSB) */
+ u_char reserved; /* */
+ u_char block_size2; /* Tape block size (MSB) */
+ u_char block_size1; /* Tape block size */
+ u_char block_size0; /* Tape block size (LSB) */
+ u_char vendor[6]; /* vendor specific data */
+} ScsiTapeModeSelectHdr;
+
+/*
+ * Definitions of SCSI messages.
+ *
+ * SCSI_COMMAND_COMPLETE - After a command has completed, successfully
+ * or not, this is returned to the host from the target.
+ *
+ * SCSI_EXTENDED_MSG - Indicates that a multi-byte message is being sent.
+ *
+ * The following messages are used with connect/disconnect:
+ * SCSI_SAVE_DATA_POINTER - Sent from target to host to request saving
+ * of current DMA address and count. Indicates a pending dis-connect.
+ * SCSI_RESTORE_POINTER - Sent from the target to the host to request
+ * restoring pointers saved before a disconnect
+ * SCSI_DISCONNECT - Sent from the target to the host to disconnect.
+ * SCSI_ABORT - Sent from the host to the target to abort current request.
+ * SCSI_MESSAGE_REJECT - Indicates receipt, by either host or target, of
+ * an unimplemented message.
+ * SCSI_NO_OP - Sent from host to target if it has no real message to send.
+ * SCSI_MESSAGE_PARITY_ERROR - Sent from host to target on message parity error
+ * SCSI_BUS_RESET - Sent from host to target to reset all current I/O
+ *
+ * SCSI_IDENTIFY - The low order two bits of this message type indicate
+ * the Logical Unit of the Target which is requesting a reconnect.
+ * SCSI_DIS_REC_IDENTIFY - Sent from the host to a target to indicate
+ * is supports connect/dis-connect
+ *
+ */
+#define SCSI_COMMAND_COMPLETE 0x00
+#define SCSI_EXTENDED_MSG 0x01
+#define SCSI_SAVE_DATA_POINTER 0x02
+#define SCSI_RESTORE_POINTERS 0x03
+#define SCSI_DISCONNECT 0x04
+#define SCSI_ABORT 0x06
+#define SCSI_MESSAGE_REJECT 0x07
+#define SCSI_NO_OP 0x08
+#define SCSI_MESSAGE_PARITY_ERROR 0x09
+#define SCSI_LINKED_CMD_COMPLETE 0x0A
+#define SCSI_LINKED_FLAGED_CMD_COMPLETE 0x0B
+#define SCSI_BUS_RESET 0x0C
+
+#define SCSI_IDENTIFY 0x80
+#define SCSI_DIS_REC_IDENTIFY 0xc0
+
+/*
+ * Extended message types (2nd byte of SCSI_EXTENDED_MSG).
+ */
+#define SCSI_MODIFY_DATA_PTR 0x00
+#define SCSI_SYNCHRONOUS_XFER 0x01
+#define SCSI_EXTENDED_IDENTIFY 0x02 /* only in SCSI I */
+#define SCSI_WIDE_XFER 0x03
+
+/*
+ * Driver ioctl's for various scsi operations.
+ */
+#ifndef _IOCTL_
+#include <sys/ioctl.h>
+#endif
+
+/*
+ * Control for SCSI "format" mode.
+ *
+ * "Format" mode allows a privileged process to issue direct SCSI
+ * commands to a drive (it is intended primarily to allow on-line
+ * formatting). SDIOCSFORMAT with a non-zero arg will put the drive
+ * into format mode; a zero arg will take it out. When in format
+ * mode, only the process that issued the SDIOCFORMAT can read or
+ * write the drive.
+ *
+ * In format mode, process is expected to
+ * - do SDIOCSCSICOMMAND to supply cdb for next SCSI op
+ * - do read or write as appropriate for cdb
+ * - if i/o error, optionally do SDIOCSENSE to get completion
+ * status and sense data from last scsi operation.
+ */
+
+struct scsi_fmt_cdb {
+ int len; /* cdb length (in bytes) */
+ u_char cdb[28]; /* cdb to use on next read/write */
+};
+
+struct scsi_fmt_sense {
+ u_int status; /* completion status of last op */
+ u_char sense[32]; /* sense data (if any) from last op */
+};
+
+#define SDIOCSFORMAT _IOW('S', 0x1, int)
+#define SDIOCGFORMAT _IOR('S', 0x2, int)
+#define SDIOCSCSICOMMAND _IOW('S', 0x3, struct scsi_fmt_cdb)
+#define SDIOCSENSE _IOR('S', 0x4, struct scsi_fmt_sense)
+
+#ifdef _KERNEL
+/*
+ * Routines.
+ */
+extern void scsiGroup0Cmd();
+extern void scsiGroup1Cmd();
+#endif /* _KERNEL */
+
+#endif /* _SCSI_H */
diff --git a/sys/arch/arc/include/ansi.h b/sys/arch/arc/include/ansi.h
new file mode 100644
index 00000000000..a8ded390579
--- /dev/null
+++ b/sys/arch/arc/include/ansi.h
@@ -0,0 +1,75 @@
+/* $OpenBSD: ansi.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: ansi.h,v 1.5 1994/10/26 21:09:33 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ansi.h 8.2 (Berkeley) 1/4/94
+ */
+
+#ifndef _ANSI_H_
+#define _ANSI_H_
+
+/*
+ * Types which are fundamental to the implementation and may appear in
+ * more than one standard header are defined here. Standard headers
+ * then use:
+ * #ifdef _BSD_SIZE_T_
+ * typedef _BSD_SIZE_T_ size_t;
+ * #undef _BSD_SIZE_T_
+ * #endif
+ */
+#define _BSD_CLOCK_T_ unsigned long /* clock() */
+#define _BSD_PTRDIFF_T_ int /* ptr1 - ptr2 */
+#define _BSD_SIZE_T_ unsigned int /* sizeof() */
+#define _BSD_SSIZE_T_ int /* byte count or error */
+#define _BSD_TIME_T_ long /* time() */
+#define _BSD_VA_LIST_ char * /* va_list */
+
+/*
+ * Runes (wchar_t) is declared to be an ``int'' instead of the more natural
+ * ``unsigned long'' or ``long''. Two things are happening here. It is not
+ * unsigned so that EOF (-1) can be naturally assigned to it and used. Also,
+ * it looks like 10646 will be a 31 bit standard. This means that if your
+ * ints cannot hold 32 bits, you will be in trouble. The reason an int was
+ * chosen over a long is that the is*() and to*() routines take ints (says
+ * ANSI C), but they use _RUNE_T_ instead of int. By changing it here, you
+ * lose a bit of ANSI conformance, but your programs will still work.
+ *
+ * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type. When wchar_t
+ * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains
+ * defined for ctype.h.
+ */
+#define _BSD_WCHAR_T_ int /* wchar_t */
+#define _BSD_RUNE_T_ int /* rune_t */
+
+#endif /* _ANSI_H_ */
diff --git a/sys/arch/arc/include/asm.h b/sys/arch/arc/include/asm.h
new file mode 100644
index 00000000000..b276c10a1f3
--- /dev/null
+++ b/sys/arch/arc/include/asm.h
@@ -0,0 +1,160 @@
+/* $OpenBSD: asm.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (C) 1989 Digital Equipment Corporation.
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies.
+ * Digital Equipment Corporation makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+
+#ifndef _MACHASMDEFS
+#define _MACHASMDEFS
+
+#include <machine/regdef.h>
+
+#define ABICALLS
+
+#define RCSID(x)
+
+#define _C_LABEL(x) x
+
+/*
+ * Define -pg profile entry code.
+ */
+#if defined(GPROF) || defined(PROF)
+#define MCOUNT .set noreorder; \
+ .set noat; \
+ move $1,$31; \
+ jal _mcount; \
+ subu sp,sp,8; \
+ .set reorder; \
+ .set at;
+#else
+#define MCOUNT
+#endif
+
+/*
+ * LEAF(x)
+ *
+ * Declare a leaf routine.
+ */
+#define LEAF(x) \
+ .globl x; \
+ .ent x, 0; \
+x: ; \
+ .frame sp, 0, ra; \
+ MCOUNT
+
+/*
+ * NLEAF(x)
+ *
+ * Declare a non-profiled leaf routine.
+ */
+#define NLEAF(x) \
+ .globl x; \
+ .ent x, 0; \
+x: ; \
+ .frame sp, 0, ra
+
+/*
+ * ALEAF -- declare alternate entry to a leaf routine.
+ */
+#define ALEAF(x) \
+ .globl x; \
+x:
+
+/*
+ * NON_LEAF(x)
+ *
+ * Declare a non-leaf routine (a routine that makes other C calls).
+ */
+#define NON_LEAF(x, fsize, retpc) \
+ .globl x; \
+ .ent x, 0; \
+x: ; \
+ .frame sp, fsize, retpc; \
+ MCOUNT
+
+/*
+ * NNON_LEAF(x)
+ *
+ * Declare a non-profiled non-leaf routine
+ * (a routine that makes other C calls).
+ */
+#define NNON_LEAF(x, fsize, retpc) \
+ .globl x; \
+ .ent x, 0; \
+x: ; \
+ .frame sp, fsize, retpc
+
+/*
+ * END(x)
+ *
+ * Mark end of a procedure.
+ */
+#define END(x) \
+ .end x
+
+#define STAND_FRAME_SIZE 24
+#define STAND_RA_OFFSET 20
+
+/*
+ * Macros to panic and printf from assembly language.
+ */
+#define PANIC(msg) \
+ la a0, 9f; \
+ jal panic; \
+ MSG(msg)
+
+#define PRINTF(msg) \
+ la a0, 9f; \
+ jal printf; \
+ MSG(msg)
+
+#define MSG(msg) \
+ .rdata; \
+9: .asciiz msg; \
+ .text
+
+#define ASMSTR(str) \
+ .asciiz str; \
+ .align 3
+
+#endif /* _MACHASMDEFS */
diff --git a/sys/arch/arc/include/autoconf.h b/sys/arch/arc/include/autoconf.h
new file mode 100644
index 00000000000..650e387012d
--- /dev/null
+++ b/sys/arch/arc/include/autoconf.h
@@ -0,0 +1,79 @@
+/* $OpenBSD: autoconf.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: autoconf.h,v 1.1 1995/02/13 23:07:31 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Machine-dependent structures of autoconfiguration
+ */
+
+#ifndef _ARC_AUTOCONF_H_
+#define _ARC_AUTOCONF_H_
+
+struct confargs;
+
+typedef int (*intr_handler_t) __P((void *));
+
+struct abus {
+ struct device *ab_dv; /* back-pointer to device */
+ int ab_type; /* bus type (see below) */
+ void (*ab_intr_establish) /* bus's set-handler function */
+ __P((struct confargs *, intr_handler_t, void *));
+ void (*ab_intr_disestablish) /* bus's unset-handler function */
+ __P((struct confargs *));
+ caddr_t (*ab_cvtaddr) /* convert slot/offset to address */
+ __P((struct confargs *));
+ int (*ab_matchname) /* see if name matches driver */
+ __P((struct confargs *, char *));
+};
+
+#define BUS_MAIN 1 /* mainbus */
+#define BUS_PICA 2 /* PICA Bus */
+#define BUS_ISABR 3 /* ISA Bridge Bus */
+
+#define BUS_INTR_ESTABLISH(ca, handler, val) \
+ (*(ca)->ca_bus->ab_intr_establish)((ca), (handler), (val))
+#define BUS_INTR_DISESTABLISH(ca) \
+ (*(ca)->ca_bus->ab_intr_establish)(ca)
+#define BUS_CVTADDR(ca) \
+ (*(ca)->ca_bus->ab_cvtaddr)(ca)
+#define BUS_MATCHNAME(ca, name) \
+ (*(ca)->ca_bus->ab_matchname)((ca), (name))
+
+struct confargs {
+ char *ca_name; /* Device name. */
+ int ca_slot; /* Device slot. */
+ int ca_offset; /* Offset into slot. */
+ struct abus *ca_bus; /* bus device resides on. */
+};
+
+void set_clockintr __P((void (*)(struct clockframe *)));
+void set_iointr __P((void (*)(void *, int)));
+int badaddr __P((void *, u_int64_t));
+
+#endif /* _ARC_AUTOCONF_H_ */
diff --git a/sys/arch/arc/include/bus.h b/sys/arch/arc/include/bus.h
new file mode 100644
index 00000000000..8f9d234ac15
--- /dev/null
+++ b/sys/arch/arc/include/bus.h
@@ -0,0 +1,132 @@
+/* $OpenBSD: bus.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: bus.h,v 1.2 1996/04/05 23:59:37 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ARC_BUS_H_
+#define _ARC_BUS_H_
+
+#include <machine/autoconf.h>
+#include <machine/pio.h>
+
+/*
+ * I/O addresses (in bus space)
+ */
+typedef u_long bus_io_addr_t;
+typedef u_long bus_io_size_t;
+typedef u_long bus_io_handle_t;
+
+/*
+ * Memory addresses (in bus space)
+ */
+typedef u_long bus_mem_addr_t;
+typedef u_long bus_mem_size_t;
+typedef caddr_t bus_mem_handle_t;
+
+/*
+ * Access methods for bus resources, I/O space, and memory space.
+ */
+typedef
+struct arc_isa_busmap {
+ void *isa_io_base;
+ void *isa_mem_base;
+} *bus_chipset_tag_t;
+
+
+#define bus_io_map(t, port, size, iohp) \
+ (*iohp = (t == NULL ? port : port + (ulong)(t->isa_io_base)), 0)
+#define bus_io_unmap(t, ioh, size)
+
+#define bus_io_read_1(t, h, o) inb((h) + (o))
+#define bus_io_read_2(t, h, o) inw((h) + (o))
+#define bus_io_read_4(t, h, o) inl((h) + (o))
+#if 0 /* Cause a link error for bus_io_read_8 */
+#define bus_io_read_8(t, h, o) !!! bus_io_read_8 unimplemented !!!
+#endif
+
+#define bus_io_read_multi_1(t, h, o, a, c) \
+ insb((h) + (o), (a), (c))
+#define bus_io_read_multi_2(t, h, o, a, c) \
+ insw((h) + (o), (a), (c))
+#define bus_io_read_multi_4(t, h, o, a, c) \
+ insl((h) + (o), (a), (c))
+#if 0 /* Cause a link error for bus_io_read_multi_8 */
+#define bus_io_read_multi_8(t, h, o, a, c) \
+ !!! bus_io_read_multi_8 unimplemented !!!
+#endif
+
+#define bus_io_write_1(t, h, o, v) outb((h) + (o), (v))
+#define bus_io_write_2(t, h, o, v) outw((h) + (o), (v))
+#define bus_io_write_4(t, h, o, v) outl((h) + (o), (v))
+#if 0 /* Cause a link error for bus_io_write_8 */
+#define bus_io_write_8(t, h, o, v) !!! bus_io_write_8 unimplemented !!!
+#endif
+
+#define bus_io_write_multi_1(t, h, o, a, c) \
+ outsb((h) + (o), (a), (c))
+#define bus_io_write_multi_2(t, h, o, a, c) \
+ outsw((h) + (o), (a), (c))
+#define bus_io_write_multi_4(t, h, o, a, c) \
+ outsl((h) + (o), (a), (c))
+#if 0 /* Cause a link error for bus_io_write_multi_8 */
+#define bus_io_write_multi_8(t, h, o, a, c) \
+ !!! bus_io_write_multi_8 unimplimented !!!
+#endif
+
+int bus_mem_map __P((bus_chipset_tag_t t, bus_mem_addr_t bpa,
+ bus_mem_size_t size, int cacheable, bus_mem_handle_t *mhp));
+void bus_mem_unmap __P((bus_chipset_tag_t t, bus_mem_handle_t memh,
+ bus_mem_size_t size));
+
+#define bus_mem_read_1(t, h, o) (*(volatile u_int8_t *)((h) + (o)))
+#define bus_mem_read_2(t, h, o) (*(volatile u_int16_t *)((h) + (o)))
+#define bus_mem_read_4(t, h, o) (*(volatile u_int32_t *)((h) + (o)))
+#define bus_mem_read_8(t, h, o) (*(volatile u_int64_t *)((h) + (o)))
+
+#define bus_mem_write_1(t, h, o, v) \
+ ((void)(*(volatile u_int8_t *)((h) + (o)) = (v)))
+#define bus_mem_write_2(t, h, o, v) \
+ ((void)(*(volatile u_int16_t *)((h) + (o)) = (v)))
+#define bus_mem_write_4(t, h, o, v) \
+ ((void)(*(volatile u_int32_t *)((h) + (o)) = (v)))
+#define bus_mem_write_8(t, h, o, v) \
+ ((void)(*(volatile u_int64_t *)((h) + (o)) = (v)))
+
+/* These are extensions to the general NetBSD bus interface. */
+#define bus_to_host_2(t, v) (v)
+#define bus_to_host_4(t, v) (v)
+#define bus_to_host_8(t, v) (v)
+
+#define bus_from_host_2(t, v) (v)
+#define bus_from_host_4(t, v) (v)
+#define bus_from_host_8(t, v) (v)
+
+#endif /* _ARC_BUS_H_ */
diff --git a/sys/arch/arc/include/cdefs.h b/sys/arch/arc/include/cdefs.h
new file mode 100644
index 00000000000..d60f7476119
--- /dev/null
+++ b/sys/arch/arc/include/cdefs.h
@@ -0,0 +1,39 @@
+/* $OpenBSD: cdefs.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: cdefs.h,v 1.3 1995/05/03 06:04:54 mellon Exp $ */
+
+/*
+ * Copyright (c) 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _MACHINE_CDEFS_H_
+#define _MACHINE_CDEFS_H_
+
+#define _C_LABEL(x) _STRING(x)
+
+#define __indr_references(sym,msg) /* nothing */
+#define __warn_references(sym,msg) /* nothing */
+
+#endif /* !_MACHINE_CDEFS_H_ */
diff --git a/sys/arch/arc/include/cpu.h b/sys/arch/arc/include/cpu.h
new file mode 100644
index 00000000000..a15717c3374
--- /dev/null
+++ b/sys/arch/arc/include/cpu.h
@@ -0,0 +1,417 @@
+/* $OpenBSD: cpu.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (C) 1989 Digital Equipment Corporation.
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies.
+ * Digital Equipment Corporation makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * from: @(#)cpu.h 8.4 (Berkeley) 1/4/94
+ */
+
+#ifndef _CPU_H_
+#define _CPU_H_
+
+#define KUSEG_ADDR 0x0
+#define CACHED_MEMORY_ADDR 0x80000000
+#define UNCACHED_MEMORY_ADDR 0xa0000000
+#define KSEG2_ADDR 0xc0000000
+#define MAX_MEM_ADDR 0xbe000000
+#define RESERVED_ADDR 0xbfc80000
+
+#define CACHED_TO_PHYS(x) ((unsigned)(x) & 0x1fffffff)
+#define PHYS_TO_CACHED(x) ((unsigned)(x) | CACHED_MEMORY_ADDR)
+#define UNCACHED_TO_PHYS(x) ((unsigned)(x) & 0x1fffffff)
+#define PHYS_TO_UNCACHED(x) ((unsigned)(x) | UNCACHED_MEMORY_ADDR)
+#define VA_TO_CINDEX(x) ((unsigned)(x) & 0xffffff | CACHED_MEMORY_ADDR)
+
+#define CODE_START 0x80080000
+
+#ifdef _KERNEL
+/*
+ * The bits in the cause register.
+ *
+ * CR_BR_DELAY Exception happened in branch delay slot.
+ * CR_COP_ERR Coprocessor error.
+ * CR_IP Interrupt pending bits defined below.
+ * CR_EXC_CODE The exception type (see exception codes below).
+ */
+#define CR_BR_DELAY 0x80000000
+#define CR_COP_ERR 0x30000000
+#define CR_EXC_CODE 0x0000007C
+#define CR_IP 0x0000FF00
+#define CR_EXC_CODE_SHIFT 2
+
+/*
+ * The bits in the status register. All bits are active when set to 1.
+ */
+#define SR_COP_USABILITY 0xf0000000
+#define SR_COP_0_BIT 0x10000000
+#define SR_COP_1_BIT 0x20000000
+#define SR_RP 0x08000000
+#define SR_FR_32 0x04000000
+#define SR_RE 0x02000000
+#define SR_BOOT_EXC_VEC 0x00400000
+#define SR_TLB_SHUTDOWN 0x00200000
+#define SR_SOFT_RESET 0x00100000
+#define SR_DIAG_CH 0x00040000
+#define SR_DIAG_CE 0x00020000
+#define SR_DIAG_PE 0x00010000
+#define SR_KX 0x00000080
+#define SR_SX 0x00000040
+#define SR_UX 0x00000020
+#define SR_KSU_MASK 0x00000018
+#define SR_KSU_USER 0x00000010
+#define SR_KSU_SUPER 0x00000008
+#define SR_KSU_KERNEL 0x00000000
+#define SR_ERL 0x00000004
+#define SR_EXL 0x00000002
+#define SR_INT_ENAB 0x00000001
+/*#define SR_INT_MASK 0x0000ff00*/
+
+/*
+ * The interrupt masks.
+ * If a bit in the mask is 1 then the interrupt is enabled (or pending).
+ */
+#define INT_MASK 0x7f00
+#define INT_MASK_5 0x8000 /* Not used (on chip timer) */
+#define INT_MASK_4 0x4000
+#define INT_MASK_3 0x2000
+#define INT_MASK_2 0x1000
+#define INT_MASK_1 0x0800
+#define INT_MASK_0 0x0400
+#define HARD_INT_MASK 0x7c00
+#define SOFT_INT_MASK_1 0x0200
+#define SOFT_INT_MASK_0 0x0100
+
+/*
+ * The bits in the context register.
+ */
+#define CNTXT_PTE_BASE 0xFF800000
+#define CNTXT_BAD_VPN2 0x007FFFF0
+
+/*
+ * Location of exception vectors.
+ */
+#define RESET_EXC_VEC 0xBFC00000
+#define TLB_MISS_EXC_VEC 0x80000000
+#define XTLB_MISS_EXC_VEC 0x80000080
+#define CACHE_ERR_EXC_VEC 0x80000100
+#define GEN_EXC_VEC 0x80000180
+
+/*
+ * Coprocessor 0 registers:
+ */
+#define COP_0_TLB_INDEX $0
+#define COP_0_TLB_RANDOM $1
+#define COP_0_TLB_LO0 $2
+#define COP_0_TLB_LO1 $3
+#define COP_0_TLB_CONTEXT $4
+#define COP_0_TLB_PG_MASK $5
+#define COP_0_TLB_WIRED $6
+#define COP_0_BAD_VADDR $8
+#define COP_0_TLB_HI $10
+#define COP_0_STATUS_REG $12
+#define COP_0_CAUSE_REG $13
+#define COP_0_EXC_PC $14
+#define COP_0_PRID $15
+#define COP_0_CONFIG $16
+#define COP_0_LLADDR $17
+#define COP_0_WATCH_LO $18
+#define COP_0_WATCH_HI $19
+#define COP_0_TLB_XCONTEXT $20
+#define COP_0_ECC $26
+#define COP_0_CACHE_ERR $27
+#define COP_0_TAG_LO $28
+#define COP_0_TAG_HI $29
+#define COP_0_ERROR_PC $30
+
+/*
+ * Values for the code field in a break instruction.
+ */
+#define BREAK_INSTR 0x0000000d
+#define BREAK_VAL_MASK 0x03ff0000
+#define BREAK_VAL_SHIFT 16
+#define BREAK_KDB_VAL 512
+#define BREAK_SSTEP_VAL 513
+#define BREAK_BRKPT_VAL 514
+#define BREAK_SOVER_VAL 515
+#define BREAK_KDB (BREAK_INSTR | (BREAK_KDB_VAL << BREAK_VAL_SHIFT))
+#define BREAK_SSTEP (BREAK_INSTR | (BREAK_SSTEP_VAL << BREAK_VAL_SHIFT))
+#define BREAK_BRKPT (BREAK_INSTR | (BREAK_BRKPT_VAL << BREAK_VAL_SHIFT))
+#define BREAK_SOVER (BREAK_INSTR | (BREAK_SOVER_VAL << BREAK_VAL_SHIFT))
+
+/*
+ * Mininum and maximum cache sizes.
+ */
+#define MIN_CACHE_SIZE (16 * 1024)
+#define MAX_CACHE_SIZE (256 * 1024)
+
+/*
+ * The floating point version and status registers.
+ */
+#define FPC_ID $0
+#define FPC_CSR $31
+
+/*
+ * The floating point coprocessor status register bits.
+ */
+#define FPC_ROUNDING_BITS 0x00000003
+#define FPC_ROUND_RN 0x00000000
+#define FPC_ROUND_RZ 0x00000001
+#define FPC_ROUND_RP 0x00000002
+#define FPC_ROUND_RM 0x00000003
+#define FPC_STICKY_BITS 0x0000007c
+#define FPC_STICKY_INEXACT 0x00000004
+#define FPC_STICKY_UNDERFLOW 0x00000008
+#define FPC_STICKY_OVERFLOW 0x00000010
+#define FPC_STICKY_DIV0 0x00000020
+#define FPC_STICKY_INVALID 0x00000040
+#define FPC_ENABLE_BITS 0x00000f80
+#define FPC_ENABLE_INEXACT 0x00000080
+#define FPC_ENABLE_UNDERFLOW 0x00000100
+#define FPC_ENABLE_OVERFLOW 0x00000200
+#define FPC_ENABLE_DIV0 0x00000400
+#define FPC_ENABLE_INVALID 0x00000800
+#define FPC_EXCEPTION_BITS 0x0003f000
+#define FPC_EXCEPTION_INEXACT 0x00001000
+#define FPC_EXCEPTION_UNDERFLOW 0x00002000
+#define FPC_EXCEPTION_OVERFLOW 0x00004000
+#define FPC_EXCEPTION_DIV0 0x00008000
+#define FPC_EXCEPTION_INVALID 0x00010000
+#define FPC_EXCEPTION_UNIMPL 0x00020000
+#define FPC_COND_BIT 0x00800000
+#define FPC_FLUSH_BIT 0x01000000
+#define FPC_MBZ_BITS 0xfe7c0000
+
+/*
+ * Constants to determine if have a floating point instruction.
+ */
+#define OPCODE_SHIFT 26
+#define OPCODE_C1 0x11
+
+/*
+ * The low part of the TLB entry.
+ */
+#define VMTLB_PF_NUM 0x3fffffc0
+#define VMTLB_ATTR_MASK 0x00000038
+#define VMTLB_MOD_BIT 0x00000004
+#define VMTLB_VALID_BIT 0x00000002
+#define VMTLB_GLOBAL_BIT 0x00000001
+
+#define VMTLB_PHYS_PAGE_SHIFT 6
+
+/*
+ * The high part of the TLB entry.
+ */
+#define VMTLB_VIRT_PAGE_NUM 0xffffe000
+#define VMTLB_PID 0x000000ff
+#define VMTLB_PID_SHIFT 0
+#define VMTLB_VIRT_PAGE_SHIFT 12
+
+/*
+ * The number of TLB entries and the first one that write random hits.
+ */
+#define VMNUM_TLB_ENTRIES 48
+#define VMWIRED_ENTRIES 8
+
+/*
+ * The number of process id entries.
+ */
+#define VMNUM_PIDS 256
+
+/*
+ * TLB probe return codes.
+ */
+#define VMTLB_NOT_FOUND 0
+#define VMTLB_FOUND 1
+#define VMTLB_FOUND_WITH_PATCH 2
+#define VMTLB_PROBE_ERROR 3
+
+/*
+ * Kernel virtual address for user page table entries
+ * (i.e., the address for the context register).
+ */
+#define VMPTE_BASE 0xFF800000
+
+#endif /* _KERNEL */
+
+/*
+ * Exported definitions unique to pica/mips cpu support.
+ */
+
+/*
+ * definitions of cpu-dependent requirements
+ * referenced in generic code
+ */
+#define COPY_SIGCODE /* copy sigcode above user stack in exec */
+
+#define cpu_wait(p) /* nothing */
+#define cpu_set_init_frame(p, fp) /* nothing */
+#define cpu_swapout(p) panic("cpu_swapout: can't get here");
+
+#ifndef _LOCORE
+/*
+ * Arguments to hardclock and gatherstats encapsulate the previous
+ * machine state in an opaque clockframe.
+ */
+struct clockframe {
+ int pc; /* program counter at time of interrupt */
+ int sr; /* status register at time of interrupt */
+};
+
+#define CLKF_USERMODE(framep) ((framep)->sr & SR_KSU_USER)
+#define CLKF_BASEPRI(framep) ((~(framep)->sr & (INT_MASK|SR_INT_ENAB)) == 0)
+#define CLKF_PC(framep) ((framep)->pc)
+#define CLKF_INTR(framep) (0)
+
+/*
+ * Preempt the current process if in interrupt from user mode,
+ * or after the current trap/syscall if in system mode.
+ */
+#define need_resched() { want_resched = 1; aston(); }
+
+/*
+ * Give a profiling tick to the current process when the user profiling
+ * buffer pages are invalid. On the PICA, request an ast to send us
+ * through trap, marking the proc as needing a profiling tick.
+ */
+#define need_proftick(p) { (p)->p_flag |= P_OWEUPC; aston(); }
+
+/*
+ * Notify the current process (p) that it has a signal pending,
+ * process as soon as possible.
+ */
+#define signotify(p) aston()
+
+#define aston() (astpending = 1)
+
+int astpending; /* need to trap before returning to user mode */
+int want_resched; /* resched() was called */
+
+/*
+ * CPU identification, from PRID register.
+ */
+union cpuprid {
+ int cpuprid;
+ struct {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int pad1:16; /* reserved */
+ u_int cp_imp:8; /* implementation identifier */
+ u_int cp_majrev:4; /* major revision identifier */
+ u_int cp_minrev:4; /* minor revision identifier */
+#else
+ u_int cp_minrev:4; /* minor revision identifier */
+ u_int cp_majrev:4; /* major revision identifier */
+ u_int cp_imp:8; /* implementation identifier */
+ u_int pad1:16; /* reserved */
+#endif
+ } cpu;
+};
+
+/*
+ * CTL_MACHDEP definitions.
+ */
+#define CPU_CONSDEV 1 /* dev_t: console terminal device */
+#define CPU_MAXID 2 /* number of valid machdep ids */
+
+#define CTL_MACHDEP_NAMES { \
+ { 0, 0 }, \
+ { "console_device", CTLTYPE_STRUCT }, \
+}
+
+#endif /* !_LOCORE */
+
+/*
+ * MIPS CPU types (cp_imp).
+ */
+#define MIPS_R2000 0x01 /* MIPS R2000 CPU ISA I */
+#define MIPS_R3000 0x02 /* MIPS R3000 CPU ISA I */
+#define MIPS_R6000 0x03 /* MIPS R6000 CPU ISA II */
+#define MIPS_R4000 0x04 /* MIPS R4000/4400 CPU ISA III */
+#define MIPS_R3LSI 0x05 /* LSI Logic R3000 derivate ISA I */
+#define MIPS_R6000A 0x06 /* MIPS R6000A CPU ISA II */
+#define MIPS_R3IDT 0x07 /* IDT R3000 derivate ISA I */
+#define MIPS_R10000 0x09 /* MIPS R10000/T5 CPU ISA IV */
+#define MIPS_R4200 0x0a /* MIPS R4200 CPU (ICE) ISA III */
+#define MIPS_UNKC1 0x0b /* unnanounced product cpu ISA III */
+#define MIPS_UNKC2 0x0c /* unnanounced product cpu ISA III */
+#define MIPS_R8000 0x10 /* MIPS R8000 Blackbird/TFP ISA IV */
+#define MIPS_R4600 0x20 /* QED R4600 Orion ISA III */
+#define MIPS_R3SONY 0x21 /* Sony R3000 based CPU ISA I */
+#define MIPS_R3TOSH 0x22 /* Toshiba R3000 based CPU ISA I */
+#define MIPS_R3NKK 0x23 /* NKK R3000 based CPU ISA I */
+
+/*
+ * MIPS FPU types
+ */
+#define MIPS_SOFT 0x00 /* Software emulation ISA I */
+#define MIPS_R2360 0x01 /* MIPS R2360 FPC ISA I */
+#define MIPS_R2010 0x02 /* MIPS R2010 FPC ISA I */
+#define MIPS_R3010 0x03 /* MIPS R3010 FPC ISA I */
+#define MIPS_R6010 0x04 /* MIPS R6010 FPC ISA II */
+#define MIPS_R4010 0x05 /* MIPS R4000/R4400 FPC ISA II */
+#define MIPS_R31LSI 0x06 /* LSI Logic derivate ISA I */
+#define MIPS_R10010 0x09 /* MIPS R10000/T5 FPU ISA IV */
+#define MIPS_R4210 0x0a /* MIPS R4200 FPC (ICE) ISA III */
+#define MIPS_UNKF1 0x0b /* unnanounced product cpu ISA III */
+#define MIPS_R8000 0x10 /* MIPS R8000 Blackbird/TFP ISA IV */
+#define MIPS_R4600 0x20 /* QED R4600 Orion ISA III */
+#define MIPS_R3SONY 0x21 /* Sony R3000 based FPU ISA I */
+#define MIPS_R3TOSH 0x22 /* Toshiba R3000 based FPU ISA I */
+#define MIPS_R3NKK 0x23 /* NKK R3000 based FPU ISA I */
+
+#if defined(_KERNEL) && !defined(_LOCORE)
+union cpuprid cpu_id;
+union cpuprid fpu_id;
+u_int machPrimaryDataCacheSize;
+u_int machPrimaryInstCacheSize;
+u_int machPrimaryDataCacheLSize;
+u_int machPrimaryInstCacheLSize;
+u_int machCacheAliasMask;
+extern struct intr_tab intr_tab[];
+#endif
+
+/*
+ * Enable realtime clock (always enabled).
+ */
+#define enablertclock()
+
+#endif /* _CPU_H_ */
diff --git a/sys/arch/arc/include/disklabel.h b/sys/arch/arc/include/disklabel.h
new file mode 100644
index 00000000000..eefe2733114
--- /dev/null
+++ b/sys/arch/arc/include/disklabel.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: disklabel.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: disklabel.h,v 1.2 1995/01/18 06:37:55 mellon Exp $ */
+
+/*
+ * Copyright (c) 1994 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_DISKLABEL_H_
+#define _MACHINE_DISKLABEL_H_
+
+#define LABELSECTOR 0 /* sector containing label */
+#define LABELOFFSET 64 /* offset of label in sector */
+#define MAXPARTITIONS 8 /* number of partitions */
+#define RAW_PART 2 /* raw partition: xx?c */
+
+/* DOS partition table -- used when the system is booted from a dos
+ * partition. This is the case on NT systems.
+ */
+#define DOSBBSECTOR 0 /* DOS boot block relative sector # */
+#define DOSPARTOFF 446
+#define NDOSPART 4
+
+struct dos_partition {
+ unsigned char dp_flag; /* bootstrap flags */
+ unsigned char dp_shd; /* starting head */
+ unsigned char dp_ssect; /* starting sector */
+ unsigned char dp_scyl; /* starting cylinder */
+ unsigned char dp_typ; /* partition type (see below) */
+ unsigned char dp_ehd; /* end head */
+ unsigned char dp_esect; /* end sector */
+ unsigned char dp_ecyl; /* end cylinder */
+ unsigned long dp_start; /* absolute starting sector number */
+ unsigned long dp_size; /* partition size in sectors */
+} dos_partitions[NDOSPART];
+
+/* Known DOS partition types. */
+#define DOSPTYP_386BSD 0xa5 /* 386BSD partition type */
+#define DOSPTYP_NETBSD DOSPTYP_386BSD /* NetBSD partition type (XXX) */
+
+#include <sys/dkbad.h>
+struct cpu_disklabel {
+ struct dos_partition dosparts[NDOSPART];
+ struct dkbad bad;
+};
+
+/* Isolate the relevant bits to get sector and cylinder. */
+#define DPSECT(s) ((s) & 0x3f)
+#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2))
+
+#ifdef _KERNEL
+struct disklabel;
+int bounds_check_with_label __P((struct buf *, struct disklabel *, int));
+#endif
+
+#endif /* _MACHINE_DISKLABEL_H_ */
diff --git a/sys/arch/arc/include/display.h b/sys/arch/arc/include/display.h
new file mode 100644
index 00000000000..c5e6e2f2b64
--- /dev/null
+++ b/sys/arch/arc/include/display.h
@@ -0,0 +1,48 @@
+/* $OpenBSD: display.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+
+/*
+ * IBM PC display definitions
+ *
+ */
+
+/* Color attributes for foreground text */
+
+#define FG_BLACK 0
+#define FG_BLUE 1
+#define FG_GREEN 2
+#define FG_CYAN 3
+#define FG_RED 4
+#define FG_MAGENTA 5
+#define FG_BROWN 6
+#define FG_LIGHTGREY 7
+#define FG_DARKGREY 8
+#define FG_LIGHTBLUE 9
+#define FG_LIGHTGREEN 10
+#define FG_LIGHTCYAN 11
+#define FG_LIGHTRED 12
+#define FG_LIGHTMAGENTA 13
+#define FG_YELLOW 14
+#define FG_WHITE 15
+#define FG_BLINK 0x80
+#define FG_MASK 0x8f
+
+/* Color attributes for text background */
+
+#define BG_BLACK 0x00
+#define BG_BLUE 0x10
+#define BG_GREEN 0x20
+#define BG_CYAN 0x30
+#define BG_RED 0x40
+#define BG_MAGENTA 0x50
+#define BG_BROWN 0x60
+#define BG_LIGHTGREY 0x70
+#define BG_MASK 0x70
+
+/* Monochrome attributes for foreground text */
+
+#define FG_UNDERLINE 0x01
+#define FG_INTENSE 0x08
+
+/* Monochrome attributes for text background */
+
+#define BG_INTENSE 0x10
diff --git a/sys/arch/arc/include/ecoff.h b/sys/arch/arc/include/ecoff.h
new file mode 100644
index 00000000000..9cdc5c61277
--- /dev/null
+++ b/sys/arch/arc/include/ecoff.h
@@ -0,0 +1,90 @@
+/* $OpenBSD: ecoff.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: ecoff.h,v 1.4 1995/06/16 02:07:33 mellon Exp $ */
+
+/*
+ * Copyright (c) 1994 Adam Glass
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Glass.
+ * 4. The name of the Author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Adam Glass BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define ECOFF_LDPGSZ 4096
+
+#define ECOFF_PAD
+
+#define ECOFF_MACHDEP \
+ u_long ea_gprmask; \
+ u_long ea_cprmask[4]; \
+ u_long ea_gp_value
+
+#define ECOFF_MAGIC_MIPSEL 0x0162
+#define ECOFF_BADMAG(ex) ((ex)->f.f_magic != ECOFF_MAGIC_MIPSEL)
+
+#define ECOFF_SEGMENT_ALIGNMENT(eap) ((eap)->ea_vstamp < 23 ? 8 : 16)
+
+struct ecoff_symhdr {
+ int16_t sh_magic;
+ int16_t sh_vstamp;
+ int32_t sh_linemax;
+ int32_t sh_densenummax;
+ int32_t sh_procmax;
+ int32_t sh_lsymmax;
+ int32_t sh_optsymmax;
+ int32_t sh_auxxymmax;
+ int32_t sh_lstrmax;
+ int32_t sh_estrmax;
+ int32_t sh_fdmax;
+ int32_t sh_rfdmax;
+ int32_t sh_esymmax;
+ long sh_linesize;
+ long sh_lineoff;
+ long sh_densenumoff;
+ long sh_procoff;
+ long sh_lsymoff;
+ long sh_optsymoff;
+ long sh_auxsymoff;
+ long sh_lstroff;
+ long sh_estroff;
+ long sh_fdoff;
+ long sh_rfdoff;
+ long sh_esymoff;
+};
+
+struct ecoff_extsym {
+ long es_value;
+ int es_strindex;
+ unsigned es_type:6;
+ unsigned es_class:5;
+ unsigned :1;
+ unsigned es_symauxindex:20;
+ unsigned es_jmptbl:1;
+ unsigned es_cmain:1;
+ unsigned es_weakext:1;
+ unsigned :29;
+ int es_indexfld;
+};
+
diff --git a/sys/arch/arc/include/elf.h b/sys/arch/arc/include/elf.h
new file mode 100644
index 00000000000..c66e2005e3d
--- /dev/null
+++ b/sys/arch/arc/include/elf.h
@@ -0,0 +1,138 @@
+/* $OpenBSD: elf.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: elf.h,v 1.2 1995/03/28 18:19:14 jtc Exp $ */
+
+/*
+ * Copyright (c) 1994 Ted Lemon
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MACHINE_ELF_H__
+#define __MACHINE_ELF_H__
+
+/* ELF executable header... */
+struct ehdr {
+ char elf_magic [4]; /* Elf magic number... */
+ unsigned long magic [3]; /* Magic number... */
+ unsigned short type; /* Object file type... */
+ unsigned short machine; /* Machine ID... */
+ unsigned long version; /* File format version... */
+ unsigned long entry; /* Entry point... */
+ unsigned long phoff; /* Program header table offset... */
+ unsigned long shoff; /* Section header table offset... */
+ unsigned long flags; /* Processor-specific flags... */
+ unsigned short ehsize; /* Elf header size in bytes... */
+ unsigned short phsize; /* Program header size... */
+ unsigned short phcount; /* Program header count... */
+ unsigned short shsize; /* Section header size... */
+ unsigned short shcount; /* Section header count... */
+ unsigned short shstrndx; /* Section header string table index... */
+};
+
+/* Program header... */
+struct phdr {
+ unsigned long type; /* Segment type... */
+ unsigned long offset; /* File offset... */
+ unsigned long vaddr; /* Virtual address... */
+ unsigned long paddr; /* Physical address... */
+ unsigned long filesz; /* Size of segment in file... */
+ unsigned long memsz; /* Size of segment in memory... */
+ unsigned long flags; /* Segment flags... */
+ unsigned long align; /* Alighment, file and memory... */
+};
+
+/* Section header... */
+struct shdr {
+ unsigned long name; /* Offset into string table of section name */
+ unsigned long type; /* Type of section... */
+ unsigned long flags; /* Section flags... */
+ unsigned long addr; /* Section virtual address at execution... */
+ unsigned long offset; /* Section file offset... */
+ unsigned long size; /* Section size... */
+ unsigned long link; /* Link to another section... */
+ unsigned long info; /* Additional section info... */
+ unsigned long align; /* Section alignment... */
+ unsigned long esize; /* Entry size if section holds table... */
+};
+
+/* Symbol table entry... */
+struct sym {
+ unsigned long name; /* Index into strtab of symbol name. */
+ unsigned long value; /* Section offset, virt addr or common align. */
+ unsigned long size; /* Size of object referenced. */
+ unsigned type : 4; /* Symbol type (e.g., function, data)... */
+ unsigned binding : 4; /* Symbol binding (e.g., global, local)... */
+ unsigned char other; /* Unused. */
+ unsigned short shndx; /* Section containing symbol. */
+};
+
+/* Values for program header type field */
+
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved, unspecified semantics */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_LOPROC 0x70000000 /* Processor-specific */
+#define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
+#define PT_MIPS_REGINFO PT_LOPROC /* Mips reginfo section... */
+
+/* Program segment permissions, in program header flags field */
+
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+#define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
+
+/* Reserved section indices... */
+#define SHN_UNDEF 0
+#define SHN_ABS 0xfff1
+#define SHN_COMMON 0xfff2
+#define SHN_MIPS_ACOMMON 0xfff0
+
+/* Symbol bindings... */
+#define STB_LOCAL 0
+#define STB_GLOBAL 1
+#define STB_WEAK 2
+
+/* Symbol types... */
+#define STT_NOTYPE 0
+#define STT_OBJECT 1
+#define STT_FUNC 2
+#define STT_SECTION 3
+#define STT_FILE 4
+
+#define ELF_HDR_SIZE (sizeof (struct ehdr))
+#ifdef _KERNEL
+int pmax_elf_makecmds __P((struct proc *, struct exec_package *));
+#endif /* _KERNEL */
+#endif /* __MACHINE_ELF_H__ */
diff --git a/sys/arch/arc/include/endian.h b/sys/arch/arc/include/endian.h
new file mode 100644
index 00000000000..b03f0c5c78d
--- /dev/null
+++ b/sys/arch/arc/include/endian.h
@@ -0,0 +1,95 @@
+/* $OpenBSD: endian.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: endian.h,v 1.4 1994/10/26 21:09:38 cgd Exp $ */
+
+/*
+ * Copyright (c) 1987, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)endian.h 8.1 (Berkeley) 6/11/93
+ */
+
+#ifndef _ENDIAN_H_
+#define _ENDIAN_H_
+
+/*
+ * Define _NOQUAD if the compiler does NOT support 64-bit integers.
+ */
+/* #define _NOQUAD */
+
+/*
+ * Define the order of 32-bit words in 64-bit words.
+ */
+#define _QUAD_HIGHWORD 1
+#define _QUAD_LOWWORD 0
+
+#ifndef _POSIX_SOURCE
+/*
+ * Definitions for byte order, according to byte significance from low
+ * address to high.
+ */
+#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */
+#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */
+#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */
+
+#define BYTE_ORDER LITTLE_ENDIAN /* ``... Beautiful SPIIIIM!'' */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+unsigned long htonl __P((unsigned long));
+unsigned short htons __P((unsigned short));
+unsigned long ntohl __P((unsigned long));
+unsigned short ntohs __P((unsigned short));
+__END_DECLS
+
+/*
+ * Macros for network/external number representation conversion.
+ */
+#if BYTE_ORDER == BIG_ENDIAN && !defined(lint)
+#define ntohl(x) (x)
+#define ntohs(x) (x)
+#define htonl(x) (x)
+#define htons(x) (x)
+
+#define NTOHL(x) (x)
+#define NTOHS(x) (x)
+#define HTONL(x) (x)
+#define HTONS(x) (x)
+
+#else
+
+#define NTOHL(x) (x) = ntohl((u_long)x)
+#define NTOHS(x) (x) = ntohs((u_short)x)
+#define HTONL(x) (x) = htonl((u_long)x)
+#define HTONS(x) (x) = htons((u_short)x)
+#endif
+#endif /* ! _POSIX_SOURCE */
+#endif /* !_ENDIAN_H_ */
diff --git a/sys/arch/arc/include/exec.h b/sys/arch/arc/include/exec.h
new file mode 100644
index 00000000000..d4f4e03159f
--- /dev/null
+++ b/sys/arch/arc/include/exec.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: exec.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: exec.h,v 1.5 1994/10/26 21:09:39 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)exec.h 8.1 (Berkeley) 6/10/93
+ */
+
+#define __LDPGSZ 4096
+
+/*
+ * Define what exec "formats" we should handle.
+ */
+#define NATIVE_EXEC_ELF
+#define EXEC_SCRIPT
+
+#define ELF_TARG_CLASS ELFCLASS32
+#define ELF_TARG_DATA ELFDATA2LSB
+#define ELF_TARG_MACH EM_MIPS
+
+/*
+ * This is what we want nlist(3) to handle.
+ */
+#define DO_AOUT /* support a.out */
+#define DO_ELF /* support ELF */
+#define DO_ECOFF /* support ECOFF */
+
diff --git a/sys/arch/arc/include/float.h b/sys/arch/arc/include/float.h
new file mode 100644
index 00000000000..db2c3da071f
--- /dev/null
+++ b/sys/arch/arc/include/float.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: float.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: float.h,v 1.7 1995/06/20 20:45:50 jtc Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)float.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _PMAX_FLOAT_H_
+#define _PMAX_FLOAT_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int __flt_rounds();
+__END_DECLS
+
+#define FLT_RADIX 2 /* b */
+#define FLT_ROUNDS __flt_rounds()
+
+#define FLT_MANT_DIG 24 /* p */
+#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */
+#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */
+#define FLT_MIN_EXP -125 /* emin */
+#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */
+#define FLT_MIN_10_EXP -37 /* ceil(log10(b**(emin-1))) */
+#define FLT_MAX_EXP 128 /* emax */
+#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */
+#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */
+
+#define DBL_MANT_DIG 53
+#define DBL_EPSILON 2.2204460492503131E-16
+#define DBL_DIG 15
+#define DBL_MIN_EXP -1021
+#define DBL_MIN 2.225073858507201E-308
+#define DBL_MIN_10_EXP -307
+#define DBL_MAX_EXP 1024
+#define DBL_MAX 1.797693134862316E+308
+#define DBL_MAX_10_EXP 308
+
+#define LDBL_MANT_DIG DBL_MANT_DIG
+#define LDBL_EPSILON DBL_EPSILON
+#define LDBL_DIG DBL_DIG
+#define LDBL_MIN_EXP DBL_MIN_EXP
+#define LDBL_MIN DBL_MIN
+#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+#define LDBL_MAX_EXP DBL_MAX_EXP
+#define LDBL_MAX DBL_MAX
+#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
+
+#endif /* _PMAX_FLOAT_H_ */
diff --git a/sys/arch/arc/include/ieeefp.h b/sys/arch/arc/include/ieeefp.h
new file mode 100644
index 00000000000..898094c474a
--- /dev/null
+++ b/sys/arch/arc/include/ieeefp.h
@@ -0,0 +1,25 @@
+/* $OpenBSD: ieeefp.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 11, 1995
+ * Public domain.
+ */
+
+#ifndef _MIPS_IEEEFP_H_
+#define _MIPS_IEEEFP_H_
+
+typedef int fp_except;
+#define FP_X_IMP 0x01 /* imprecise (loss of precision) */
+#define FP_X_UFL 0x02 /* underflow exception */
+#define FP_X_OFL 0x04 /* overflow exception */
+#define FP_X_DZ 0x08 /* divide-by-zero exception */
+#define FP_X_INV 0x10 /* invalid operation exception */
+
+typedef enum {
+ FP_RN=0, /* round to nearest representable number */
+ FP_RZ=1, /* round to zero (truncate) */
+ FP_RP=2, /* round toward positive infinity */
+ FP_RM=3 /* round toward negative infinity */
+} fp_rnd;
+
+#endif /* _MIPS_IEEEFP_H_ */
diff --git a/sys/arch/arc/include/intr.h b/sys/arch/arc/include/intr.h
new file mode 100644
index 00000000000..67e7ad75ff1
--- /dev/null
+++ b/sys/arch/arc/include/intr.h
@@ -0,0 +1,164 @@
+/* $NetBSD: intr.h,v 1.5 1996/05/13 06:11:28 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ARC_INTR_H_
+#define _ARC_INTR_H_
+
+/* Interrupt priority `levels'; not mutually exclusive. */
+#define IPL_BIO 0 /* block I/O */
+#define IPL_NET 1 /* network */
+#define IPL_TTY 2 /* terminal */
+#define IPL_CLOCK 3 /* clock */
+#define IPL_IMP 4 /* memory allocation */
+#define IPL_NONE 5 /* nothing */
+#define IPL_HIGH 6 /* everything */
+
+/* Interrupt sharing types. */
+#define IST_NONE 0 /* none */
+#define IST_PULSE 1 /* pulsed */
+#define IST_EDGE 2 /* edge-triggered */
+#define IST_LEVEL 3 /* level-triggered */
+
+/* Soft interrupt masks. */
+#define SIR_CLOCK 31
+#define SIR_CLOCKMASK ((1 << SIR_CLOCK))
+#define SIR_NET 30
+#define SIR_NETMASK ((1 << SIR_NET) | SIR_CLOCKMASK)
+#define SIR_TTY 29
+#define SIR_TTYMASK ((1 << SIR_TTY) | SIR_CLOCKMASK)
+#define SIR_ALLMASK (SIR_CLOCKMASK | SIR_NETMASK | SIR_TTYMASK)
+
+#ifndef _LOCORE
+
+volatile int cpl, ipending, astpending;
+int imask[7];
+
+#if 0
+extern void Xspllower __P((void));
+
+static __inline int splraise __P((int));
+static __inline int spllower __P((int));
+static __inline void splx __P((int));
+static __inline void softintr __P((int));
+
+/*
+ * Add a mask to cpl, and return the old value of cpl.
+ */
+static __inline int
+splraise(ncpl)
+ register int ncpl;
+{
+ register int ocpl = cpl;
+
+ cpl = ocpl | ncpl;
+ return (ocpl);
+}
+
+/*
+ * Restore a value to cpl (unmasking interrupts). If any unmasked
+ * interrupts are pending, call Xspllower() to process them.
+ */
+static __inline void
+splx(ncpl)
+ register int ncpl;
+{
+
+ cpl = ncpl;
+ if (ipending & ~ncpl)
+ Xspllower();
+}
+
+/*
+ * Same as splx(), but we return the old value of spl, for the
+ * benefit of some splsoftclock() callers.
+ */
+static __inline int
+spllower(ncpl)
+ register int ncpl;
+{
+ register int ocpl = cpl;
+
+ cpl = ncpl;
+ if (ipending & ~ncpl)
+ Xspllower();
+ return (ocpl);
+}
+#endif
+
+/*
+ * Hardware interrupt masks
+ */
+#if 0
+#define splbio() splraise(imask[IPL_BIO])
+#define splnet() splraise(imask[IPL_NET])
+#define spltty() splraise(imask[IPL_TTY])
+#define splclock() splraise(imask[IPL_CLOCK])
+#define splimp() splraise(imask[IPL_IMP])
+#define splstatclock() splclock()
+
+/*
+ * Software interrupt masks
+ *
+ * NOTE: splsoftclock() is used by hardclock() to lower the priority from
+ * clock to softclock before it calls softclock().
+ */
+#define splsoftclock() spllower(SIR_CLOCKMASK)
+#define splsoftnet() splraise(SIR_NETMASK)
+#define splsofttty() splraise(SIR_TTYMASK)
+
+/*
+ * Miscellaneous
+ */
+#define splhigh() splraise(-1)
+#define spl0() spllower(0)
+
+#endif
+/*
+ * Software interrupt registration
+ *
+ * We hand-code this to ensure that it's atomic.
+ */
+static __inline void
+softintr(mask)
+ register int mask;
+{
+
+ __asm __volatile("orl %0,_ipending" : : "ir" (mask));
+}
+
+#define setsoftast() (astpending = 1)
+#define setsoftclock() softintr(1 << SIR_CLOCK)
+#define setsoftnet() softintr(1 << SIR_NET)
+#define setsofttty() softintr(1 << SIR_TTY)
+
+#endif /* _LOCORE */
+
+#endif /* _ARC_INTR_H_ */
diff --git a/sys/arch/arc/include/kbdreg.h b/sys/arch/arc/include/kbdreg.h
new file mode 100644
index 00000000000..36f7c430398
--- /dev/null
+++ b/sys/arch/arc/include/kbdreg.h
@@ -0,0 +1,53 @@
+/* $OpenBSD: kbdreg.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+
+/*
+ * Keyboard definitions
+ *
+ */
+
+#define KBSTATP (PICA_SYS_KBD + 0x61) /* controller status port (I) */
+#define KBS_DIB 0x01 /* data in buffer */
+#define KBS_IBF 0x02 /* input buffer low */
+#define KBS_WARM 0x04 /* input buffer low */
+#define KBS_OCMD 0x08 /* output buffer has command */
+#define KBS_NOSEC 0x10 /* security lock not engaged */
+#define KBS_TERR 0x20 /* transmission error */
+#define KBS_RERR 0x40 /* receive error */
+#define KBS_PERR 0x80 /* parity error */
+
+#define KBCMDP (PICA_SYS_KBD + 0x61) /* controller port (O) */
+#define KBDATAP (PICA_SYS_KBD + 0x60) /* data port (I) */
+#define KBOUTP (PICA_SYS_KBD + 0x60) /* data port (O) */
+
+#define K_RDCMDBYTE 0x20
+#define K_LDCMDBYTE 0x60
+
+#define KC8_TRANS 0x40 /* convert to old scan codes */
+#define KC8_MDISABLE 0x20 /* disable mouse */
+#define KC8_KDISABLE 0x10 /* disable keyboard */
+#define KC8_IGNSEC 0x08 /* ignore security lock */
+#define KC8_CPU 0x04 /* exit from protected mode reset */
+#define KC8_MENABLE 0x02 /* enable mouse interrupt */
+#define KC8_KENABLE 0x01 /* enable keyboard interrupt */
+#define CMDBYTE (KC8_TRANS|KC8_CPU|KC8_MENABLE|KC8_KENABLE)
+
+/* keyboard commands */
+#define KBC_RESET 0xFF /* reset the keyboard */
+#define KBC_RESEND 0xFE /* request the keyboard resend the last byte */
+#define KBC_SETDEFAULT 0xF6 /* resets keyboard to its power-on defaults */
+#define KBC_DISABLE 0xF5 /* as per KBC_SETDEFAULT, but also disable key scanning */
+#define KBC_ENABLE 0xF4 /* enable key scanning */
+#define KBC_TYPEMATIC 0xF3 /* set typematic rate and delay */
+#define KBC_SETTABLE 0xF0 /* set scancode translation table */
+#define KBC_MODEIND 0xED /* set mode indicators (i.e. LEDs) */
+#define KBC_ECHO 0xEE /* request an echo from the keyboard */
+
+/* keyboard responses */
+#define KBR_EXTENDED 0xE0 /* extended key sequence */
+#define KBR_RESEND 0xFE /* needs resend of command */
+#define KBR_ACK 0xFA /* received a valid command */
+#define KBR_OVERRUN 0x00 /* flooded */
+#define KBR_FAILURE 0xFD /* diagnosic failure */
+#define KBR_BREAK 0xF0 /* break code prefix - sent on key release */
+#define KBR_RSTDONE 0xAA /* reset complete */
+#define KBR_ECHO 0xEE /* echo response */
diff --git a/sys/arch/arc/include/kcore.h b/sys/arch/arc/include/kcore.h
new file mode 100644
index 00000000000..ce62986fe0e
--- /dev/null
+++ b/sys/arch/arc/include/kcore.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: kcore.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: kcore.h,v 1.1 1996/03/10 21:55:18 leo Exp $ */
+
+/*
+ * Copyright (c) 1996 Leo Weppelman.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MIPS_KCORE_H_
+#define _MIPS_KCORE_H_
+
+#define NPHYS_RAM_SEGS 8
+
+typedef struct cpu_kcore_hdr {
+ vm_offset_t kernel_pa; /* Phys. address of kernel VA 0 */
+ int mmutype;
+ phys_ram_seg_t ram_segs[NPHYS_RAM_SEGS];
+} cpu_kcore_hdr_t;
+
+#endif /* _MIPS_KCORE_H_ */
diff --git a/sys/arch/arc/include/kdbparam.h b/sys/arch/arc/include/kdbparam.h
new file mode 100644
index 00000000000..511ab733778
--- /dev/null
+++ b/sys/arch/arc/include/kdbparam.h
@@ -0,0 +1,75 @@
+/* $OpenBSD: kdbparam.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: kdbparam.h,v 1.4 1994/10/26 21:09:42 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)kdbparam.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine dependent definitions for kdb.
+ */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define kdbshorten(w) ((w) & 0xFFFF)
+#define kdbbyte(w) ((w) & 0xFF)
+#define kdbitol(a,b) ((long)(((b) << 16) | ((a) & 0xFFFF)))
+#define kdbbtol(a) ((long)(a))
+#endif
+
+#define LPRMODE "%R"
+#define OFFMODE "+%R"
+
+#define SETBP(ins) BREAK_BRKPT
+
+/* return the program counter value modified if we are in a delay slot */
+#define kdbgetpc(pcb) (kdbvar[kdbvarchk('t')] < 0 ? \
+ (pcb).pcb_regs[34] + 4 : (pcb).pcb_regs[34])
+#define kdbishiddenreg(p) ((p) >= &kdbreglist[33])
+#define kdbisbreak(type) (((type) & CR_EXC_CODE) == 0x24)
+
+/* check for address wrap around */
+#define kdbaddrwrap(addr,newaddr) (((addr)^(newaddr)) >> 31)
+
+/* declare machine dependent routines defined in kadb.c */
+void kdbprinttrap __P((unsigned, unsigned));
+void kdbsetsstep __P((void));
+void kdbclrsstep __P((void));
+void kdbreadc __P((char *));
+void kdbwrite __P((char *, int));
+void kdbprintins __P((int, long));
+void kdbstacktrace __P((int));
+char *kdbmalloc __P((int));
diff --git a/sys/arch/arc/include/limits.h b/sys/arch/arc/include/limits.h
new file mode 100644
index 00000000000..92211965129
--- /dev/null
+++ b/sys/arch/arc/include/limits.h
@@ -0,0 +1,101 @@
+/* $OpenBSD: limits.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: limits.h,v 1.8 1995/03/28 18:19:16 jtc Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)limits.h 8.3 (Berkeley) 1/4/94
+ */
+
+#define CHAR_BIT 8 /* number of bits in a char */
+#define MB_LEN_MAX 6 /* Allow 31 bit UTF2 */
+
+#ifdef _KERNEL
+#define CLK_TCK 100 /* ticks per second */
+#endif
+
+/*
+ * According to ANSI (section 2.2.4.2), the values below must be usable by
+ * #if preprocessing directives. Additionally, the expression must have the
+ * same type as would an expression that is an object of the corresponding
+ * type converted according to the integral promotions. The subtraction for
+ * INT_MIN and LONG_MIN is so the value is not unsigned; 2147483648 is an
+ * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2).
+ * These numbers work for pcc as well. The UINT_MAX and ULONG_MAX values
+ * are written as hex so that GCC will be quiet about large integer constants.
+ */
+#define SCHAR_MAX 127 /* min value for a signed char */
+#define SCHAR_MIN (-128) /* max value for a signed char */
+
+#define UCHAR_MAX 255 /* max value for an unsigned char */
+#define CHAR_MAX 127 /* max value for a char */
+#define CHAR_MIN (-128) /* min value for a char */
+
+#define USHRT_MAX 65535 /* max value for an unsigned short */
+#define SHRT_MAX 32767 /* max value for a short */
+#define SHRT_MIN (-32768) /* min value for a short */
+
+#define UINT_MAX 0xffffffff /* max value for an unsigned int */
+#define INT_MAX 2147483647 /* max value for an int */
+#define INT_MIN (-2147483647-1) /* min value for an int */
+
+#define ULONG_MAX 0xffffffff /* max value for an unsigned long */
+#define LONG_MAX 2147483647 /* max value for a long */
+#define LONG_MIN (-2147483647-1) /* min value for a long */
+
+#if !defined(_ANSI_SOURCE)
+#define SSIZE_MAX INT_MAX /* max value for a ssize_t */
+
+#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
+#define SIZE_T_MAX UINT_MAX /* max value for a size_t */
+
+/* GCC requires that quad constants be written as expressions. */
+#define UQUAD_MAX ((u_quad_t)0-1) /* max value for a uquad_t */
+ /* max value for a quad_t */
+#define QUAD_MAX ((quad_t)(UQUAD_MAX >> 1))
+#define QUAD_MIN (-QUAD_MAX-1) /* min value for a quad_t */
+
+#endif /* !_POSIX_SOURCE && !_XOPEN_SOURCE */
+#endif /* !_ANSI_SOURCE */
+
+#if (!defined(_ANSI_SOURCE)&&!defined(_POSIX_SOURCE)) || defined(_XOPEN_SOURCE)
+#define LONG_BIT 32
+#define WORD_BIT 32
+
+#define DBL_DIG 15
+#define DBL_MAX 1.797693134862316E+308
+#define DBL_MIN 2.225073858507201E-308
+
+#define FLT_DIG 6
+#define FLT_MAX 3.40282347E+38F
+#define FLT_MIN 1.17549435E-38F
+#endif
diff --git a/sys/arch/arc/include/mips_opcode.h b/sys/arch/arc/include/mips_opcode.h
new file mode 100644
index 00000000000..5af5668d88c
--- /dev/null
+++ b/sys/arch/arc/include/mips_opcode.h
@@ -0,0 +1,260 @@
+/* $OpenBSD: mips_opcode.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)mips_opcode.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Define the instruction formats and opcode values for the
+ * MIPS instruction set.
+ */
+
+/*
+ * Define the instruction formats.
+ */
+typedef union {
+ unsigned word;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ struct {
+ unsigned imm: 16;
+ unsigned rt: 5;
+ unsigned rs: 5;
+ unsigned op: 6;
+ } IType;
+
+ struct {
+ unsigned target: 26;
+ unsigned op: 6;
+ } JType;
+
+ struct {
+ unsigned func: 6;
+ unsigned shamt: 5;
+ unsigned rd: 5;
+ unsigned rt: 5;
+ unsigned rs: 5;
+ unsigned op: 6;
+ } RType;
+
+ struct {
+ unsigned func: 6;
+ unsigned fd: 5;
+ unsigned fs: 5;
+ unsigned ft: 5;
+ unsigned fmt: 4;
+ unsigned : 1; /* always '1' */
+ unsigned op: 6; /* always '0x11' */
+ } FRType;
+#endif
+} InstFmt;
+
+/*
+ * Values for the 'op' field.
+ */
+#define OP_SPECIAL 000
+#define OP_BCOND 001
+#define OP_J 002
+#define OP_JAL 003
+#define OP_BEQ 004
+#define OP_BNE 005
+#define OP_BLEZ 006
+#define OP_BGTZ 007
+
+#define OP_ADDI 010
+#define OP_ADDIU 011
+#define OP_SLTI 012
+#define OP_SLTIU 013
+#define OP_ANDI 014
+#define OP_ORI 015
+#define OP_XORI 016
+#define OP_LUI 017
+
+#define OP_COP0 020
+#define OP_COP1 021
+#define OP_COP2 022
+#define OP_COP3 023
+#define OP_BEQL 024
+#define OP_BNEL 025
+#define OP_BLEZL 026
+#define OP_BGTZL 027
+
+#define OP_DADDI 030
+#define OP_DADDIU 031
+#define OP_LDL 032
+#define OP_LDR 033
+
+#define OP_LB 040
+#define OP_LH 041
+#define OP_LWL 042
+#define OP_LW 043
+#define OP_LBU 044
+#define OP_LHU 045
+#define OP_LWR 046
+#define OP_LHU 045
+#define OP_LWR 046
+#define OP_LWU 047
+
+#define OP_SB 050
+#define OP_SH 051
+#define OP_SWL 052
+#define OP_SW 053
+#define OP_SDL 054
+#define OP_SDR 055
+#define OP_SWR 056
+#define OP_CACHE 057
+
+#define OP_LL 060
+#define OP_LWC1 061
+#define OP_LWC2 062
+#define OP_LWC3 063
+#define OP_LLD 064
+#define OP_LD 067
+
+#define OP_SC 070
+#define OP_SWC1 071
+#define OP_SWC2 072
+#define OP_SWC3 073
+#define OP_SCD 074
+#define OP_SD 077
+
+/*
+ * Values for the 'func' field when 'op' == OP_SPECIAL.
+ */
+#define OP_SLL 000
+#define OP_SRL 002
+#define OP_SRA 003
+#define OP_SLLV 004
+#define OP_SRLV 006
+#define OP_SRAV 007
+
+#define OP_JR 010
+#define OP_JALR 011
+#define OP_SYSCALL 014
+#define OP_BREAK 015
+#define OP_SYNC 017
+
+#define OP_MFHI 020
+#define OP_MTHI 021
+#define OP_MFLO 022
+#define OP_MTLO 023
+#define OP_DSLLV 024
+#define OP_DSRLV 026
+#define OP_DSRAV 027
+
+#define OP_MULT 030
+#define OP_MULTU 031
+#define OP_DIV 032
+#define OP_DIVU 033
+#define OP_DMULT 034
+#define OP_DMULTU 035
+#define OP_DDIV 036
+#define OP_DDIVU 037
+
+
+#define OP_ADD 040
+#define OP_ADDU 041
+#define OP_SUB 042
+#define OP_SUBU 043
+#define OP_AND 044
+#define OP_OR 045
+#define OP_XOR 046
+#define OP_NOR 047
+
+#define OP_SLT 052
+#define OP_SLTU 053
+#define OP_DADD 054
+#define OP_DADDU 055
+#define OP_DSUB 056
+#define OP_DSUBU 057
+
+#define OP_TGE 060
+#define OP_TGEU 061
+#define OP_TLT 062
+#define OP_TLTU 063
+#define OP_TEQ 064
+#define OP_TNE 066
+
+#define OP_DSLL 070
+#define OP_DSRL 072
+#define OP_DSRA 073
+#define OP_DSLL32 074
+#define OP_DSRL32 076
+#define OP_DSRA32 077
+
+/*
+ * Values for the 'func' field when 'op' == OP_BCOND.
+ */
+#define OP_BLTZ 000
+#define OP_BGEZ 001
+#define OP_BLTZL 002
+#define OP_BGEZL 003
+
+#define OP_TGEI 010
+#define OP_TGEIU 011
+#define OP_TLTI 012
+#define OP_TLTIU 013
+#define OP_TEQI 014
+#define OP_TNEI 016
+
+#define OP_BLTZAL 020
+#define OP_BLTZAL 020
+#define OP_BGEZAL 021
+#define OP_BLTZALL 022
+#define OP_BGEZALL 023
+
+/*
+ * Values for the 'rs' field when 'op' == OP_COPz.
+ */
+#define OP_MF 000
+#define OP_DMF 001
+#define OP_MT 004
+#define OP_DMT 005
+#define OP_BCx 010
+#define OP_BCy 014
+#define OP_CF 002
+#define OP_CT 006
+
+/*
+ * Values for the 'rt' field when 'op' == OP_COPz.
+ */
+#define COPz_BC_TF_MASK 0x01
+#define COPz_BC_TRUE 0x01
+#define COPz_BC_FALSE 0x00
+#define COPz_BCL_TF_MASK 0x02
+#define COPz_BCL_TRUE 0x02
+#define COPz_BCL_FALSE 0x00
diff --git a/sys/arch/arc/include/mouse.h b/sys/arch/arc/include/mouse.h
new file mode 100644
index 00000000000..29d4423f83b
--- /dev/null
+++ b/sys/arch/arc/include/mouse.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: mouse.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: mouse.h,v 1.4 1994/10/27 04:16:10 cgd Exp $ */
+
+/*-
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 _MOUSE_H_
+#define _MOUSE_H_
+
+struct mouseinfo {
+ unsigned char status;
+ char xmotion, ymotion;
+};
+
+#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 */
+
+/* Ioctl definitions */
+
+#define MOUSEIOC ('M'<<8)
+#define MOUSEIOCREAD (MOUSEIOC|60)
+
+#endif /* !_MOUSE_H_ */
diff --git a/sys/arch/arc/include/param.h b/sys/arch/arc/include/param.h
new file mode 100644
index 00000000000..a24f4b327c4
--- /dev/null
+++ b/sys/arch/arc/include/param.h
@@ -0,0 +1,166 @@
+/* $OpenBSD: param.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: machparam.h 1.11 89/08/14
+ * from: @(#)param.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine dependent constants for Acer Labs PICA_61.
+ */
+#define MACHINE "arc"
+#define MACHINE_ARCH "mips"
+#define MID_PICA MID_PMAX /* For the moment */
+#define MID_MACHINE MID_PICA
+
+/*
+ * Round p (pointer or byte index) up to a correctly-aligned value for all
+ * data types (int, long, ...). The result is u_int and must be cast to
+ * any desired pointer type.
+ */
+#define ALIGNBYTES 7
+#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+
+#define NBPG 4096 /* bytes/page */
+#define PGOFSET (NBPG-1) /* byte offset into page */
+#define PGSHIFT 12 /* LOG2(NBPG) */
+#define NPTEPG (NBPG/4)
+
+#define NBSEG 0x400000 /* bytes/segment */
+#define SEGOFSET (NBSEG-1) /* byte offset into segment */
+#define SEGSHIFT 22 /* LOG2(NBSEG) */
+
+#define KERNBASE 0x80000000 /* start of kernel virtual */
+#define KERNTEXTOFF 0x80080000 /* start of kernel text for kvm_mkdb */
+#define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT)
+
+#define DEV_BSIZE 512
+#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
+#define BLKDEV_IOSIZE 2048
+#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */
+
+#define CLSIZE 1
+#define CLSIZELOG2 0
+
+/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */
+#define SSIZE 1 /* initial stack size/NBPG */
+#define SINCR 1 /* increment of stack/NBPG */
+
+#define UPAGES 2 /* pages of u-area */
+#define UADDR 0xffffc000 /* address of u */
+#define USPACE (UPAGES*NBPG) /* size of u-area in bytes */
+#define UVPN (UADDR>>PGSHIFT)/* virtual page number of u */
+#define KERNELSTACK (UADDR+UPAGES*NBPG) /* top of kernel stack */
+
+/*
+ * Constants related to network buffer management.
+ * MCLBYTES must be no larger than CLBYTES (the software page size), and,
+ * on machines that exchange pages of input or output buffers with mbuf
+ * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple
+ * of the hardware page size.
+ */
+#define MSIZE 128 /* size of an mbuf */
+#define MCLBYTES 2048 /* enough for whole Ethernet packet */
+#define MCLSHIFT 10
+#define MCLOFSET (MCLBYTES - 1)
+#ifndef NMBCLUSTERS
+#ifdef GATEWAY
+#define NMBCLUSTERS 2048 /* map size, max cluster allocation */
+#else
+#define NMBCLUSTERS 1024 /* map size, max cluster allocation */
+#endif
+#endif
+
+/*
+ * Size of kernel malloc arena in CLBYTES-sized logical pages
+ */
+#ifndef NKMEMCLUSTERS
+#define NKMEMCLUSTERS (512*1024/CLBYTES)
+#endif
+
+/* pages ("clicks") (4096 bytes) to disk blocks */
+#define ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT))
+#define dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT))
+
+/* pages to bytes */
+#define ctob(x) ((x) << PGSHIFT)
+#define btoc(x) (((x) + PGOFSET) >> PGSHIFT)
+
+/* bytes to disk blocks */
+#define btodb(x) ((x) >> DEV_BSHIFT)
+#define dbtob(x) ((x) << DEV_BSHIFT)
+
+/*
+ * Map a ``block device block'' to a file system block.
+ * This should be device dependent, and should use the bsize
+ * field from the disk label.
+ * For now though just use DEV_BSIZE.
+ */
+#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE/DEV_BSIZE))
+
+/*
+ * Mach derived conversion macros
+ */
+#define pica_round_page(x) ((((unsigned)(x)) + NBPG - 1) & ~(NBPG-1))
+#define pica_trunc_page(x) ((unsigned)(x) & ~(NBPG-1))
+#define pica_btop(x) ((unsigned)(x) >> PGSHIFT)
+#define pica_ptob(x) ((unsigned)(x) << PGSHIFT)
+
+#ifdef _KERNEL
+#ifndef _LOCORE
+extern int (*Mach_splnet)(), (*Mach_splbio)(), (*Mach_splimp)(),
+ (*Mach_spltty)(), (*Mach_splclock)(), (*Mach_splstatclock)();
+#define splnet() ((*Mach_splnet)())
+#define splbio() ((*Mach_splbio)())
+#define splimp() ((*Mach_splimp)())
+#define spltty() ((*Mach_spltty)())
+#define splclock() ((*Mach_splclock)())
+#define splstatclock() ((*Mach_splstatclock)())
+
+/*
+ * Delay is based on an assumtion that each time in the loop
+ * takes 3 clocks. Three is for branch and subtract in the delay slot.
+ */
+extern int cpuspeed;
+#define DELAY(n) { register int N = cpuspeed * (n); while ((N -= 3) > 0); }
+#endif
+
+#else /* !_KERNEL */
+#define DELAY(n) { register int N = (n); while (--N > 0); }
+#endif /* !_KERNEL */
diff --git a/sys/arch/arc/include/pcb.h b/sys/arch/arc/include/pcb.h
new file mode 100644
index 00000000000..8181602c1ab
--- /dev/null
+++ b/sys/arch/arc/include/pcb.h
@@ -0,0 +1,61 @@
+/* $OpenBSD: pcb.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: pcb.h 1.13 89/04/23
+ * from: @(#)pcb.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * PICA process control block
+ */
+struct pcb
+{
+ int pcb_regs[71]; /* saved CPU and floating point registers */
+ label_t pcb_context; /* kernel context for resume */
+ int pcb_onfault; /* for copyin/copyout faults */
+ void *pcb_segtab; /* copy of pmap pm_segtab */
+};
+
+/*
+ * The pcb is augmented with machine-dependent additional data for
+ * core dumps. For the PICA, there is nothing to add.
+ */
+struct md_coredump {
+ long md_pad[8];
+};
diff --git a/sys/arch/arc/include/pccons.h b/sys/arch/arc/include/pccons.h
new file mode 100644
index 00000000000..df988c0da17
--- /dev/null
+++ b/sys/arch/arc/include/pccons.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: pccons.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: pccons.h,v 1.4 1996/02/02 18:06:06 mycroft Exp $ */
+
+/*
+ * pccons.h -- pccons ioctl definitions
+ */
+
+#ifndef _PCCONS_H_
+#define _PCCONS_H_
+
+#include <sys/ioctl.h>
+
+/* key types -- warning: pccons.c depends on most values */
+
+#define KB_SCROLL 0x0001 /* stop output */
+#define KB_NUM 0x0002 /* numeric shift cursors vs. numeric */
+#define KB_CAPS 0x0004 /* caps shift -- swaps case of letter */
+#define KB_SHIFT 0x0008 /* keyboard shift */
+#define KB_CTL 0x0010 /* control shift -- allows ctl function */
+#define KB_ASCII 0x0020 /* ascii code for this key */
+#define KB_ALTGR 0x0040 /* alternate graphics shift */
+#define KB_ALT 0x0080 /* alternate shift -- alternate chars */
+#define KB_FUNC 0x0100 /* function key */
+#define KB_KP 0x0200 /* Keypad keys */
+#define KB_NONE 0x0400 /* no function */
+
+#define KB_CODE_SIZE 4 /* Use a max of 4 for now... */
+#define KB_NUM_KEYS 128 /* Number of scan codes */
+typedef struct {
+ u_short type;
+ char unshift[KB_CODE_SIZE];
+ char shift[KB_CODE_SIZE];
+ char ctl[KB_CODE_SIZE];
+ char altgr[KB_CODE_SIZE];
+ char shift_altgr[KB_CODE_SIZE];
+} keymap_t;
+
+#define CONSOLE_X_MODE_ON _IO('t',121)
+#define CONSOLE_X_MODE_OFF _IO('t',122)
+#define CONSOLE_X_BELL _IOW('t',123,int[2])
+#define CONSOLE_SET_TYPEMATIC_RATE _IOW('t',124,u_char)
+#define CONSOLE_GET_KEYMAP _IOR('t',128,keymap_t[KB_NUM_KEYS])
+#define CONSOLE_SET_KEYMAP _IOW('t',129,keymap_t[KB_NUM_KEYS])
+
+#endif /* _PCCONS_H_ */
diff --git a/sys/arch/arc/include/pio.h b/sys/arch/arc/include/pio.h
new file mode 100644
index 00000000000..04db5b11f34
--- /dev/null
+++ b/sys/arch/arc/include/pio.h
@@ -0,0 +1,46 @@
+/* $OpenBSD: pio.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+
+/*
+ * Copyright (c) 1995 Per Fogelstrom. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by 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.
+ */
+
+/*
+ * I/O macros.
+ */
+
+#define outb(a,v) (*(volatile unsigned char*)(a) = (v))
+#define outw(a,v) (*(volatile unsigned short*)(a) = (v))
+#define out16(a,v) outw(a,v)
+#define outl(a,v) (*(volatile unsigned int*)(a) = (v))
+#define out32(a,v) outl(a,v)
+#define inb(a) (*(volatile unsigned char*)(a))
+#define inw(a) (*(volatile unsigned short*)(a))
+#define in16(a) inw(a)
+#define inl(a) (*(volatile unsigned int*)(a))
+#define in32(a) inl(a)
+
diff --git a/sys/arch/arc/include/pmap.h b/sys/arch/arc/include/pmap.h
new file mode 100644
index 00000000000..6582b7b13ba
--- /dev/null
+++ b/sys/arch/arc/include/pmap.h
@@ -0,0 +1,109 @@
+/* $OpenBSD: pmap.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+
+/*
+ * Copyright (c) 1987 Carnegie-Mellon University
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)pmap.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _PMAP_MACHINE_
+#define _PMAP_MACHINE_
+
+/*
+ * The user address space is 2Gb (0x0 - 0x80000000).
+ * User programs are laid out in memory as follows:
+ * address
+ * USRTEXT 0x00001000
+ * USRDATA USRTEXT + text_size
+ * USRSTACK 0x7FFFFFFF
+ *
+ * The user address space is mapped using a two level structure where
+ * virtual address bits 30..22 are used to index into a segment table which
+ * points to a page worth of PTEs (4096 page can hold 1024 PTEs).
+ * Bits 21..12 are then used to index a PTE which describes a page within
+ * a segment.
+ *
+ * The wired entries in the TLB will contain the following:
+ * 0-1 (UPAGES) for curproc user struct and kernel stack.
+ *
+ * Note: The kernel doesn't use the same data structures as user programs.
+ * All the PTE entries are stored in a single array in Sysmap which is
+ * dynamically allocated at boot time.
+ */
+
+#define pica_trunc_seg(x) ((vm_offset_t)(x) & ~SEGOFSET)
+#define pica_round_seg(x) (((vm_offset_t)(x) + SEGOFSET) & ~SEGOFSET)
+#define pmap_segmap(m, v) ((m)->pm_segtab->seg_tab[((v) >> SEGSHIFT)])
+
+#define PMAP_SEGTABSIZE 512
+
+union pt_entry;
+
+struct segtab {
+ union pt_entry *seg_tab[PMAP_SEGTABSIZE];
+};
+
+/*
+ * Machine dependent pmap structure.
+ */
+typedef struct pmap {
+ int pm_count; /* pmap reference count */
+ simple_lock_data_t pm_lock; /* lock on pmap */
+ struct pmap_statistics pm_stats; /* pmap statistics */
+ int pm_tlbpid; /* address space tag */
+ u_int pm_tlbgen; /* TLB PID generation number */
+ struct segtab *pm_segtab; /* pointers to pages of PTEs */
+} *pmap_t;
+
+/*
+ * Defines for pmap_attributes[phys_mach_page];
+ */
+#define PMAP_ATTR_MOD 0x01 /* page has been modified */
+#define PMAP_ATTR_REF 0x02 /* page has been referenced */
+
+#ifdef _KERNEL
+extern char *pmap_attributes; /* reference and modify bits */
+extern struct pmap kernel_pmap_store;
+
+#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
+#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count)
+#define pmap_kernel() (&kernel_pmap_store)
+
+#define PMAP_PREFER(pa, va) pmap_prefer((pa), (va))
+
+#endif /* _KERNEL */
+
+#endif /* _PMAP_MACHINE_ */
diff --git a/sys/arch/arc/include/proc.h b/sys/arch/arc/include/proc.h
new file mode 100644
index 00000000000..b9b2b81c76d
--- /dev/null
+++ b/sys/arch/arc/include/proc.h
@@ -0,0 +1,54 @@
+/* $OpenBSD: proc.h,v 1.1 1996/06/24 09:07:17 pefo Exp $ */
+/* $NetBSD: proc.h,v 1.4 1994/10/26 21:09:52 cgd Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)proc.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine-dependent part of the proc structure for DEC Station.
+ */
+struct mdproc {
+ int *md_regs; /* registers on current frame */
+ int md_flags; /* machine-dependent flags */
+ int md_upte[UPAGES]; /* ptes for mapping u page */
+ int md_ss_addr; /* single step address for ptrace */
+ int md_ss_instr; /* single step instruction for ptrace */
+};
+
+/* md_flags */
+#define MDP_FPUSED 0x0001 /* floating point coprocessor used */
diff --git a/sys/arch/arc/include/profile.h b/sys/arch/arc/include/profile.h
new file mode 100644
index 00000000000..911da1370f9
--- /dev/null
+++ b/sys/arch/arc/include/profile.h
@@ -0,0 +1,79 @@
+/* $OpenBSD: profile.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)profile.h 8.1 (Berkeley) 6/10/93
+ */
+
+#define _MCOUNT_DECL static void ___mcount
+
+#define MCOUNT \
+ __asm(".globl _mcount;" \
+ "_mcount:;" \
+ ".set noreorder;" \
+ ".set noat;" \
+ "sw $4,8($29);" \
+ "sw $5,12($29);" \
+ "sw $6,16($29);" \
+ "sw $7,20($29);" \
+ "sw $1,0($29);" \
+ "sw $31,4($29);" \
+ "move $5,$31;" \
+ "jal ___mcount;" \
+ "move $4,$1;" \
+ "lw $4,8($29);" \
+ "lw $5,12($29);" \
+ "lw $6,16($29);" \
+ "lw $7,20($29);" \
+ "lw $31,4($29);" \
+ "lw $1,0($29);" \
+ "addu $29,$29,8;" \
+ "j $31;" \
+ "move $31,$1;" \
+ ".set reorder;" \
+ ".set at");
+
+#ifdef _KERNEL
+/*
+ * The following two macros do splhigh and splx respectively.
+ * They have to be defined this way because these are real
+ * functions on the PICA, and we do not want to invoke mcount
+ * recursively.
+ */
+#define MCOUNT_ENTER s = _splhigh()
+
+#define MCOUNT_EXIT _splx(s)
+#endif /* _KERNEL */
diff --git a/sys/arch/arc/include/psl.h b/sys/arch/arc/include/psl.h
new file mode 100644
index 00000000000..e1109ebbb54
--- /dev/null
+++ b/sys/arch/arc/include/psl.h
@@ -0,0 +1,69 @@
+/* $OpenBSD: psl.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)psl.h 8.1 (Berkeley) 6/10/93
+ */
+
+#include <machine/cpu.h>
+
+#define PSL_LOWIPL (INT_MASK | SR_INT_ENAB)
+
+#define PSL_USERSET ( \
+ SR_KSU_USER | \
+ SR_INT_ENAB | \
+ SR_EXL | \
+ INT_MASK)
+
+#define PSL_USERCLR ( \
+ SR_COP_USABILITY | \
+ SR_BOOT_EXC_VEC | \
+ SR_TLB_SHUTDOWN | \
+ SR_PARITY_ERR | \
+ SR_CACHE_MISS | \
+ SR_PARITY_ZERO | \
+ SR_SWAP_CACHES | \
+ SR_ISOL_CACHES | \
+ SR_KU_CUR | \
+ SR_INT_ENA_CUR | \
+ SR_MBZ)
+
+/*
+ * Macros to decode processor status word.
+ */
+#define USERMODE(ps) (((ps) & SR_KSU_MASK) == SR_KSU_USER)
+#define BASEPRI(ps) (((ps) & (INT_MASK | SR_INT_ENA_PREV)) \
+ == (INT_MASK | SR_INT_ENA_PREV))
diff --git a/sys/arch/arc/include/pte.h b/sys/arch/arc/include/pte.h
new file mode 100644
index 00000000000..a5e6ee48054
--- /dev/null
+++ b/sys/arch/arc/include/pte.h
@@ -0,0 +1,134 @@
+/* $OpenBSD: pte.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: pte.h 1.11 89/09/03
+ * from: @(#)pte.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * R4000 hardware page table entry
+ */
+
+#ifndef _LOCORE
+struct pte {
+#if BYTE_ORDER == BIG_ENDIAN
+unsigned int pg_prot:2, /* SW: access control */
+ pg_pfnum:24, /* HW: core page frame number or 0 */
+ pg_attr:3, /* HW: cache attribute */
+ pg_m:1, /* HW: modified (dirty) bit */
+ pg_v:1, /* HW: valid bit */
+ pg_g:1; /* HW: ignore pid bit */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+unsigned int pg_g:1, /* HW: ignore pid bit */
+ pg_v:1, /* HW: valid bit */
+ pg_m:1, /* HW: modified (dirty) bit */
+ pg_attr:3, /* HW: cache attribute */
+ pg_pfnum:24, /* HW: core page frame number or 0 */
+ pg_prot:2; /* SW: access control */
+#endif
+};
+
+/*
+ * Structure defining an tlb entry data set.
+ */
+
+struct tlb {
+ int tlb_mask;
+ int tlb_hi;
+ int tlb_lo0;
+ int tlb_lo1;
+};
+
+typedef union pt_entry {
+ unsigned int pt_entry; /* for copying, etc. */
+ struct pte pt_pte; /* for getting to bits by name */
+} pt_entry_t; /* Mach page table entry */
+#endif /* _LOCORE */
+
+#define PT_ENTRY_NULL ((pt_entry_t *) 0)
+
+#define PG_WIRED 0x80000000 /* SW */
+#define PG_RO 0x40000000 /* SW */
+
+#define PG_SVPN 0xfffff000 /* Software page no mask */
+#define PG_HVPN 0xffffe000 /* Hardware page no mask */
+#define PG_ODDPG 0x00001000 /* Odd even pte entry */
+#define PG_ASID 0x000000ff /* Address space ID */
+#define PG_G 0x00000001 /* HW */
+#define PG_V 0x00000002
+#define PG_NV 0x00000000
+#define PG_M 0x00000004
+#define PG_ATTR 0x0000003f
+#define PG_UNCACHED 0x00000010
+#define PG_CACHED 0x00000018
+#define PG_CACHEMODE 0x00000038
+#define PG_ROPAGE (PG_V | PG_RO | PG_CACHED) /* Write protected */
+#define PG_RWPAGE (PG_V | PG_M | PG_CACHED) /* Not wr-prot not clean */
+#define PG_CWPAGE (PG_V | PG_CACHED) /* Not wr-prot but clean */
+#define PG_IOPAGE (PG_G | PG_V | PG_M | PG_UNCACHED)
+#define PG_FRAME 0x3fffffc0
+#define PG_SHIFT 6
+#define vad_to_pfn(x) (((unsigned)(x) >> PG_SHIFT) & PG_FRAME)
+#define pfn_to_vad(x) (((x) & PG_FRAME) << PG_SHIFT)
+#define vad_to_vpn(x) ((unsigned)(x) & PG_SVPN)
+#define vpn_to_vad(x) ((x) & PG_SVPN)
+/* User viritual to pte page entry */
+#define uvtopte(adr) (((adr) >> PGSHIFT) & (NPTEPG -1))
+
+#define PG_SIZE_4K 0x00000000
+#define PG_SIZE_16K 0x00006000
+#define PG_SIZE_64K 0x0001e000
+#define PG_SIZE_256K 0x0007e000
+#define PG_SIZE_1M 0x001fe000
+#define PG_SIZE_4M 0x007fe000
+#define PG_SIZE_16M 0x01ffe000
+
+#if defined(_KERNEL) && !defined(_LOCORE)
+/*
+ * Kernel virtual address to page table entry and visa versa.
+ */
+#define kvtopte(va) \
+ (Sysmap + (((vm_offset_t)(va) - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT))
+#define ptetokv(pte) \
+ ((((pt_entry_t *)(pte) - Sysmap) << PGSHIFT) + VM_MIN_KERNEL_ADDRESS)
+
+extern pt_entry_t *Sysmap; /* kernel pte table */
+extern u_int Sysmapsize; /* number of pte's in Sysmap */
+#endif
diff --git a/sys/arch/arc/include/ptrace.h b/sys/arch/arc/include/ptrace.h
new file mode 100644
index 00000000000..987d48b285b
--- /dev/null
+++ b/sys/arch/arc/include/ptrace.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: ptrace.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ptrace.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine dependent trace commands.
+ *
+ */
+
+#define PT_GETREGS (PT_FIRSTMACH+0)
+#define PT_SETREGS (PT_FIRSTMACH+1)
+#define PT_STEP (PT_FIRSTMACH+2)
diff --git a/sys/arch/arc/include/reg.h b/sys/arch/arc/include/reg.h
new file mode 100644
index 00000000000..d1a7a2b76e1
--- /dev/null
+++ b/sys/arch/arc/include/reg.h
@@ -0,0 +1,62 @@
+/* $OpenBSD: reg.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: reg.h,v 1.6 1995/12/20 02:00:27 jonathan Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: reg.h 1.1 90/07/09
+ * @(#)reg.h 8.2 (Berkeley) 1/11/94
+ */
+
+#ifndef _MACHINE_REG_H_
+#define _MACHINE_REG_H_
+/*
+ * Location of the users' stored
+ * registers relative to ZERO.
+ * Usage is p->p_regs[XX].
+ *
+ * must be visible to assembly code.
+ */
+#include <machine/regnum.h>
+
+/*
+ * Register set accessible via /proc/$pid/reg
+ */
+struct reg {
+ int r_regs[71]; /* numbered as above */
+};
+#endif /*_MACHINE_REG_H_*/
diff --git a/sys/arch/arc/include/regdef.h b/sys/arch/arc/include/regdef.h
new file mode 100644
index 00000000000..def7c6ef1a1
--- /dev/null
+++ b/sys/arch/arc/include/regdef.h
@@ -0,0 +1,74 @@
+/* $OpenBSD: regdef.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: regdef.h,v 1.4 1994/10/26 21:09:58 cgd Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell. This file is derived from the MIPS RISC
+ * Architecture book by Gerry Kane.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)regdef.h 8.1 (Berkeley) 6/10/93
+ */
+
+#define zero $0 /* always zero */
+#define AT $at /* assembler temp */
+#define v0 $2 /* return value */
+#define v1 $3
+#define a0 $4 /* argument registers */
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define t0 $8 /* temp registers (not saved across subroutine calls) */
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+#define s0 $16 /* saved across subroutine calls (callee saved) */
+#define s1 $17
+#define s2 $18
+#define s3 $19
+#define s4 $20
+#define s5 $21
+#define s6 $22
+#define s7 $23
+#define t8 $24 /* two more temp registers */
+#define t9 $25
+#define k0 $26 /* kernel temporary */
+#define k1 $27
+#define gp $28 /* global pointer */
+#define sp $29 /* stack pointer */
+#define s8 $30 /* one more callee saved */
+#define ra $31 /* return address */
diff --git a/sys/arch/arc/include/regnum.h b/sys/arch/arc/include/regnum.h
new file mode 100644
index 00000000000..b0cc92e6d9b
--- /dev/null
+++ b/sys/arch/arc/include/regnum.h
@@ -0,0 +1,136 @@
+/* $OpenBSD: regnum.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: reg.h,v 1.5 1995/01/18 06:40:12 mellon Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: reg.h 1.1 90/07/09
+ * @(#)reg.h 8.2 (Berkeley) 1/11/94
+ */
+
+/*
+ * Location of the users' stored
+ * registers relative to ZERO.
+ * Usage is p->p_regs[XX].
+ */
+#define ZERO 0
+#define AST 1
+#define V0 2
+#define V1 3
+#define A0 4
+#define A1 5
+#define A2 6
+#define A3 7
+#define T0 8
+#define T1 9
+#define T2 10
+#define T3 11
+#define T4 12
+#define T5 13
+#define T6 14
+#define T7 15
+#define S0 16
+#define S1 17
+#define S2 18
+#define S3 19
+#define S4 20
+#define S5 21
+#define S6 22
+#define S7 23
+#define T8 24
+#define T9 25
+#define K0 26
+#define K1 27
+#define GP 28
+#define SP 29
+#define S8 30
+#define RA 31
+#define SR 32
+#define PS SR /* alias for SR */
+#define MULLO 33
+#define MULHI 34
+#define BADVADDR 35
+#define CAUSE 36
+#define PC 37
+
+#define FPBASE 38
+#define F0 (FPBASE+0)
+#define F1 (FPBASE+1)
+#define F2 (FPBASE+2)
+#define F3 (FPBASE+3)
+#define F4 (FPBASE+4)
+#define F5 (FPBASE+5)
+#define F6 (FPBASE+6)
+#define F7 (FPBASE+7)
+#define F8 (FPBASE+8)
+#define F9 (FPBASE+9)
+#define F10 (FPBASE+10)
+#define F11 (FPBASE+11)
+#define F12 (FPBASE+12)
+#define F13 (FPBASE+13)
+#define F14 (FPBASE+14)
+#define F15 (FPBASE+15)
+#define F16 (FPBASE+16)
+#define F17 (FPBASE+17)
+#define F18 (FPBASE+18)
+#define F19 (FPBASE+19)
+#define F20 (FPBASE+20)
+#define F21 (FPBASE+21)
+#define F22 (FPBASE+22)
+#define F23 (FPBASE+23)
+#define F24 (FPBASE+24)
+#define F25 (FPBASE+25)
+#define F26 (FPBASE+26)
+#define F27 (FPBASE+27)
+#define F28 (FPBASE+28)
+#define F29 (FPBASE+29)
+#define F30 (FPBASE+30)
+#define F31 (FPBASE+31)
+#define FSR (FPBASE+32)
+
+#ifdef IPCREG
+#define NIPCREG (FSR + 1)
+int ipcreg[NIPCREG] = {
+ ZERO, AST, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7,
+ S0, S1, S2, S3, S4, S5, S6, S7, T8, T9, K0, K1, GP, SP, S8, RA,
+ SR, MULLO, MULHI, BADVADDR, CAUSE, PC,
+ F0, F1, F2, F3, F4, F5, F6, F7,
+ F8, F9, F10, F11, F12, F13, F14, F15,
+ F16, F17, F18, F19, F20, F21, F22, F23,
+ F24, F25, F26, F27, F28, F29, F30, F31, FSR,
+};
+#endif
diff --git a/sys/arch/arc/include/reloc.h b/sys/arch/arc/include/reloc.h
new file mode 100644
index 00000000000..bba5426b18a
--- /dev/null
+++ b/sys/arch/arc/include/reloc.h
@@ -0,0 +1,75 @@
+/* $OpenBSD: reloc.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)reloc.h 8.1 (Berkeley) 6/10/93
+ * from: Header: reloc.h,v 1.6 92/06/20 09:59:37 torek Exp
+ */
+
+#if 0
+/*
+ * MIPS relocation types.
+ */
+enum reloc_type {
+ MIPS_RELOC_32, /* 32-bit absolute */
+ MIPS_RELOC_JMP, /* 26-bit absolute << 2 | high 4 bits of pc */
+ MIPS_RELOC_WDISP16, /* 16-bit signed pc-relative << 2 */
+ MIPS_RELOC_HI16, /* 16-bit absolute << 16 */
+ MIPS_RELOC_HI16_S, /* 16-bit absolute << 16 (+1 if needed) */
+ MIPS_RELOC_LO16, /* 16-bit absolute */
+};
+
+/*
+ * MIPS relocation info.
+ *
+ * Symbol-relative relocation is done by:
+ * 1. start with the value r_addend,
+ * 2. locate the appropriate symbol and if defined, add symbol value,
+ * 3. if pc relative, subtract pc,
+ * 4. if the reloc_type is MIPS_RELOC_HI16_S and the result bit 15 is set,
+ * add 0x00010000,
+ * 5. shift down 2 or 16 if necessary.
+ * The resulting value is then to be stuffed into the appropriate bits
+ * in the object (the low 16, or the low 26 bits).
+ */
+struct reloc_info_pica {
+ u_long r_address; /* relocation addr (offset in segment) */
+ u_int r_index:24, /* segment (r_extern==0) or symbol index */
+ r_extern:1, /* if set, r_index is symbol index */
+ :2; /* unused */
+ enum reloc_type r_type:5; /* relocation type, from above */
+ long r_addend; /* value to add to symbol value */
+};
+
+#define relocation_info reloc_info_pica
+#endif
diff --git a/sys/arch/arc/include/setjmp.h b/sys/arch/arc/include/setjmp.h
new file mode 100644
index 00000000000..0c31feea29b
--- /dev/null
+++ b/sys/arch/arc/include/setjmp.h
@@ -0,0 +1,8 @@
+/* $OpenBSD: setjmp.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: setjmp.h,v 1.1 1994/12/20 10:37:05 cgd Exp $ */
+
+/*
+ * machine/setjmp.h: machine dependent setjmp-related information.
+ */
+
+#define _JBLEN 83 /* size, in longs, of a jmp_buf */
diff --git a/sys/arch/arc/include/signal.h b/sys/arch/arc/include/signal.h
new file mode 100644
index 00000000000..8051144c5a3
--- /dev/null
+++ b/sys/arch/arc/include/signal.h
@@ -0,0 +1,68 @@
+/* $OpenBSD: signal.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: signal.h,v 1.6 1995/01/18 06:42:01 mellon Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)signal.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Machine-dependent signal definitions
+ */
+
+typedef int sig_atomic_t;
+
+#ifndef _ANSI_SOURCE
+/*
+ * Information pushed on stack when a signal is delivered.
+ * This is used by the kernel to restore state following
+ * execution of the signal handler. It is also made available
+ * to the handler to allow it to restore state properly if
+ * a non-standard exit is performed.
+ */
+struct sigcontext {
+ int sc_onstack; /* sigstack state to restore */
+ int sc_mask; /* signal mask to restore */
+ int sc_pc; /* pc at time of signal */
+ int sc_regs[32]; /* processor regs 0 to 31 */
+ int mullo, mulhi; /* mullo and mulhi registers... */
+ int sc_fpused; /* fp has been used */
+ int sc_fpregs[33]; /* fp regs 0 to 31 and csr */
+ int sc_fpc_eir; /* floating point exception instruction reg */
+ int xxx[8]; /* XXX reserved */
+};
+
+#endif /* !_ANSI_SOURCE */
diff --git a/sys/arch/arc/include/stdarg.h b/sys/arch/arc/include/stdarg.h
new file mode 100644
index 00000000000..f2416324434
--- /dev/null
+++ b/sys/arch/arc/include/stdarg.h
@@ -0,0 +1,65 @@
+/* $OpenBSD: stdarg.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: stdarg.h,v 1.7 1995/03/28 18:19:28 jtc Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)stdarg.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _PMAX_STDARG_H_
+#define _PMAX_STDARG_H_
+
+#include <machine/ansi.h>
+
+typedef _BSD_VA_LIST_ va_list;
+
+#define __va_promote(type) \
+ (((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+#define va_start(ap, last) \
+ (ap = ((char *)&(last) + __va_promote(last)))
+
+#ifdef _KERNEL
+#define va_arg(ap, type) \
+ ((type *)(ap += sizeof(type)))[-1]
+#else
+#define va_arg(ap, type) \
+ ((type *)(ap += sizeof(type) == sizeof(int) ? sizeof(type) : \
+ sizeof(type) > sizeof(int) ? \
+ (-(int)(ap) & (sizeof(type) - 1)) + sizeof(type) : \
+ (abort(), 0)))[-1]
+#endif
+
+#define va_end(ap) ((void) 0)
+
+#endif /* !_PMAX_STDARG_H_ */
diff --git a/sys/arch/arc/include/trap.h b/sys/arch/arc/include/trap.h
new file mode 100644
index 00000000000..b134df761f0
--- /dev/null
+++ b/sys/arch/arc/include/trap.h
@@ -0,0 +1,68 @@
+/* $OpenBSD: trap.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: trap.h 1.1 90/07/09
+ * from: @(#)trap.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Trap codes
+ * also known in trap.c for name strings
+ */
+
+#define T_INT 0 /* Interrupt pending */
+#define T_TLB_MOD 1 /* TLB modified fault */
+#define T_TLB_LD_MISS 2 /* TLB miss on load or ifetch */
+#define T_TLB_ST_MISS 3 /* TLB miss on a store */
+#define T_ADDR_ERR_LD 4 /* Address error on a load or ifetch */
+#define T_ADDR_ERR_ST 5 /* Address error on a store */
+#define T_BUS_ERR_IFETCH 6 /* Bus error on an ifetch */
+#define T_BUS_ERR_LD_ST 7 /* Bus error on a load or store */
+#define T_SYSCALL 8 /* System call */
+#define T_BREAK 9 /* Breakpoint */
+#define T_RES_INST 10 /* Reserved instruction exception */
+#define T_COP_UNUSABLE 11 /* Coprocessor unusable */
+#define T_OVFLOW 12 /* Arithmetic overflow */
+#define T_TRAP 13 /* Trap instruction */
+#define T_VCEI 14 /* Viritual coherency instruction */
+#define T_FPE 15 /* Floating point exception */
+#define T_WATCH 23 /* Watch address reference */
+#define T_VCED 31 /* Viritual coherency data */
+
+#define T_USER 0x20 /* user-mode flag or'ed with type */
diff --git a/sys/arch/arc/include/types.h b/sys/arch/arc/include/types.h
new file mode 100644
index 00000000000..e847a7f4f8f
--- /dev/null
+++ b/sys/arch/arc/include/types.h
@@ -0,0 +1,82 @@
+/* $OpenBSD: types.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: types.h,v 1.10 1995/07/06 03:39:43 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)types.h 8.3 (Berkeley) 1/5/94
+ */
+
+#ifndef _MACHTYPES_H_
+#define _MACHTYPES_H_
+
+#include <sys/cdefs.h>
+
+#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
+typedef struct _physadr {
+ int r[1];
+} *physadr;
+
+typedef struct label_t {
+ int val[12];
+} label_t;
+#endif
+
+typedef unsigned long vm_offset_t;
+typedef unsigned long vm_size_t;
+
+/*
+ * Basic integral types. Omit the typedef if
+ * not possible for a machine/compiler combination.
+ */
+#define __BIT_TYPES_DEFINED__
+typedef __signed char int8_t;
+typedef unsigned char u_int8_t;
+typedef short int16_t;
+typedef unsigned short u_int16_t;
+typedef int int32_t;
+typedef unsigned int u_int32_t;
+/* LONGLONG */
+typedef long long int64_t;
+/* LONGLONG */
+typedef unsigned long long u_int64_t;
+
+typedef int32_t register_t;
+
+#define __BDEVSW_DUMP_OLD_TYPE
+#define __SWAP_BROKEN
+#define __FORK_BRAINDAMAGE
+
+#endif /* _MACHTYPES_H_ */
diff --git a/sys/arch/arc/include/varargs.h b/sys/arch/arc/include/varargs.h
new file mode 100644
index 00000000000..eca413161e8
--- /dev/null
+++ b/sys/arch/arc/include/varargs.h
@@ -0,0 +1,69 @@
+/* $OpenBSD: varargs.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: varargs.h,v 1.8 1995/03/28 18:19:30 jtc Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)varargs.h 8.2 (Berkeley) 3/22/94
+ */
+
+#ifndef _PMAX_VARARGS_H_
+#define _PMAX_VARARGS_H_
+
+#include <machine/ansi.h>
+
+typedef _BSD_VA_LIST_ va_list;
+
+#define va_dcl int va_alist; ...
+
+#define va_start(ap) \
+ ap = (char *)&va_alist
+
+#ifdef _KERNEL
+#define va_arg(ap, type) \
+ ((type *)(ap += sizeof(type)))[-1]
+#else
+#define va_arg(ap, type) \
+ ((type *)(ap += sizeof(type) == sizeof(int) ? sizeof(type) : \
+ sizeof(type) > sizeof(int) ? \
+ (-(int)(ap) & (sizeof(type) - 1)) + sizeof(type) : \
+ (abort(), 0)))[-1]
+#endif
+
+#define va_end(ap) ((void) 0)
+
+#endif /* !_PMAX_VARARGS_H_ */
diff --git a/sys/arch/arc/include/vmparam.h b/sys/arch/arc/include/vmparam.h
new file mode 100644
index 00000000000..539b024441d
--- /dev/null
+++ b/sys/arch/arc/include/vmparam.h
@@ -0,0 +1,238 @@
+/* $OpenBSD: vmparam.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: vmparam.h,v 1.5 1994/10/26 21:10:10 cgd Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: vmparam.h 1.16 91/01/18
+ * @(#)vmparam.h 8.2 (Berkeley) 4/22/94
+ */
+
+/*
+ * Machine dependent constants for DEC Station 3100.
+ */
+/*
+ * USRTEXT is the start of the user text/data space, while USRSTACK
+ * is the top (end) of the user stack. LOWPAGES and HIGHPAGES are
+ * the number of pages from the beginning of the P0 region to the
+ * beginning of the text and from the beginning of the P1 region to the
+ * beginning of the stack respectively.
+ */
+#define USRTEXT 0x00001000
+#define USRSTACK 0x80000000 /* Start of user stack */
+#define BTOPUSRSTACK 0x80000 /* btop(USRSTACK) */
+#define LOWPAGES 0x00001
+#define HIGHPAGES 0
+
+/*
+ * Virtual memory related constants, all in bytes
+ */
+#ifndef MAXTSIZ
+#define MAXTSIZ (24*1024*1024) /* max text size */
+#endif
+#ifndef DFLDSIZ
+#define DFLDSIZ (32*1024*1024) /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define MAXDSIZ (32*1024*1024) /* max data size */
+#endif
+#ifndef DFLSSIZ
+#define DFLSSIZ (1024*1024) /* initial stack size limit */
+#endif
+#ifndef MAXSSIZ
+#define MAXSSIZ MAXDSIZ /* max stack size */
+#endif
+
+/*
+ * Default sizes of swap allocation chunks (see dmap.h).
+ * The actual values may be changed in vminit() based on MAXDSIZ.
+ * With MAXDSIZ of 16Mb and NDMAP of 38, dmmax will be 1024.
+ * DMMIN should be at least ctod(1) so that vtod() works.
+ * vminit() insures this.
+ */
+#define DMMIN 32 /* smallest swap allocation */
+#define DMMAX 4096 /* largest potential swap allocation */
+
+/*
+ * Sizes of the system and user portions of the system page table.
+ */
+/* SYSPTSIZE IS SILLY; (really number of buffers for I/O) */
+#define SYSPTSIZE 1228
+#define USRPTSIZE 1024
+
+/*
+ * PTEs for mapping user space into the kernel for phyio operations.
+ * 16 pte's are enough to cover 8 disks * MAXBSIZE.
+ */
+#ifndef USRIOSIZE
+#define USRIOSIZE 32
+#endif
+
+/*
+ * PTEs for system V style shared memory.
+ * This is basically slop for kmempt which we actually allocate (malloc) from.
+ */
+#ifndef SHMMAXPGS
+#define SHMMAXPGS 1024 /* 4mb */
+#endif
+
+/*
+ * Boundary at which to place first MAPMEM segment if not explicitly
+ * specified. Should be a power of two. This allows some slop for
+ * the data segment to grow underneath the first mapped segment.
+ */
+#define MMSEG 0x200000
+
+/*
+ * The size of the clock loop.
+ */
+#define LOOPPAGES (maxfree - firstfree)
+
+/*
+ * The time for a process to be blocked before being very swappable.
+ * This is a number of seconds which the system takes as being a non-trivial
+ * amount of real time. You probably shouldn't change this;
+ * it is used in subtle ways (fractions and multiples of it are, that is, like
+ * half of a ``long time'', almost a long time, etc.)
+ * It is related to human patience and other factors which don't really
+ * change over time.
+ */
+#define MAXSLP 20
+
+/*
+ * A swapped in process is given a small amount of core without being bothered
+ * by the page replacement algorithm. Basically this says that if you are
+ * swapped in you deserve some resources. We protect the last SAFERSS
+ * pages against paging and will just swap you out rather than paging you.
+ * Note that each process has at least UPAGES+CLSIZE pages which are not
+ * paged anyways (this is currently 8+2=10 pages or 5k bytes), so this
+ * number just means a swapped in process is given around 25k bytes.
+ * Just for fun: current memory prices are 4600$ a megabyte on VAX (4/22/81),
+ * so we loan each swapped in process memory worth 100$, or just admit
+ * that we don't consider it worthwhile and swap it out to disk which costs
+ * $30/mb or about $0.75.
+ */
+#define SAFERSS 4 /* nominal ``small'' resident set size
+ protected against replacement */
+
+/*
+ * DISKRPM is used to estimate the number of paging i/o operations
+ * which one can expect from a single disk controller.
+ */
+#define DISKRPM 60
+
+/*
+ * Klustering constants. Klustering is the gathering
+ * of pages together for pagein/pageout, while clustering
+ * is the treatment of hardware page size as though it were
+ * larger than it really is.
+ *
+ * KLMAX gives maximum cluster size in CLSIZE page (cluster-page)
+ * units. Note that ctod(KLMAX*CLSIZE) must be <= DMMIN in dmap.h.
+ * ctob(KLMAX) should also be less than MAXPHYS (in vm_swp.c)
+ * unless you like "big push" panics.
+ */
+
+#ifdef notdef /* XXX */
+#define KLMAX (4/CLSIZE)
+#define KLSEQL (2/CLSIZE) /* in klust if vadvise(VA_SEQL) */
+#define KLIN (4/CLSIZE) /* default data/stack in klust */
+#define KLTXT (4/CLSIZE) /* default text in klust */
+#define KLOUT (4/CLSIZE)
+#else
+#define KLMAX (1/CLSIZE)
+#define KLSEQL (1/CLSIZE)
+#define KLIN (1/CLSIZE)
+#define KLTXT (1/CLSIZE)
+#define KLOUT (1/CLSIZE)
+#endif
+
+/*
+ * KLSDIST is the advance or retard of the fifo reclaim for sequential
+ * processes data space.
+ */
+#define KLSDIST 3 /* klusters advance/retard for seq. fifo */
+
+/*
+ * Paging thresholds (see vm_sched.c).
+ * Strategy of 1/19/85:
+ * lotsfree is 512k bytes, but at most 1/4 of memory
+ * desfree is 200k bytes, but at most 1/8 of memory
+ */
+#define LOTSFREE (512 * 1024)
+#define LOTSFREEFRACT 4
+#define DESFREE (200 * 1024)
+#define DESFREEFRACT 8
+
+/*
+ * There are two clock hands, initially separated by HANDSPREAD bytes
+ * (but at most all of user memory). The amount of time to reclaim
+ * a page once the pageout process examines it increases with this
+ * distance and decreases as the scan rate rises.
+ */
+#define HANDSPREAD (2 * 1024 * 1024)
+
+/*
+ * The number of times per second to recompute the desired paging rate
+ * and poke the pagedaemon.
+ */
+#define RATETOSCHEDPAGING 4
+
+/*
+ * Believed threshold (in megabytes) for which interleaved
+ * swapping area is desirable.
+ */
+#define LOTSOFMEM 2
+
+#define mapin(pte, v, pfnum, prot) \
+ (*(int *)(pte) = ((pfnum) << PG_SHIFT) | (prot), MachTLBFlushAddr(v))
+
+/*
+ * Mach derived constants
+ */
+
+/* user/kernel map constants */
+#define VM_MIN_ADDRESS ((vm_offset_t)0x00000000)
+#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x80000000)
+#define VM_MAX_ADDRESS ((vm_offset_t)0x80000000)
+#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xC0000000)
+#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xFFFFC000)
+
+/* virtual sizes (bytes) for various kernel submaps */
+#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES)
+#define VM_KMEM_SIZE (NKMEMCLUSTERS*CLBYTES)
+#define VM_PHYS_SIZE (USRIOSIZE*CLBYTES)
diff --git a/sys/arch/arc/isa/isa_machdep.h b/sys/arch/arc/isa/isa_machdep.h
new file mode 100644
index 00000000000..24c104c3deb
--- /dev/null
+++ b/sys/arch/arc/isa/isa_machdep.h
@@ -0,0 +1,72 @@
+/* $OpenBSD: isa_machdep.h,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+
+/*
+ * Copyright (c) 1996 Per Fogelstrom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Per Fogelstrom
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _ISA_MACHDEP_H_
+#define _ISA_MACHDEP_H_
+
+typedef struct arc_isa_bus *isa_chipset_tag_t;
+
+struct arc_isa_bus {
+ void *ic_data;
+
+ void (*ic_attach_hook) __P((struct device *, struct device *,
+ struct isabus_attach_args *));
+ void *(*ic_intr_establish) __P((isa_chipset_tag_t, int, int, int,
+ int (*)(void *), void *, char *));
+ void (*ic_intr_disestablish) __P((isa_chipset_tag_t, void *));
+};
+
+
+/*
+ * Functions provided to machine-independent ISA code.
+ */
+#define isa_attach_hook(p, s, a) /* \
+ (*(a)->iba_ic->ic_attach_hook)((p), (s), (a)) */
+#define isa_intr_establish(c, i, t, l, f, a, w) \
+ (*(c)->ic_intr_establish)((c)->ic_data, (i), (t), (l), (f), (a), (w))
+#define isa_intr_disestablish(c, h) \
+ (*(c)->ic_intr_disestablish)((c)->ic_data, (h))
+
+/*
+ * Interrupt control struct used to control the ICU setup.
+ */
+
+struct intrhand {
+ struct intrhand *ih_next;
+ int (*ih_fun) __P((void *));
+ void *ih_arg;
+ u_long ih_count;
+ int ih_level;
+ int ih_irq;
+ char *ih_what;
+};
+
+#endif /* _ISA_MACHDEP_H_ */
diff --git a/sys/arch/arc/isa/isabus.c b/sys/arch/arc/isa/isabus.c
new file mode 100644
index 00000000000..75f69270954
--- /dev/null
+++ b/sys/arch/arc/isa/isabus.c
@@ -0,0 +1,490 @@
+/* $OpenBSD: isabus.c,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: isa.c,v 1.33 1995/06/28 04:30:51 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1995 Per Fogelstrom
+ * Copyright (c) 1993, 1994 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
+ * William Jolitz and Don Ahn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)isa.c 7.2 (Berkeley) 5/12/91
+ */
+/*
+ * 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 "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.
+ */
+/*
+ Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+#include <machine/autoconf.h>
+#include <machine/intr.h>
+
+#include <arc/arc/arctype.h>
+#include <arc/pica/pica.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <arc/isa/timerreg.h>
+#include <arc/isa/spkrreg.h>
+#include <arc/isa/isa_machdep.h>
+
+extern int isa_io_base; /* Base address for ISA I/O space */
+extern int isa_mem_base; /* Base address for ISA MEM space */
+
+static int beeping;
+
+/*
+ * I/O macros to access isa bus ports/memory.
+ * At the first glance theese macros may seem inefficient.
+ * However, the cpu executes an instruction every 7.5ns
+ * so the bus is much slower so it doesn't matter, really.
+ */
+#define isa_outb(x,y) outb(isa_io_base + (x), y)
+#define isa_inb(x) inb(isa_io_base + (x))
+
+#define IRQ_SLAVE 2
+#define ICU_LEN 16
+
+struct isabr_softc {
+ struct device sc_dv;
+ struct arc_isa_bus arc_isa_cs;
+ struct arc_isa_busmap arc_isa_map;
+ struct abus sc_bus;
+};
+
+/* Definition of the driver for autoconfig. */
+int isabrmatch(struct device *, void *, void *);
+void isabrattach(struct device *, struct device *, void *);
+int isabrprint(void *, char *);
+
+struct cfattach isabr_ca = {
+ sizeof(struct isabr_softc), isabrmatch, isabrattach
+};
+struct cfdriver isabr_cd = {
+ NULL, "isabr", DV_DULL, NULL, 0
+};
+
+void *isabr_intr_establish __P((isa_chipset_tag_t, int, int, int,
+ int (*)(void *), void *, char *));
+void isabr_intr_disestablish __P((isa_chipset_tag_t, void*));
+int isabr_iointr __P((void *));
+void isabr_initicu();
+
+extern int cputype;
+
+
+int
+isabrmatch(parent, cfdata, aux)
+ struct device *parent;
+ void *cfdata;
+ void *aux;
+{
+ struct cfdata *cf = cfdata;
+ struct confargs *ca = aux;
+
+ /* Make sure that we're looking for a ISABR. */
+ if (strcmp(ca->ca_name, isabr_cd.cd_name) != 0)
+ return (0);
+
+ return (1);
+}
+
+void
+isabrattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct isabr_softc *sc = (struct isabr_softc *)self;
+ struct isabus_attach_args iba;
+
+ printf("\n");
+
+ /* Initialize interrupt controller */
+ isabr_initicu();
+
+ /* set up interrupt handlers */
+ switch(cputype) {
+ case ACER_PICA_61:
+ set_intr(INT_MASK_2, isabr_iointr, 3);
+ break;
+ default:
+ panic("isabrattach: unkown cputype!");
+ }
+
+/*XXX we may remove the abus part of the softc struct... */
+ sc->sc_bus.ab_dv = (struct device *)sc;
+ sc->sc_bus.ab_type = BUS_ISABR;
+
+ sc->arc_isa_cs.ic_intr_establish = isabr_intr_establish;
+ sc->arc_isa_cs.ic_intr_disestablish = isabr_intr_disestablish;
+ sc->arc_isa_map.isa_io_base = (void *)isa_io_base;
+ sc->arc_isa_map.isa_mem_base = (void *)isa_mem_base;
+
+ iba.iba_busname = "isa";
+ iba.iba_bc = &sc->arc_isa_map;
+ iba.iba_ic = &sc->arc_isa_cs;
+ config_found(self, &iba, isabrprint);
+}
+
+int
+isabrprint(aux, pnp)
+ void *aux;
+ char *pnp;
+{
+ struct confargs *ca = aux;
+
+ if (pnp)
+ printf("%s at %s", ca->ca_name, pnp);
+ printf(" I/O base 0x%lx Mem base 0x%lx", isa_io_base, isa_mem_base);
+ return (UNCONF);
+}
+
+
+/*
+ * Interrupt system driver code
+ * ============================
+ */
+#define LEGAL_IRQ(x) ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
+
+int imen;
+int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
+struct intrhand *intrhand[ICU_LEN];
+
+int fakeintr(void *arg) {return 0;}
+
+/*
+ * Recalculate the interrupt masks from scratch.
+ * We could code special registry and deregistry versions of this function that
+ * would be faster, but the code would be nastier, and we don't expect this to
+ * happen very much anyway.
+ */
+void
+intr_calculatemasks()
+{
+ int irq, level;
+ struct intrhand *q;
+
+ /* First, figure out which levels each IRQ uses. */
+ for (irq = 0; irq < ICU_LEN; irq++) {
+ register int levels = 0;
+ for (q = intrhand[irq]; q; q = q->ih_next)
+ levels |= 1 << q->ih_level;
+ intrlevel[irq] = levels;
+ }
+
+ /* Then figure out which IRQs use each level. */
+ for (level = 0; level < 5; level++) {
+ register int irqs = 0;
+ for (irq = 0; irq < ICU_LEN; irq++)
+ if (intrlevel[irq] & (1 << level))
+ irqs |= 1 << irq;
+ imask[level] = irqs | SIR_ALLMASK;
+ }
+
+ /*
+ * There are tty, network and disk drivers that use free() at interrupt
+ * time, so imp > (tty | net | bio).
+ */
+ imask[IPL_IMP] |= imask[IPL_TTY] | imask[IPL_NET] | imask[IPL_BIO];
+
+ /*
+ * Enforce a hierarchy that gives slow devices a better chance at not
+ * dropping data.
+ */
+ imask[IPL_TTY] |= imask[IPL_NET] | imask[IPL_BIO];
+ imask[IPL_NET] |= imask[IPL_BIO];
+
+ /*
+ * These are pseudo-levels.
+ */
+ imask[IPL_NONE] = 0x00000000;
+ imask[IPL_HIGH] = 0xffffffff;
+
+ /* And eventually calculate the complete masks. */
+ for (irq = 0; irq < ICU_LEN; irq++) {
+ register int irqs = 1 << irq;
+ for (q = intrhand[irq]; q; q = q->ih_next)
+ irqs |= imask[q->ih_level];
+ intrmask[irq] = irqs | SIR_ALLMASK;
+ }
+
+ /* Lastly, determine which IRQs are actually in use. */
+ {
+ register int irqs = 0;
+ for (irq = 0; irq < ICU_LEN; irq++)
+ if (intrhand[irq])
+ irqs |= 1 << irq;
+ if (irqs >= 0x100) /* any IRQs >= 8 in use */
+ irqs |= 1 << IRQ_SLAVE;
+ imen = ~irqs;
+ isa_outb(IO_ICU1 + 1, imen);
+ isa_outb(IO_ICU2 + 1, imen >> 8);
+ }
+}
+
+/*
+ * Establish a ISA bus interrupt.
+ */
+void *
+isabr_intr_establish(ic, irq, type, level, ih_fun, ih_arg, ih_what)
+ isa_chipset_tag_t ic;
+ int irq;
+ int type;
+ int level;
+ int (*ih_fun) __P((void *));
+ void *ih_arg;
+ char *ih_what;
+{
+ struct intrhand **p, *q, *ih;
+ static struct intrhand fakehand = {NULL, fakeintr};
+ extern int cold;
+
+ /* no point in sleeping unless someone can free memory. */
+ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
+ if (ih == NULL)
+ panic("isa_intr_establish: can't malloc handler info");
+
+ if (!LEGAL_IRQ(irq) || type == IST_NONE)
+ panic("intr_establish: bogus irq or type");
+
+ switch (intrtype[irq]) {
+ case IST_EDGE:
+ case IST_LEVEL:
+ if (type == intrtype[irq])
+ break;
+ case IST_PULSE:
+ if (type != IST_NONE)
+ panic("intr_establish: can't share %s with %s",
+ isa_intr_typename(intrtype[irq]),
+ isa_intr_typename(type));
+ break;
+ }
+
+ /*
+ * Figure out where to put the handler.
+ * This is O(N^2), but we want to preserve the order, and N is
+ * generally small.
+ */
+ for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
+ ;
+
+ /*
+ * Actually install a fake handler momentarily, since we might be doing
+ * this with interrupts enabled and don't want the real routine called
+ * until masking is set up.
+ */
+ fakehand.ih_level = level;
+ *p = &fakehand;
+
+ intr_calculatemasks();
+
+ /*
+ * Poke the real handler in now.
+ */
+ ih->ih_fun = ih_fun;
+ ih->ih_arg = ih_arg;
+ ih->ih_count = 0;
+ ih->ih_next = NULL;
+ ih->ih_level = level;
+ ih->ih_irq = irq;
+ ih->ih_what = ih_what;
+ *p = ih;
+
+ return (ih);
+}
+
+void
+isabr_intr_disestablish(ic, arg)
+ isa_chipset_tag_t ic;
+ void *arg;
+{
+
+}
+
+/*
+ * Process an interrupt from the ISA bus ACER PICA style.
+ */
+int
+isabr_iointr(ca)
+ void *ca; /* XXX */
+{
+ struct intrhand *ih;
+ int isa_vector;
+ int o_imen;
+
+ isa_vector = in32(PICA_SYS_ISA_VECTOR) & (ICU_LEN - 1);
+
+ o_imen = imen;
+ imen |= 1 << (isa_vector & (ICU_LEN - 1));
+ if(isa_vector & 0x08) {
+ isa_inb(IO_ICU2 + 1);
+ isa_outb(IO_ICU2 + 1, imen >> 8);
+ isa_outb(IO_ICU2, 0x60 + (isa_vector & 7));
+ isa_outb(IO_ICU1, 0x60 + IRQ_SLAVE);
+ }
+ else {
+ isa_inb(IO_ICU1 + 1);
+ isa_outb(IO_ICU1 + 1, imen);
+ isa_outb(IO_ICU1, 0x60 + isa_vector);
+ }
+ ih = intrhand[isa_vector];
+ while(ih) {
+ (*ih->ih_fun)(ih->ih_arg);
+ ih = ih->ih_next;
+ }
+ imen = o_imen;
+ isa_inb(IO_ICU1 + 1);
+ isa_inb(IO_ICU2 + 1);
+ isa_outb(IO_ICU1 + 1, imen);
+ isa_outb(IO_ICU2 + 1, imen >> 8);
+
+ return(~0); /* Dont reenable */
+}
+
+
+/*
+ * Initialize the Interrupt controller logic.
+ */
+void
+isabr_initicu()
+{
+
+ isa_outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
+ isa_outb(IO_ICU1+1, 0); /* starting at this vector index */
+ isa_outb(IO_ICU1+1, 1 << IRQ_SLAVE); /* slave on line 2 */
+ isa_outb(IO_ICU1+1, 1); /* 8086 mode */
+ isa_outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
+ isa_outb(IO_ICU1, 0x68); /* special mask mode (if available) */
+ isa_outb(IO_ICU1, 0x0a); /* Read IRR by default. */
+#ifdef REORDER_IRQ
+ isa_outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
+#endif
+
+ isa_outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
+ isa_outb(IO_ICU2+1, 8); /* staring at this vector index */
+ isa_outb(IO_ICU2+1, IRQ_SLAVE);
+ isa_outb(IO_ICU2+1, 1); /* 8086 mode */
+ isa_outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
+ isa_outb(IO_ICU2, 0x68); /* special mask mode (if available) */
+ isa_outb(IO_ICU2, 0x0a); /* Read IRR by default. */
+}
+
+
+/*
+ * SPEAKER BEEPER...
+ */
+void
+sysbeepstop(arg)
+ void *arg;
+{
+ int s;
+
+ /* disable counter 2 */
+ s = splhigh();
+ isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) & ~PIT_SPKR);
+ splx(s);
+ beeping = 0;
+}
+
+void
+sysbeep(pitch, period)
+ int pitch, period;
+{
+ static int last_pitch, last_period;
+ int s;
+
+ if (beeping)
+ untimeout(sysbeepstop, 0);
+ if (!beeping || last_pitch != pitch) {
+ s = splhigh();
+ isa_outb(TIMER_MODE, TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
+ isa_outb(TIMER_CNTR2, TIMER_DIV(pitch) % 256);
+ isa_outb(TIMER_CNTR2, TIMER_DIV(pitch) / 256);
+ isa_outb(PITAUX_PORT, isa_inb(PITAUX_PORT) | PIT_SPKR);
+ splx(s);
+ }
+ last_pitch = pitch;
+ beeping = last_period = period;
+ timeout(sysbeepstop, 0, period);
+}
diff --git a/sys/arch/arc/isa/isadma.c b/sys/arch/arc/isa/isadma.c
new file mode 100644
index 00000000000..95cdfbe475f
--- /dev/null
+++ b/sys/arch/arc/isa/isadma.c
@@ -0,0 +1,317 @@
+/* $OpenBSD: isadma.c,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: isadma.c,v 1.19 1996/04/29 20:03:26 christos Exp $ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/file.h>
+#include <sys/buf.h>
+#include <sys/syslog.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+
+#include <machine/pio.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <arch/arc/isa/isadmareg.h> /*XXX*/
+
+struct dma_info {
+ int flags;
+ int active;
+ caddr_t addr;
+ vm_size_t nbytes;
+ struct isadma_seg phys[1];
+};
+
+static struct isadma_softc *isadma_sc; /*XXX ugly */
+static struct dma_info dma_info[8];
+static u_int8_t dma_finished;
+
+/* high byte of address is stored in this port for i-th dma channel */
+static int dmapageport[2][4] = {
+ {0x87, 0x83, 0x81, 0x82},
+ {0x8f, 0x8b, 0x89, 0x8a}
+};
+
+static u_int8_t dmamode[4] = {
+ DMA37MD_READ | DMA37MD_SINGLE,
+ DMA37MD_WRITE | DMA37MD_SINGLE,
+ DMA37MD_READ | DMA37MD_LOOP,
+ DMA37MD_WRITE | DMA37MD_LOOP
+};
+
+int isadmamatch __P((struct device *, void *, void *));
+void isadmaattach __P((struct device *, struct device *, void *));
+int isadmaprint __P((void *, char *));
+
+struct isadma_softc {
+ struct device sc_dev;
+ bus_chipset_tag_t sc_bc;
+ bus_io_handle_t sc_ioh1;
+ bus_io_handle_t sc_ioh2;
+}
+
+struct cfattach isadma_ca = {
+ sizeof(struct isadma_softc), isadmamatch, isadmaattach
+};
+
+struct cfdriver isadma_cd = {
+ NULL, "isadma", DV_DULL, 1
+};
+
+isadmamatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct isa_attach_args *ia = aux;
+
+ /* Sure we exist */
+ ia->ia_iosize = 0;
+ return (1);
+}
+
+void
+isadmaattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isadma_softc *sc = (void *)self;
+ struct isa_attach_args *ia = aux;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+
+ printf("\n");
+
+ bc = sc->sc_bc = ia->ia_bc;
+ if (bus_io_map(bc, IO_DMA1, DMA_NREGS, &ioh))
+ panic("isadmaattach: couldn't map I/O ports");
+ sc->sc_ioh1 = ioh;
+ if (bus_io_map(bc, IO_DMA2, DMA_NREGS*2, &ioh))
+ panic("isadmaattach: couldn't map I/O ports");
+ sc->sc_ioh2 = ioh;
+ isadma_sc = sc;
+}
+
+/*
+ * isadma_cascade(): program 8237 DMA controller channel to accept
+ * external dma control by a board.
+ */
+void
+isadma_cascade(chan)
+ int chan;
+{
+ struct isadma_softc *sc = isadma_sc;
+ bus_chipset_tag_t bc = sc->sc_bc;
+
+#ifdef ISADMA_DEBUG
+ if (chan < 0 || chan > 7)
+ panic("isadma_cascade: impossible request");
+#endif
+
+ /* set dma channel mode, and set dma channel mode */
+ if ((chan & 4) == 0) {
+ bus_io_write_1(bc, sc->sc_ioh1, DMA1_MODE, chan | DMA37MD_CASCADE);
+ bus_io_write_1(bc, sc->sc_ioh1, DMA1_SMSK, chan);
+ } else {
+ chan &= 3;
+
+ bus_io_write_1(bc, sc->sc_ioh2, DMA2_MODE, chan | DMA37MD_CASCADE);
+ bus_io_write_1(bc, sc->sc_ioh2, DMA2_SMSK, chan);
+ }
+}
+
+/*
+ * isadma_start(): program 8237 DMA controller channel, avoid page alignment
+ * problems by using a bounce buffer.
+ */
+void
+isadma_start(addr, nbytes, chan, flags)
+ caddr_t addr;
+ vm_size_t nbytes;
+ int chan;
+ int flags;
+{
+ struct dma_info *di;
+ int waport;
+ int mflags;
+ vm_size_t size;
+ struct isadma_softc *sc = isadma_sc;
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh;
+
+#ifdef ISADMA_DEBUG
+ if (chan < 0 || chan > 7 ||
+ (((flags & DMAMODE_READ) != 0) + ((flags & DMAMODE_WRITE) != 0) +
+ ((flags & DMAMODE_LOOP) != 0) != 1) ||
+ ((chan & 4) ? (nbytes >= (1<<17) || nbytes & 1 || (u_int)addr & 1) :
+ (nbytes >= (1<<16))))
+ panic("isadma_start: impossible request");
+#endif
+
+ di = dma_info+chan;
+ if (di->active) {
+ log(LOG_ERR,"isadma_start: old request active on %d\n",chan);
+ isadma_abort(chan);
+ }
+
+ di->flags = flags;
+ di->active = 1;
+ di->addr = addr;
+ di->nbytes = nbytes;
+
+ mflags = ISADMA_MAP_WAITOK | ISADMA_MAP_BOUNCE | ISADMA_MAP_CONTIG;
+ mflags |= (chan & 4) ? ISADMA_MAP_16BIT : ISADMA_MAP_8BIT;
+
+ if (isadma_map(addr, nbytes, di->phys, mflags) != 1)
+ panic("isadma_start: cannot map");
+
+ /* XXX Will this do what we want with DMAMODE_LOOP? */
+ if ((flags & DMAMODE_READ) == 0)
+ isadma_copytobuf(addr, nbytes, 1, di->phys);
+
+ dma_finished &= ~(1 << chan);
+
+ if ((chan & 4) == 0) {
+ ioh = sc->sc_ioh1;
+ /*
+ * Program one of DMA channels 0..3. These are
+ * byte mode channels.
+ */
+ /* set dma channel mode, and reset address ff */
+ bus_io_write_1(bc, ioh, DMA1_MODE, chan | dmamode[flags]);
+ bus_io_write_1(bc, ioh, DMA1_FFC, 0);
+
+ /* send start address */
+ waport = DMA1_CHN(chan);
+ outb(dmapageport[0][chan], di->phys[0].addr>>16);
+ outb(waport, di->phys[0].addr);
+ outb(waport, di->phys[0].addr>>8);
+
+ /* send count */
+ outb(waport + 1, --nbytes);
+ outb(waport + 1, nbytes>>8);
+
+ /* unmask channel */
+ bus_io_write_1(bc, ioh, DMA1_SMSK, chan | DMA37SM_CLEAR);
+ } else {
+ ioh = sc->sc_ioh2;
+ /*
+ * Program one of DMA channels 4..7. These are
+ * word mode channels.
+ */
+ /* set dma channel mode, and reset address ff */
+ bus_io_write_1(bc, ioh, DMA2_MODE, (chan & 3) | dmamode[flags]);
+ bus_io_write_1(bc, ioh, DMA2_FFC, 0);
+
+ /* send start address */
+ waport = DMA2_CHN(chan & 3);
+ outb(dmapageport[1][chan], di->phys[0].addr>>16);
+ outb(waport, di->phys[0].addr>>1);
+ outb(waport, di->phys[0].addr>>9);
+
+ /* send count */
+ nbytes >>= 1;
+ outb(waport + 2, --nbytes);
+ outb(waport + 2, nbytes>>8);
+
+ /* unmask channel */
+ bus_io_write_1(bc, ioh, DMA2_SMSK, (chan & 3) | DMA37SM_CLEAR);
+ }
+}
+
+void
+isadma_abort(chan)
+ int chan;
+{
+ struct dma_info *di;
+ struct isadma_softc *sc = isadma_sc;
+ bus_chipset_tag_t bc = sc->sc_bc;
+
+#ifdef ISADMA_DEBUG
+ if (chan < 0 || chan > 7)
+ panic("isadma_abort: impossible request");
+#endif
+
+ di = dma_info+chan;
+ if (! di->active) {
+ log(LOG_ERR,"isadma_abort: no request active on %d\n",chan);
+ return;
+ }
+
+ /* mask channel */
+ if ((chan & 4) == 0)
+ bus_io_write_1(bc, sc->sc_ioh1, DMA1_SMSK, DMA37SM_SET | chan);
+ else
+ bus_io_write_1(bc, sc->sc_ioh2, DMA2_SMSK, DMA37SM_SET | (chan & 3));
+
+ isadma_unmap(di->addr, di->nbytes, 1, di->phys);
+ di->active = 0;
+}
+
+int
+isadma_finished(chan)
+ int chan;
+{
+ struct isadma_softc *sc = isadma_sc;
+ bus_chipset_tag_t bc = sc->sc_bc;
+
+#ifdef ISADMA_DEBUG
+ if (chan < 0 || chan > 7)
+ panic("isadma_finished: impossible request");
+#endif
+
+ /* check that the terminal count was reached */
+ if ((chan & 4) == 0)
+ dma_finished |= bus_io_read_1(bc, sc->sc_ioh1, DMA1_SR) & 0x0f;
+ else
+ dma_finished |= (bus_io_read_1(bc, sc->sc_ioh2, DMA2_SR) & 0x0f) << 4;
+
+ return ((dma_finished & (1 << chan)) != 0);
+}
+
+void
+isadma_done(chan)
+ int chan;
+{
+ struct dma_info *di;
+ u_char tc;
+ struct isadma_softc *sc = isadma_sc;
+ bus_chipset_tag_t bc = sc->sc_bc;
+
+#ifdef DIAGNOSTIC
+ if (chan < 0 || chan > 7)
+ panic("isadma_done: impossible request");
+#endif
+
+ di = dma_info+chan;
+ if (! di->active) {
+ log(LOG_ERR,"isadma_done: no request active on %d\n",chan);
+ return;
+ }
+
+ /* check that the terminal count was reached */
+ if ((chan & 4) == 0)
+ tc = bus_io_read_1(bc, sc->sc_ioh1, DMA1_SR) & (1 << chan);
+ else
+ tc = bus_io_read_1(bc, sc->sc_ioh2, DMA2_SR) & (1 << (chan & 3));
+ if (tc == 0)
+ /* XXX probably should panic or something */
+ log(LOG_ERR, "dma channel %d not finished\n", chan);
+
+ /* mask channel */
+ if ((chan & 4) == 0)
+ bus_io_write_1(bc, sc->sc_ioh1, DMA1_SMSK, DMA37SM_SET | chan);
+ else
+ bus_io_write_1(bc, sc->sc_ioh2, DMA2_SMSK, DMA37SM_SET | (chan & 3));
+
+ /* XXX Will this do what we want with DMAMODE_LOOP? */
+ if (di->flags & DMAMODE_READ)
+ isadma_copyfrombuf(di->addr, di->nbytes, 1, di->phys);
+
+ isadma_unmap(di->addr, di->nbytes, 1, di->phys);
+ di->active = 0;
+}
diff --git a/sys/arch/arc/isa/isadmareg.h b/sys/arch/arc/isa/isadmareg.h
new file mode 100644
index 00000000000..185016060f2
--- /dev/null
+++ b/sys/arch/arc/isa/isadmareg.h
@@ -0,0 +1,22 @@
+/* $NetBSD: isadmareg.h,v 1.4 1995/06/28 04:31:48 cgd Exp $ */
+
+#include <dev/ic/i8237reg.h>
+
+#define DMA_NREG 16
+/*
+ * Register definitions for DMA controller 1 (channels 0..3):
+ */
+#define DMA1_CHN(c) (1*(2*(c))) /* addr reg for channel c */
+#define DMA1_SR (1*8) /* status register */
+#define DMA1_SMSK (1*10) /* single mask register */
+#define DMA1_MODE (1*11) /* mode register */
+#define DMA1_FFC (1*12) /* clear first/last FF */
+
+/*
+ * Register definitions for DMA controller 2 (channels 4..7):
+ */
+#define DMA2_CHN(c) (2*(2*(c))) /* addr reg for channel c */
+#define DMA2_SR (2*8) /* status register */
+#define DMA2_SMSK (2*10) /* single mask register */
+#define DMA2_MODE (2*11) /* mode register */
+#define DMA2_FFC (2*12) /* clear first/last FF */
diff --git a/sys/arch/arc/isa/spkrreg.h b/sys/arch/arc/isa/spkrreg.h
new file mode 100644
index 00000000000..af1df50e2ad
--- /dev/null
+++ b/sys/arch/arc/isa/spkrreg.h
@@ -0,0 +1,11 @@
+/* $NetBSD: spkrreg.h,v 1.2 1994/10/27 04:18:16 cgd Exp $ */
+
+/*
+ * PIT port addresses and speaker control values
+ */
+
+#define PITAUX_PORT 0x61 /* port of Programmable Peripheral Interface */
+#define PIT_ENABLETMR2 0x01 /* Enable timer/counter 2 */
+#define PIT_SPKRDATA 0x02 /* Direct to speaker */
+
+#define PIT_SPKR (PIT_ENABLETMR2|PIT_SPKRDATA)
diff --git a/sys/arch/arc/isa/timerreg.h b/sys/arch/arc/isa/timerreg.h
new file mode 100644
index 00000000000..996834cadca
--- /dev/null
+++ b/sys/arch/arc/isa/timerreg.h
@@ -0,0 +1,100 @@
+/* $NetBSD: timerreg.h,v 1.4 1994/10/27 04:18:17 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Register definitions for the Intel 8253 Programmable Interval Timer.
+ *
+ * This chip has three independent 16-bit down counters that can be
+ * read on the fly. There are three mode registers and three countdown
+ * registers. The countdown registers are addressed directly, via the
+ * first three I/O ports. The three mode registers are accessed via
+ * the fourth I/O port, with two bits in the mode byte indicating the
+ * register. (Why are hardware interfaces always so braindead?).
+ *
+ * To write a value into the countdown register, the mode register
+ * is first programmed with a command indicating the which byte of
+ * the two byte register is to be modified. The three possibilities
+ * are load msb (TMR_MR_MSB), load lsb (TMR_MR_LSB), or load lsb then
+ * msb (TMR_MR_BOTH).
+ *
+ * To read the current value ("on the fly") from the countdown register,
+ * you write a "latch" command into the mode register, then read the stable
+ * value from the corresponding I/O port. For example, you write
+ * TMR_MR_LATCH into the corresponding mode register. Presumably,
+ * after doing this, a write operation to the I/O port would result
+ * in undefined behavior (but hopefully not fry the chip).
+ * Reading in this manner has no side effects.
+ *
+ * The outputs of the three timers are connected as follows:
+ *
+ * timer 0 -> irq 0
+ * timer 1 -> dma chan 0 (for dram refresh)
+ * timer 2 -> speaker (via keyboard controller)
+ *
+ * Timer 0 is used to call hardclock.
+ * Timer 2 is used to generate console beeps.
+ */
+
+/*
+ * Frequency of all three count-down timers; (TIMER_FREQ/freq) is the
+ * appropriate count to generate a frequency of freq hz.
+ */
+#ifndef TIMER_FREQ
+#define TIMER_FREQ 1193182
+#endif
+#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
+
+/*
+ * Macros for specifying values to be written into a mode register.
+ */
+#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */
+#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */
+#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */
+#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */
+#define TIMER_SEL0 0x00 /* select counter 0 */
+#define TIMER_SEL1 0x40 /* select counter 1 */
+#define TIMER_SEL2 0x80 /* select counter 2 */
+#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */
+#define TIMER_ONESHOT 0x02 /* mode 1, one shot */
+#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */
+#define TIMER_SQWAVE 0x06 /* mode 3, square wave */
+#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */
+#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */
+#define TIMER_LATCH 0x00 /* latch counter for reading */
+#define TIMER_LSB 0x10 /* r/w counter LSB */
+#define TIMER_MSB 0x20 /* r/w counter MSB */
+#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */
+#define TIMER_BCD 0x01 /* count in BCD */
+
diff --git a/sys/arch/arc/pica/pica.h b/sys/arch/arc/pica/pica.h
new file mode 100644
index 00000000000..454e674f81f
--- /dev/null
+++ b/sys/arch/arc/pica/pica.h
@@ -0,0 +1,168 @@
+/* $OpenBSD */
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University,
+ * Ralph Campbell and Rick Macklem.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)pica.h 8.1 (Berkeley) 6/10/93
+ * $Id: pica.h,v 1.1 1996/06/24 09:07:18 pefo Exp $
+ */
+
+/*
+ * HISTORY
+ * Log: pica.h,v
+ * Created, from the ALI specs:
+ */
+/*
+ * File: pica.h
+ * Author: Per Fogelstrom
+ * Date: 1/95
+ *
+ */
+
+#ifndef _PICA_H_
+#define _PICA_H_ 1
+
+/*
+ * PICA's Physical address space
+ */
+
+#define PICA_PHYS_MIN 0x00000000 /* 256 Meg */
+#define PICA_PHYS_MAX 0x0fffffff
+
+/*
+ * Memory map
+ */
+
+#define PICA_PHYS_MEMORY_START 0x00000000
+#define PICA_PHYS_MEMORY_END 0x0fffffff /* 256 Meg in 8 slots */
+
+#define PICA_MEMORY_SIZE_REG 0xe00fffe0 /* Memory size register */
+#define PICA_CONFIG_REG 0xe00ffff0 /* Hardware config reg */
+
+/*
+ * I/O map
+ */
+
+#define PICA_P_LOCAL_IO_BASE 0x80000000 /* I/O Base address */
+#define PICA_V_LOCAL_IO_BASE 0xe0000000
+#define PICA_S_LOCAL_IO_BASE 0x00040000 /* Size */
+#define PVLB PICA_V_LOCAL_IO_BASE
+#define PICA_SYS_TL_BASE (PVLB+0x0018) /* DMA transl. table base */
+#define PICA_SYS_TL_LIMIT (PVLB+0x0020) /* DMA transl. table limit */
+#define PICA_SYS_TL_IVALID (PVLB+0x0028) /* DMA transl. cache inval */
+#define PICA_SYS_DMA0_REGS (PVLB+0x0100) /* DMA ch0 base address */
+#define PICA_SYS_DMA1_REGS (PVLB+0x0120) /* DMA ch0 base address */
+#define PICA_SYS_DMA2_REGS (PVLB+0x0140) /* DMA ch0 base address */
+#define PICA_SYS_DMA3_REGS (PVLB+0x0160) /* DMA ch0 base address */
+#define PICA_SYS_IT_VALUE (PVLB+0x0228) /* Interval timer reload */
+#define PICA_SYS_IT_STAT (PVLB+0x0230) /* Interval timer count */
+#define PICA_SYS_ISA_VECTOR (PVLB+0x0238) /* ISA Interrupt vector */
+#define PICA_SYS_EXT_IMASK (PVLB+0x00e8) /* External int enable mask */
+#define PICA_SYS_SONIC (PVLB+0x1000) /* SONIC base address */
+#define PICA_SYS_SCSI (PVLB+0x2000) /* SCSI base address */
+#define PICA_SYS_FLOPPY (PVLB+0x3000) /* Floppy base address */
+#define PICA_SYS_CLOCK (PVLB+0x4000) /* Clock base address */
+#define PICA_SYS_KBD (PVLB+0x5000) /* Keybrd/mouse base address */
+#define PICA_SYS_COM1 (PVLB+0x6000) /* Com port 1 */
+#define PICA_SYS_COM2 (PVLB+0x7000) /* Com port 2 */
+#define PICA_SYS_PAR1 (PVLB+0x8000) /* Parallel port 1 */
+#define PICA_SYS_NVRAM (PVLB+0x9000) /* Unprotected NV-ram */
+#define PICA_SYS_PNVRAM (PVLB+0xa000) /* Protected NV-ram */
+#define PICA_SYS_NVPROM (PVLB+0xb000) /* Read only NV-ram */
+#define PICA_SYS_SOUND (PVLB+0xc000) /* Sound port */
+
+#define PICA_SYS_ISA_AS (PICA_V_ISA_IO+0x70)
+
+#define PICA_P_DRAM_CONF 0x800e0000 /* Dram config registers */
+#define PICA_V_DRAM_CONF 0xe00e0000
+#define PICA_S_DRAM_CONF 0x00020000
+
+#define PICA_P_INT_SOURCE 0xf0000000 /* Interrupt src registers */
+#define PICA_V_INT_SOURCE PICA_V_LOCAL_IO_BASE+PICA_S_LOCAL_IO_BASE
+#define PICA_S_INT_SOURCE 0x00001000
+#define PVIS PICA_V_INT_SOURCE
+#define PICA_SYS_LB_IS (PVIS+0x0000) /* Local bus int source */
+#define PICA_SYS_LB_IE (PVIS+0x0002) /* Local bus int enables */
+#define PICA_SYS_LB_IE_PAR1 0x0001 /* Parallel port enable */
+#define PICA_SYS_LB_IE_FLOPPY 0x0002 /* Floppy ctrl enable */
+#define PICA_SYS_LB_IE_SOUND 0x0004 /* Sound port enable */
+#define PICA_SYS_LB_IE_VIDEO 0x0008 /* Video int enable */
+#define PICA_SYS_LB_IE_SONIC 0x0010 /* Ethernet ctrl enable */
+#define PICA_SYS_LB_IE_SCSI 0x0020 /* Scsi crtl enable */
+#define PICA_SYS_LB_IE_KBD 0x0040 /* Keyboard ctrl enable */
+#define PICA_SYS_LB_IE_MOUSE 0x0080 /* Mouse ctrl enable */
+#define PICA_SYS_LB_IE_COM1 0x0100 /* Serial port 1 enable */
+#define PICA_SYS_LB_IE_COM2 0x0200 /* Serial port 2 enable */
+
+#define PICA_P_LOCAL_VIDEO_CTRL 0x60000000 /* Local video control */
+#define PICA_V_LOCAL_VIDEO_CTRL 0xe0200000
+#define PICA_S_LOCAL_VIDEO_CTRL 0x00200000
+
+#define PICA_P_EXTND_VIDEO_CTRL 0x60200000 /* Extended video control */
+#define PICA_V_EXTND_VIDEO_CTRL 0xe0400000
+#define PICA_S_EXTND_VIDEO_CTRL 0x00200000
+
+#define PICA_P_LOCAL_VIDEO 0x40000000 /* Local video memory */
+#define PICA_V_LOCAL_VIDEO 0xe0800000
+#define PICA_S_LOCAL_VIDEO 0x00800000
+
+#define PICA_P_ISA_IO 0x90000000 /* ISA I/O control */
+#define PICA_V_ISA_IO 0xe2000000
+#define PICA_S_ISA_IO 0x01000000
+
+#define PICA_P_ISA_MEM 0x91000000 /* ISA Memory control */
+#define PICA_V_ISA_MEM 0xe3000000
+#define PICA_S_ISA_MEM 0x01000000
+
+/*
+ * Addresses used by various display drivers.
+ */
+#define MONO_BASE (PICA_V_LOCAL_VIDEO_CTRL + 0x3B4)
+#define MONO_BUF (PICA_V_LOCAL_VIDEO + 0xB0000)
+#define CGA_BASE (PICA_V_LOCAL_VIDEO_CTRL + 0x3D4)
+#define CGA_BUF (PICA_V_LOCAL_VIDEO + 0xB8000)
+
+/*
+ * Interrupt vector descriptor for device on pica bus.
+ */
+struct pica_int_desc {
+ int int_mask; /* Mask used in PICA_SYS_LB_IE */
+ intr_handler_t int_hand; /* Interrupt handler */
+ void *param; /* Parameter to send to handler */
+ int spl_mask; /* Spl mask for interrupt */
+};
+
+int pica_intrnull __P((void *));
+#endif /* _PICA_H_ */
diff --git a/sys/arch/arc/pica/picabus.c b/sys/arch/arc/pica/picabus.c
new file mode 100644
index 00000000000..f6058cf8b4d
--- /dev/null
+++ b/sys/arch/arc/pica/picabus.c
@@ -0,0 +1,323 @@
+/* $OpenBSD: picabus.c,v 1.1 1996/06/24 09:07:18 pefo Exp $ */
+/* $NetBSD: tc.c,v 1.2 1995/03/08 00:39:05 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ * Author: Per Fogelstrom. (Mips R4x00)
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+#include <machine/autoconf.h>
+
+#include <arc/pica/pica.h>
+#include <arc/arc/arctype.h>
+
+struct pica_softc {
+ struct device sc_dv;
+ struct abus sc_bus;
+ struct pica_dev *sc_devs;
+};
+
+/* Definition of the driver for autoconfig. */
+int picamatch(struct device *, void *, void *);
+void picaattach(struct device *, struct device *, void *);
+int picaprint(void *, char *);
+
+struct cfattach pica_ca = {
+ sizeof(struct pica_softc), picamatch, picaattach
+};
+struct cfdriver pica_cd = {
+ NULL, "pica", DV_DULL, NULL, 0
+};
+
+void pica_intr_establish __P((struct confargs *, int (*)(void *), void *));
+void pica_intr_disestablish __P((struct confargs *));
+caddr_t pica_cvtaddr __P((struct confargs *));
+int pica_matchname __P((struct confargs *, char *));
+int pica_iointr __P((void *));
+int pica_clkintr __P((unsigned, unsigned, unsigned, unsigned));
+
+extern int cputype;
+
+/*
+ * Interrupt dispatch table.
+ */
+struct pica_int_desc int_table[] = {
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 0 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 1 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 2 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 3 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 4 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 5 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 6 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 7 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 8 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 9 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 10 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 11 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 12 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 13 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 14 */
+ {0, pica_intrnull, (void *)NULL, 0 }, /* 15 */
+};
+
+struct pica_dev {
+ struct confargs ps_ca;
+ u_int ps_mask;
+ intr_handler_t ps_handler;
+ void *ps_base;
+};
+#ifdef ACER_PICA_61
+struct pica_dev acer_pica_61_cpu[] = {
+ {{ "dallas_rtc",0, 0, },
+ 0, pica_intrnull, (void *)PICA_SYS_CLOCK, },
+ {{ "lpt", 1, 0, },
+ PICA_SYS_LB_IE_PAR1, pica_intrnull, (void *)PICA_SYS_PAR1, },
+ {{ "fdc", 2, 0, },
+ PICA_SYS_LB_IE_FLOPPY,pica_intrnull, (void *)PICA_SYS_FLOPPY, },
+ {{ NULL, 3, NULL, },
+ 0, pica_intrnull, (void *)NULL, },
+ {{ NULL, 4, NULL, },
+ 0, pica_intrnull, (void *)NULL, },
+ {{ "sonic", 5, 0, },
+ PICA_SYS_LB_IE_SONIC, pica_intrnull, (void *)PICA_SYS_SONIC, },
+ {{ "asc", 6, 0, },
+ PICA_SYS_LB_IE_SCSI, pica_intrnull, (void *)PICA_SYS_SCSI, },
+ {{ "pc", 7, 0, },
+ PICA_SYS_LB_IE_KBD, pica_intrnull, (void *)PICA_SYS_KBD, },
+ {{ "pms", 8, NULL, },
+ PICA_SYS_LB_IE_MOUSE, pica_intrnull, (void *)PICA_SYS_KBD, },
+ {{ "com", 9, 0, },
+ PICA_SYS_LB_IE_COM1, pica_intrnull, (void *)PICA_SYS_COM1, },
+ {{ "com", 10, 0, },
+ PICA_SYS_LB_IE_COM2, pica_intrnull, (void *)PICA_SYS_COM2, },
+ {{ NULL, -1, NULL, },
+ 0, NULL, (void *)NULL, },
+};
+#endif
+
+struct pica_dev *pica_cpu_devs[] = {
+ NULL, /* Unused */
+#ifdef ACER_PICA_61
+ acer_pica_61_cpu, /* Acer PICA */
+#else
+ NULL,
+#endif
+};
+int npica_cpu_devs = sizeof pica_cpu_devs / sizeof pica_cpu_devs[0];
+
+int local_int_mask = 0; /* Local interrupt enable mask */
+
+int
+picamatch(parent, cfdata, aux)
+ struct device *parent;
+ void *cfdata;
+ void *aux;
+{
+ struct cfdata *cf = cfdata;
+ struct confargs *ca = aux;
+
+ /* Make sure that we're looking for a PICA. */
+ if (strcmp(ca->ca_name, pica_cd.cd_name) != 0)
+ return (0);
+
+ /* Make sure that unit exists. */
+ if (cf->cf_unit != 0 ||
+ cputype > npica_cpu_devs || pica_cpu_devs[cputype] == NULL)
+ return (0);
+
+ return (1);
+}
+
+void
+picaattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct pica_softc *sc = (struct pica_softc *)self;
+ struct confargs *nca;
+ int i;
+
+ printf("\n");
+
+ /* keep our CPU device description handy */
+ sc->sc_devs = pica_cpu_devs[cputype];
+
+ /* set up interrupt handlers */
+ set_intr(INT_MASK_1, pica_iointr, 2);
+
+ sc->sc_bus.ab_dv = (struct device *)sc;
+ sc->sc_bus.ab_type = BUS_PICA;
+ sc->sc_bus.ab_intr_establish = pica_intr_establish;
+ sc->sc_bus.ab_intr_disestablish = pica_intr_disestablish;
+ sc->sc_bus.ab_cvtaddr = pica_cvtaddr;
+ sc->sc_bus.ab_matchname = pica_matchname;
+
+ /* Initialize PICA Dma */
+ picaDmaInit();
+
+ /* Try to configure each PICA attached device */
+ for (i = 0; sc->sc_devs[i].ps_ca.ca_slot >= 0; i++) {
+
+ if(sc->sc_devs[i].ps_ca.ca_name == NULL)
+ continue; /* Empty slot */
+
+ nca = &sc->sc_devs[i].ps_ca;
+ nca->ca_bus = &sc->sc_bus;
+
+ /* Tell the autoconfig machinery we've found the hardware. */
+ config_found(self, nca, picaprint);
+ }
+}
+
+int
+picaprint(aux, pnp)
+ void *aux;
+ char *pnp;
+{
+ struct confargs *ca = aux;
+
+ if (pnp)
+ printf("%s at %s", ca->ca_name, pnp);
+ printf(" slot %ld offset 0x%lx", ca->ca_slot, ca->ca_offset);
+ return (UNCONF);
+}
+
+caddr_t
+pica_cvtaddr(ca)
+ struct confargs *ca;
+{
+ struct pica_softc *sc = pica_cd.cd_devs[0];
+
+ return(sc->sc_devs[ca->ca_slot].ps_base + ca->ca_offset);
+
+}
+
+void
+pica_intr_establish(ca, handler, val)
+ struct confargs *ca;
+ intr_handler_t handler;
+ void *val;
+{
+ struct pica_softc *sc = pica_cd.cd_devs[0];
+
+ int slot;
+
+ slot = ca->ca_slot;
+ if(slot == 0) { /* Slot 0 is special, clock */
+ set_intr(INT_MASK_4, pica_clkintr, 1);
+ }
+
+ if(int_table[slot].int_mask != 0) {
+ panic("pica intr already set");
+ }
+ else {
+ int_table[slot].int_mask = sc->sc_devs[slot].ps_mask;;
+ local_int_mask |= int_table[slot].int_mask;
+ int_table[slot].int_hand = handler;
+ int_table[slot].param = val;
+ }
+ out16(PICA_SYS_LB_IE, local_int_mask);
+}
+
+void
+pica_intr_disestablish(ca)
+ struct confargs *ca;
+{
+ struct pica_softc *sc = pica_cd.cd_devs[0];
+
+ int slot;
+
+ slot = ca->ca_slot;
+ if(slot = 0) { /* Slot 0 is special, clock */
+ }
+ else {
+ local_int_mask &= ~int_table[slot].int_mask;
+ int_table[slot].int_mask = 0;
+ int_table[slot].int_hand = pica_intrnull;
+ int_table[slot].param = (void *)NULL;
+ }
+}
+
+int
+pica_matchname(ca, name)
+ struct confargs *ca;
+ char *name;
+{
+ return (strcmp(name, ca->ca_name) == 0);
+}
+
+int
+pica_intrnull(val)
+ void *val;
+{
+ panic("uncaught PICA intr for slot %d\n", val);
+}
+
+/*
+ * Handle pica i/o interrupt.
+ */
+int
+pica_iointr(val)
+ void *val;
+{
+ int vector;
+
+ while((vector = inb(PVIS) >> 2) != 0) {
+ (*int_table[vector].int_hand)(int_table[vector].param);
+ }
+ return(~0); /* Dont reenable */
+}
+
+/*
+ * Handle pica interval clock interrupt.
+ */
+int
+pica_clkintr(mask, pc, statusReg, causeReg)
+ unsigned mask;
+ unsigned pc;
+ unsigned statusReg;
+ unsigned causeReg;
+{
+ struct clockframe cf;
+ int temp;
+
+ temp = inw(PICA_SYS_IT_STAT);
+ cf.pc = pc;
+ cf.sr = statusReg;
+ hardclock(&cf);
+
+ /* Re-enable clock interrupts */
+ splx(INT_MASK_4 | SR_INT_ENAB);
+
+ return(~INT_MASK_4); /* Keep clock interrupts enabled */
+}
+
diff --git a/sys/arch/arc/stand/Makefile b/sys/arch/arc/stand/Makefile
new file mode 100644
index 00000000000..a7dd6383200
--- /dev/null
+++ b/sys/arch/arc/stand/Makefile
@@ -0,0 +1,96 @@
+# $NetBSD: Makefile,v 1.5 1995/01/18 06:53:36 mellon Exp $
+# @(#)Makefile 8.3 (Berkeley) 2/16/94
+
+DESTDIR=
+STAND= ../../stand
+#VPATH= ${STAND}
+
+# RELOC=80200000 allows for boot prog up to 1D0000 (1900544) bytes long
+RELOC= 80200000
+
+S= ../../..
+
+DEFS= -DSTANDALONE -DDEBUG
+CFLAGS= -O2 ${INCPATH} ${DEFS}
+AFLAGS= -O2 ${INCPATH} ${DEFS} -DLOCORE
+
+.PATH: ${S}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
+.PATH: ${S}/stand ${S}/lib/libsa
+
+#INCPATH=-I. -I/sys
+INCPATH=-I${.CURDIR} -I${.CURDIR}/../.. -I${S} -I${S}/lib/libsa
+
+### find out what to use for libkern
+.include "$S/lib/libkern/Makefile.inc"
+LIBKERN= ${KERNLIB}
+#KERNLIB= ${.CURDIR}/../compile/libkern.a
+
+.include "$S/lib/libsa/Makefile.inc"
+LIBSA= ${SA_LIB}
+
+# not yet: need to write libsa/Makefile.inc first
+LIBS= ${.OBJDIR}/libdrive.a ${.CURDIR}/libsa/libsa.a ${KERNLIB}
+#LIBS= libdrive.a libsa/libsa.a ../../libkern/obj/libkern.a
+
+DRIVERS= rz.c
+SRCS= ${DRIVERS}
+#STUFF= callvec.c devopen.c getenv.c gets.c strcmp.c
+STUFF=
+
+ALL= boot
+
+.s.o:
+ ${CPP} -E ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} | \
+ ${AS} -o ${.TARGET}
+
+all: ${ALL}
+
+boot: ${LIBS}
+
+#libsa/libsa.a::
+# cd libsa; make
+
+${.OBJDIR}/libdrive.a: conf.o ${DRIVERS:.c=.o}
+ ar crv $@ $?
+ ranlib $@
+
+# depend on DEFS
+
+#before other deps on bootconf.o
+bootconf.o: conf.o
+ rm -f bootconf.c
+ ln -s ${.CURDIR}/conf.c bootconf.c
+ ${CC} -c ${CFLAGS} -DBOOT bootconf.c
+ rm -f bootconf.c
+
+
+# bootable from real disks
+
+boot: start.o boot.o bootconf.o filesystem.o ${LIBS}
+ /usr/gnu/ld -N -Ttext ${RELOC} -e __start start.o boot.o bootconf.o filesystem.o ${LIBS} -o boot.elf
+ elf2ecoff boot.elf boot
+
+start.o: ${.CURDIR}/start.S
+
+# ${CPP} -E ${CFLAGS:M-[ID]*} -DLOCORE ${AINC} ${.IMPSRC} | \
+# ${AS} -o ${.TARGET}
+
+mkboot: ${.CURDIR}/mkboot.c
+ ${CC} ${CFLAGS} -o mkboot ${.CURDIR}/mkboot.c
+
+# utilities
+
+clean::
+ rm -f .depend *.o *.exe *.i errs make.out core*
+ rm -f a.out ${ALL}
+ rm -f libdrive.a
+ cd libsa; make cleandir
+
+install:
+
+depend: ${SRCS}
+ mkdep ${INCPATH} ${DEFS} ${SRCS}
+ cd libsa; make depend
+
+.include <bsd.dep.mk>
+.include <bsd.obj.mk>
diff --git a/sys/arch/arc/stand/boot.c b/sys/arch/arc/stand/boot.c
new file mode 100644
index 00000000000..170f6f923de
--- /dev/null
+++ b/sys/arch/arc/stand/boot.c
@@ -0,0 +1,114 @@
+/* $NetBSD: boot.c,v 1.6 1995/06/28 10:22:32 jonathan Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)boot.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <stand.h>
+
+
+char line[1024];
+
+/*
+ * This gets arguments from the PROM, calls other routines to open
+ * and load the program to boot, and then transfers execution to that
+ * new program.
+ * Argv[0] should be something like "rz(0,0,0)vmunix" on a DECstation 3100.
+ * Argv[0,1] should be something like "boot 5/rz0/vmunix" on a DECstation 5000.
+ * The argument "-a" means vmunix should do an automatic reboot.
+ */
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *cp;
+ int ask, entry;
+ int i;
+
+ ask = 1;
+
+ for(i = 0; i < argc; i++)
+ printf("Arg %d:%s\n",i,argv[i]);
+
+ do {
+ printf("Boot: ");
+ if (ask) {
+ gets(line);
+ cp = line;
+ argv[0] = cp;
+ argc = 1;
+ } else
+ printf("%s\n", cp);
+ } while(ask && line[0] == '\0');
+
+ entry = loadfile(cp);
+ if (entry == -1) {
+ gets(line);
+ return 0;
+ }
+
+ printf("Starting at 0x%x\n\n", entry);
+ ((void (*)())entry)(argc, argv, 0, 0);
+}
+
+/*
+ * Open 'filename', read in program and return the entry point or -1 if error.
+ */
+loadfile(fname)
+ register char *fname;
+{
+ struct devices *dp;
+ int fd, i, n;
+ struct exec aout;
+
+ if ((fd = open(fname, 0)) < 0) {
+ printf("open(%s) failed: %d\n", fname, errno);
+ goto err;
+ }
+
+ /* read the exec header */
+ i = read(fd, (char *)&aout, sizeof(aout));
+
+cerr:
+ (void) close(fd);
+err:
+ printf("Can't boot '%s'\n", fname);
+ return (-1);
+}
diff --git a/sys/arch/arc/stand/conf.c b/sys/arch/arc/stand/conf.c
new file mode 100644
index 00000000000..cecbc70b64c
--- /dev/null
+++ b/sys/arch/arc/stand/conf.c
@@ -0,0 +1,70 @@
+/* $NetBSD: conf.c,v 1.5 1995/01/18 06:53:39 mellon Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)conf.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <stand.h>
+
+int errno;
+
+extern void nullsys();
+extern int nodev(), noioctl();
+
+int rzstrategy(), rzopen();
+#ifdef SMALL
+#define rzclose 0
+#else /*!SMALL*/
+int rzclose();
+#endif /*!SMALL*/
+
+#define rzioctl noioctl
+
+#ifndef BOOT
+int tzstrategy(), tzopen(), tzclose();
+#endif
+#define tzioctl noioctl
+
+
+struct devsw devsw[] = {
+ { "rz", rzstrategy, rzopen, rzclose, rzioctl }, /*0*/
+#ifndef BOOT
+ { "tz", tzstrategy, tzopen, tzclose, tzioctl }, /*1*/
+#endif
+};
+
+int ndevs = (sizeof(devsw)/sizeof(devsw[0]));
diff --git a/sys/arch/arc/stand/filesystem.c b/sys/arch/arc/stand/filesystem.c
new file mode 100644
index 00000000000..514e6e809bf
--- /dev/null
+++ b/sys/arch/arc/stand/filesystem.c
@@ -0,0 +1,44 @@
+/* $NetBSD: filesystem.c,v 1.2 1995/02/16 02:33:05 cgd Exp $ */
+
+/*
+ * Copyright (c) 1993 Philip A. Nelson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Philip A. Nelson.
+ * 4. The name of Philip A. Nelson may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PHILIP NELSON BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * filesystem.c
+ */
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/ufs.h>
+
+struct fs_ops file_system[] = {
+ { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat },
+};
+
+int nfsys = sizeof(file_system)/sizeof(struct fs_ops);
+
diff --git a/sys/arch/arc/stand/libsa/Makefile b/sys/arch/arc/stand/libsa/Makefile
new file mode 100644
index 00000000000..d147171311d
--- /dev/null
+++ b/sys/arch/arc/stand/libsa/Makefile
@@ -0,0 +1,14 @@
+# $NetBSD: Makefile,v 1.5 1995/01/18 06:53:51 mellon Exp $
+# @(#)Makefile 8.2 (Berkeley) 2/16/94
+
+LIB= sa
+SRCS= alloc.c bcopy.c bzero.c close.c dev.c disklabel.c getfile.c \
+ getputchar.c ioctl.c lseek.c open.c printf.c read.c ufs.c write.c \
+ devopen.c getenv.c gets.c strcat.c strcmp.c strcpy.c strlen.c
+
+.PATH: ../../../../lib/libsa ../../../../lib/libkern
+NOPROFILE=noprofile
+
+.include <bsd.lib.mk>
+
+CFLAGS=-O2 -I../../include -I/sys -DSMALL
diff --git a/sys/arch/arc/stand/libsa/devopen.c b/sys/arch/arc/stand/libsa/devopen.c
new file mode 100644
index 00000000000..79b35f8f595
--- /dev/null
+++ b/sys/arch/arc/stand/libsa/devopen.c
@@ -0,0 +1,128 @@
+/* $NetBSD: devopen.c,v 1.5 1995/01/18 06:53:54 mellon Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)devopen.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <lib/libsa/stand.h>
+
+/*
+ * Decode the string 'fname', open the device and return the remaining
+ * file name if any.
+ */
+devopen(f, fname, file)
+ struct open_file *f;
+ const char *fname;
+ char **file; /* out */
+{
+ register char *cp;
+ register char *ncp;
+ register struct devsw *dp;
+ register int c, i;
+ int ctlr = 0, unit = 0, part = 0;
+ char namebuf[20];
+ int rc;
+
+ cp = fname;
+ ncp = namebuf;
+
+ /* expect a string like 'rz(0,0,0)vmunix' */
+ while ((c = *cp) != '\0') {
+ if (c == '(') {
+ cp++;
+ break;
+ }
+ if (ncp < namebuf + sizeof(namebuf) - 1)
+ *ncp++ = c;
+ cp++;
+ }
+
+ /* get controller number */
+ if ((c = *cp) >= '0' && c <= '9') {
+ ctlr = c - '0';
+ c = *++cp;
+ }
+
+ if (c == ',') {
+ /* get SCSI device number */
+ if ((c = *++cp) >= '0' && c <= '9') {
+ unit = c - '0';
+ c = *++cp;
+ }
+
+ if (c == ',') {
+ /* get partition number */
+ if ((c = *++cp) >= '0' && c <= '9') {
+ part = c - '0';
+ c = *++cp;
+ }
+ }
+ }
+ if (c != ')')
+ return (ENXIO);
+ cp++;
+ *ncp = '\0';
+
+#ifdef SMALL
+ if (strcmp (namebuf, "rz")) {
+ printf ("Unknown device: %s\n", namebuf);
+ return ENXIO;
+ }
+ dp = devsw;
+ i = 0;
+#else
+ for (dp = devsw, i = 0; i < ndevs; dp++, i++)
+ if (dp->dv_name && strcmp(namebuf, dp->dv_name) == 0)
+ goto fnd;
+ printf("Unknown device '%s'\nKnown devices are:", namebuf);
+ for (dp = devsw, i = 0; i < ndevs; dp++, i++)
+ if (dp->dv_name)
+ printf(" %s", dp->dv_name);
+ printf("\n");
+ return (ENXIO);
+
+fnd:
+#endif
+ rc = (dp->dv_open)(f, ctlr, unit, part);
+ if (rc)
+ return (rc);
+
+ f->f_dev = dp;
+ if (file && *cp != '\0')
+ *file = cp;
+ return (0);
+}
diff --git a/sys/arch/arc/stand/libsa/getenv.c b/sys/arch/arc/stand/libsa/getenv.c
new file mode 100644
index 00000000000..7e063cd4ad5
--- /dev/null
+++ b/sys/arch/arc/stand/libsa/getenv.c
@@ -0,0 +1,45 @@
+/* $NetBSD: getenv.c,v 1.5 1995/01/18 06:53:55 mellon Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)getenv.c 8.1 (Berkeley) 6/10/93
+ */
+
+char *
+getenv(s)
+ char *s;
+{
+}
diff --git a/sys/arch/arc/stand/libsa/getputchar.c b/sys/arch/arc/stand/libsa/getputchar.c
new file mode 100644
index 00000000000..dbfae22d4d6
--- /dev/null
+++ b/sys/arch/arc/stand/libsa/getputchar.c
@@ -0,0 +1,69 @@
+/* $NetBSD: getenv.c,v 1.5 1995/01/18 06:53:55 mellon Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)getenv.c 8.1 (Berkeley) 6/10/93
+ */
+
+getchar()
+{
+ char buf[4];
+ int cnt;
+
+ if(Bios_Read(0, &buf, 1, &cnt) != 0)
+ return(-1);
+ return(buf[0] & 255);
+}
+
+putchar(c)
+char c;
+{
+ char buf[4];
+ int cnt;
+
+ if(c == '\n') {
+ buf[0] = '\r';
+ buf[1] = c;
+ cnt = 2;
+ }
+ else {
+ buf[0] = c;
+ cnt = 1;
+ }
+ if(Bios_Write(1, &buf, cnt, &cnt) != 0)
+ return(-1);
+ return(0);
+}
diff --git a/sys/arch/arc/stand/rz.c b/sys/arch/arc/stand/rz.c
new file mode 100644
index 00000000000..1094aef4705
--- /dev/null
+++ b/sys/arch/arc/stand/rz.c
@@ -0,0 +1,174 @@
+/* $NetBSD: rz.c,v 1.6 1995/06/28 10:22:35 jonathan Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)rz.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <stdarg.h>
+
+#include <stand.h>
+#include <sys/param.h>
+#include <sys/disklabel.h>
+
+struct rz_softc {
+ int sc_fd; /* PROM file id */
+ int sc_ctlr; /* controller number */
+ int sc_unit; /* disk unit number */
+ int sc_part; /* disk partition number */
+ struct disklabel sc_label; /* disk label for this disk */
+};
+
+int
+rzstrategy(devdata, rw, bn, reqcnt, addr, cnt)
+ void *devdata;
+ int rw;
+ daddr_t bn;
+ u_int reqcnt;
+ char *addr;
+ u_int *cnt; /* out: number of bytes transfered */
+{
+ register struct rz_softc *sc = (struct rz_softc *)devdata;
+ register int part = sc->sc_part;
+ register struct partition *pp = &sc->sc_label.d_partitions[part];
+ register int s;
+ long offset;
+
+ offset = bn * DEV_BSIZE;
+
+#ifdef DEBUG
+/*XXX*/printf("rz:%x %d\n", offset, reqcnt);
+#endif
+
+ /*
+ * Partial-block transfers not handled.
+ */
+ if (reqcnt & (DEV_BSIZE - 1)) {
+ *cnt = 0;
+ return (EINVAL);
+ }
+
+ offset += pp->p_offset * DEV_BSIZE;
+
+ if (Bios_Seek(sc->sc_fd, &offset, 0) != 0)
+ return (EIO);
+ s = Bios_Read(sc->sc_fd, addr, reqcnt, &reqcnt);
+ if (s != 0)
+ return (EIO);
+
+ *cnt = reqcnt;
+ return (0);
+}
+
+int
+rzopen(struct open_file *f, ...)
+{
+ int ctlr, unit, part;
+
+ struct rz_softc *sc;
+ struct disklabel *lp;
+ int i, fd;
+ char *msg;
+ char buf[DEV_BSIZE];
+ int cnt;
+ static char device[] = "scsi()disk(0)rdisk()";
+ va_list ap;
+
+ va_start(ap, f);
+
+ ctlr = va_arg(ap, int);
+ unit = va_arg(ap, int);
+ part = va_arg(ap, int);
+ if (unit >= 8 || part >= 8)
+ return (ENXIO);
+#if 0
+ device[5] = '0' + unit;
+#endif
+ /* NOTE: only support reads for now */
+
+ i = Bios_Open(device, 0, &fd);
+ if (i != 0) {
+ printf("boot init failed error code %d\n", i);
+ return (ENXIO);
+ }
+
+ sc = alloc(sizeof(struct rz_softc));
+ bzero(sc, sizeof(struct rz_softc));
+ f->f_devdata = (void *)sc;
+
+ sc->sc_fd = fd;
+ sc->sc_ctlr = ctlr;
+ sc->sc_unit = unit;
+ sc->sc_part = part;
+
+ /* try to read disk label and partition table information */
+ lp = &sc->sc_label;
+ lp->d_secsize = DEV_BSIZE;
+ lp->d_secpercyl = 1;
+ lp->d_npartitions = MAXPARTITIONS;
+ lp->d_partitions[part].p_offset = 0;
+ lp->d_partitions[part].p_size = 0x7fffffff;
+ i = rzstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt);
+ if (i || cnt != DEV_BSIZE) {
+ printf("rz%d: error reading disk label\n", unit);
+ goto bad;
+ } else {
+ msg = getdisklabel(buf, lp);
+ if (msg) {
+ printf("rz%d: %s\n", unit, msg);
+ goto bad;
+ }
+ }
+
+ if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) {
+ bad:
+#ifndef SMALL
+ free(sc, sizeof(struct rz_softc));
+#endif
+ return (ENXIO);
+ }
+ return (0);
+}
+
+#ifndef SMALL
+rzclose(f)
+ struct open_file *f;
+{
+ free(f->f_devdata, sizeof(struct rz_softc));
+ f->f_devdata = (void *)0;
+ return (0);
+}
+#endif
diff --git a/sys/arch/arc/stand/start.S b/sys/arch/arc/stand/start.S
new file mode 100644
index 00000000000..09114a91b7e
--- /dev/null
+++ b/sys/arch/arc/stand/start.S
@@ -0,0 +1,129 @@
+/* $NetBSD: start.S,v 1.1 1995/01/18 06:19:01 mellon Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * start.S -
+ *
+ * Contains code that is the first executed at boot time.
+ */
+
+#include <machine/regdef.h>
+#include <machine/cpu.h>
+#include <machine/asm.h>
+
+/*
+ * Frame required for the debugger (if we have any)
+ */
+#define START_FRAME ((4 * 4) + 4 + 4)
+
+ .globl __start
+__start:
+ .set noreorder
+#ifdef __GP_SUPPORT__
+ la gp, _C_LABEL (_gp)
+#endif
+ la sp, __start - START_FRAME # Stack below program
+ sw zero, START_FRAME - 4(sp) # Zero out old ra for debugger
+ sw zero, START_FRAME - 8(sp) # Zero out old fp for debugger
+ move s0, a0 # save argc
+ move s1, a1 # save argv
+
+ la a0, _C_LABEL (edata) # clear BSS
+ la a1, _C_LABEL (end)
+ jal _C_LABEL(bzero) # bzero(edata, end - edata)
+ subu a1, a1, a0
+
+ move a0, s0 # restore argc
+ jal _C_LABEL(main) # main(argc, argv)
+ move a1, s1 # restore argv
+
+ j _C_LABEL(Bios_Restart) # restart...
+ nop
+
+/* dummy routine for gcc2 */
+ .globl _C_LABEL(__main)
+_C_LABEL(__main):
+ j ra
+ nop
+
+#define Bios_Call(Name,Offset) \
+LEAF(Name); \
+ lw v0,0x80001020; \
+ lw v0,Offset(v0); \
+ jr v0 ; \
+ nop ; \
+ END(Name)
+
+Bios_Call(Bios_Load, 0x00)
+Bios_Call(Bios_Invoke, 0x04)
+Bios_Call(Bios_Execute, 0x08)
+Bios_Call(Bios_Halt, 0x0c)
+Bios_Call(Bios_PowerDown, 0x10)
+Bios_Call(Bios_Restart, 0x14)
+Bios_Call(Bios_Reboot, 0x18)
+Bios_Call(Bios_EnterInteractiveMode, 0x1c)
+Bios_Call(Bios_Unused1, 0x20)
+Bios_Call(Bios_GetPeer, 0x24)
+Bios_Call(Bios_GetChild, 0x28)
+Bios_Call(Bios_GetParent, 0x2c)
+Bios_Call(Bios_GetConfigurationData, 0x30)
+Bios_Call(Bios_AddChild, 0x34)
+Bios_Call(Bios_DeleteComponent, 0x38)
+Bios_Call(Bios_GetComponent, 0x3c)
+Bios_Call(Bios_SaveConfiguration, 0x40)
+Bios_Call(Bios_GetSystemId, 0x44)
+Bios_Call(Bios_GetMemoryDescriptor, 0x48)
+Bios_Call(Bios_Unused2, 0x4c)
+Bios_Call(Bios_GetTime, 0x50)
+Bios_Call(Bios_GetRelativeTime, 0x54)
+Bios_Call(Bios_GetDirectoryEntry, 0x58)
+Bios_Call(Bios_Open, 0x5c)
+Bios_Call(Bios_Close, 0x60)
+Bios_Call(Bios_Read, 0x64)
+Bios_Call(Bios_GetReadStatus, 0x68)
+Bios_Call(Bios_Write, 0x6c)
+Bios_Call(Bios_Seek, 0x70)
+Bios_Call(Bios_Mount, 0x74)
+Bios_Call(Bios_GetEnvironmentVariable, 0x78)
+Bios_Call(Bios_SetEnvironmentVariable, 0x7c)
+Bios_Call(Bios_GetFileInformation, 0x80)
+Bios_Call(Bios_SetFileInformation, 0x84)
+Bios_Call(Bios_FlushAllCaches, 0x88)
+Bios_Call(Bios_TestUnicodeCharacter, 0x8c)
+Bios_Call(Bios_GetDisplayStatus, 0x90)