merge in hp300 support from Utah
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Wed, 9 May 1990 09:15:43 +0000 (01:15 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Wed, 9 May 1990 09:15:43 +0000 (01:15 -0800)
SCCS-vsn: sys/hp300/hp300/clockioctl.h 7.1
SCCS-vsn: sys/hp300/hp300/clockreg.h 7.1
SCCS-vsn: sys/hp/dev/cons.h 7.1
SCCS-vsn: sys/hp300/include/cpu.h 7.1
SCCS-vsn: sys/hp300/include/float.h 7.1
SCCS-vsn: sys/hp300/include/frame.h 7.1
SCCS-vsn: sys/hp300/hp300/isr.h 7.1
SCCS-vsn: sys/hp300/include/mtpr.h 7.1
SCCS-vsn: sys/hp300/include/param.h 7.1
SCCS-vsn: sys/hp300/include/pcb.h 7.1
SCCS-vsn: sys/hp300/hp300/pte.h 7.1
SCCS-vsn: sys/hp300/include/psl.h 7.1
SCCS-vsn: sys/hp300/include/reg.h 7.1
SCCS-vsn: sys/hp300/include/trap.h 7.1
SCCS-vsn: sys/hp300/include/vmparam.h 7.1
SCCS-vsn: sys/hp300/hp300/autoconf.c 7.1
SCCS-vsn: sys/hp300/hp300/clock.c 7.1
SCCS-vsn: sys/hp300/hp300/conf.c 7.1
SCCS-vsn: sys/hp/dev/cons.c 7.1
SCCS-vsn: sys/hp300/hp300/dkbad.c 7.1
SCCS-vsn: sys/hp300/hp300/genassym.c 7.1
SCCS-vsn: sys/hp300/hp300/in_cksum.c 7.1
SCCS-vsn: sys/hp300/hp300/kgdb_stub.c 7.1
SCCS-vsn: sys/hp300/hp300/machdep.c 7.1
SCCS-vsn: sys/hp300/hp300/mem.c 7.1
SCCS-vsn: sys/hp300/hp300/ns_cksum.c 7.1
SCCS-vsn: sys/hp300/hp300/swapgeneric.c 7.1
SCCS-vsn: sys/hp300/hp300/sys_machdep.c 7.1
SCCS-vsn: sys/hp300/hp300/trap.c 7.1
SCCS-vsn: sys/hp300/hp300/vm_machdep.c 7.1
SCCS-vsn: sys/hp300/hp300/locore.s 7.1
SCCS-vsn: sys/hp300/hp300/oc_cksum.s 7.1
SCCS-vsn: sys/hp300/hp300/vectors.s 7.1

33 files changed:
usr/src/sys/hp/dev/cons.c [new file with mode: 0644]
usr/src/sys/hp/dev/cons.h [new file with mode: 0644]
usr/src/sys/hp300/hp300/autoconf.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/clock.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/clockioctl.h [new file with mode: 0644]
usr/src/sys/hp300/hp300/clockreg.h [new file with mode: 0644]
usr/src/sys/hp300/hp300/conf.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/dkbad.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/genassym.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/in_cksum.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/isr.h [new file with mode: 0644]
usr/src/sys/hp300/hp300/kgdb_stub.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/locore.s [new file with mode: 0644]
usr/src/sys/hp300/hp300/machdep.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/mem.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/ns_cksum.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/oc_cksum.s [new file with mode: 0644]
usr/src/sys/hp300/hp300/pte.h [new file with mode: 0644]
usr/src/sys/hp300/hp300/swapgeneric.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/sys_machdep.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/trap.c [new file with mode: 0644]
usr/src/sys/hp300/hp300/vectors.s [new file with mode: 0644]
usr/src/sys/hp300/hp300/vm_machdep.c [new file with mode: 0644]
usr/src/sys/hp300/include/cpu.h [new file with mode: 0644]
usr/src/sys/hp300/include/float.h [new file with mode: 0644]
usr/src/sys/hp300/include/frame.h [new file with mode: 0644]
usr/src/sys/hp300/include/mtpr.h [new file with mode: 0644]
usr/src/sys/hp300/include/param.h [new file with mode: 0644]
usr/src/sys/hp300/include/pcb.h [new file with mode: 0644]
usr/src/sys/hp300/include/psl.h [new file with mode: 0644]
usr/src/sys/hp300/include/reg.h [new file with mode: 0644]
usr/src/sys/hp300/include/trap.h [new file with mode: 0644]
usr/src/sys/hp300/include/vmparam.h [new file with mode: 0644]

diff --git a/usr/src/sys/hp/dev/cons.c b/usr/src/sys/hp/dev/cons.c
new file mode 100644 (file)
index 0000000..cfb0791
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: cons.c 1.4 88/12/03$
+ *
+ *     @(#)cons.c      7.1 (Berkeley) %G%
+ */
+
+#include "param.h"
+#include "user.h"
+#include "systm.h"
+#include "buf.h"
+#include "ioctl.h"
+#include "tty.h"
+#include "file.h"
+#include "conf.h"
+
+#include "cons.h"
+
+/* XXX - all this could be autoconfig()ed */
+#include "ite.h"
+#if NITE > 0
+int itecnprobe(), itecninit(), itecngetc(), itecnputc();
+#endif
+#include "dca.h"
+#if NDCA > 0
+int dcacnprobe(), dcacninit(), dcacngetc(), dcacnputc();
+#endif
+
+struct consdev constab[] = {
+#if NITE > 0
+       { itecnprobe,   itecninit,      itecngetc,      itecnputc },
+#endif
+#if NDCA > 0
+       { dcacnprobe,   dcacninit,      dcacngetc,      dcacnputc },
+#endif
+       { 0 },
+};
+/* end XXX */
+
+extern struct consdev constab[];
+
+struct tty *constty = 0;       /* virtual console output device */
+struct consdev *cn_tab;        /* physical console device info */
+struct tty *cn_tty;            /* XXX: console tty struct for tprintf */
+
+cninit()
+{
+       register struct consdev *cp;
+
+       /*
+        * Collect information about all possible consoles
+        * and find the one with highest priority
+        */
+       for (cp = constab; cp->cn_probe; cp++) {
+               (*cp->cn_probe)(cp);
+               if (cp->cn_pri > CN_DEAD &&
+                   (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri))
+                       cn_tab = cp;
+       }
+       /*
+        * No console, we can handle it
+        */
+       if ((cp = cn_tab) == NULL)
+               return;
+       /*
+        * Turn on console
+        */
+       cn_tty = cp->cn_tp;
+       (*cp->cn_init)(cp);
+}
+
+cnopen(dev, flag)
+       dev_t dev;
+{
+       if (cn_tab == NULL)
+               return(0);
+       dev = cn_tab->cn_dev;
+       return ((*cdevsw[major(dev)].d_open)(dev, flag));
+}
+cnclose(dev, flag)
+       dev_t dev;
+{
+       if (cn_tab == NULL)
+               return(0);
+       dev = cn_tab->cn_dev;
+       return ((*cdevsw[major(dev)].d_close)(dev, flag));
+}
+cnread(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       if (cn_tab == NULL)
+               return(0);
+       dev = cn_tab->cn_dev;
+       return ((*cdevsw[major(dev)].d_read)(dev, uio));
+}
+cnwrite(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       if (cn_tab == NULL)
+               return(0);
+       dev = cn_tab->cn_dev;
+       return ((*cdevsw[major(dev)].d_write)(dev, uio));
+}
+cnioctl(dev, cmd, data, flag)
+       dev_t dev;
+       caddr_t data;
+{
+       int error;
+
+       if (cn_tab == NULL)
+               return(0);
+       /*
+        * Superuser can always use this to wrest control of console
+        * output from the "virtual" console.
+        */
+       if (cmd == TIOCCONS && constty) {
+               error = suser(u.u_cred, &u.u_acflag);
+               if (error)
+                       return (error);
+               constty = NULL;
+               return (0);
+       }
+       dev = cn_tab->cn_dev;
+       return ((*cdevsw[major(dev)].d_ioctl)(dev, cmd, data, flag));
+}
+
+/*ARGSUSED*/
+cnselect(dev, rw)
+       dev_t dev;
+       int rw;
+{
+       if (cn_tab == NULL)
+               return(1);
+       return(ttselect(cn_tab->cn_dev, rw));
+}
+
+cngetc()
+{
+       if (cn_tab == NULL)
+               return(0);
+       return((*cn_tab->cn_getc)(cn_tab->cn_dev));
+}
+
+cnputc(c)
+       register int c;
+{
+       if (cn_tab == NULL)
+               return;
+       if (c) {
+               (*cn_tab->cn_putc)(cn_tab->cn_dev, c);
+               if (c == '\n')
+                       (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r');
+       }
+}
diff --git a/usr/src/sys/hp/dev/cons.h b/usr/src/sys/hp/dev/cons.h
new file mode 100644 (file)
index 0000000..9cb6261
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: cons.h 1.4 88/12/03$
+ *
+ *     @(#)cons.h      7.1 (Berkeley) %G%
+ */
+
+struct consdev {
+       int     (*cn_probe)();  /* probe hardware and fill in consdev info */
+       int     (*cn_init)();   /* turn on as console */
+       int     (*cn_getc)();   /* kernel getchar interface */
+       int     (*cn_putc)();   /* kernel putchar interface */
+       struct  tty *cn_tp;     /* tty structure for console device */
+       dev_t   cn_dev;         /* major/minor of device */
+       short   cn_pri;         /* pecking order; the higher the better */
+};
+
+/* values for cn_pri - reflect our policy for console selection */
+#define        CN_DEAD         0       /* device doesn't exist */
+#define CN_NORMAL      1       /* device exists but is nothing special */
+#define CN_INTERNAL    2       /* "internal" bit-mapped display */
+#define CN_REMOTE      3       /* serial interface with remote bit set */
+
+/* XXX */
+#define        CONSMAJOR       0
diff --git a/usr/src/sys/hp300/hp300/autoconf.c b/usr/src/sys/hp300/hp300/autoconf.c
new file mode 100644 (file)
index 0000000..ae5278d
--- /dev/null
@@ -0,0 +1,917 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: autoconf.c 1.25 89/10/07$
+ *
+ *     @(#)autoconf.c  7.1 (Berkeley) %G%
+ */
+
+/*
+ * 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 "param.h"
+#include "systm.h"
+#include "map.h"
+#include "buf.h"
+#include "dkstat.h"
+#include "vm.h"
+#include "conf.h"
+#include "dmap.h"
+#include "reboot.h"
+
+#include "pte.h"
+#include "cpu.h"
+#include "isr.h"
+#include "../hpdev/device.h"
+#include "../hpdev/grfioctl.h"
+#include "../hpdev/grfvar.h"
+
+/*
+ * The following several variables are related to
+ * the configuration process, and are used in initializing
+ * the machine.
+ */
+int    cold;               /* if 1, still working on cold-start */
+int    dkn;                /* number of iostat dk numbers assigned so far */
+int    cpuspeed = MHZ_8;   /* relative cpu speed */
+struct isr isrqueue[NISR];
+struct hp_hw sc_table[MAX_CTLR];
+
+#ifdef DEBUG
+int    acdebug = 0;
+#endif
+
+/*
+ * Determine mass storage and memory configuration for a machine.
+ */
+configure()
+{
+       register struct hp_hw *hw;
+       int found;
+
+       /*
+        * XXX: these should be consolidated into some kind of table
+        */
+       hilinit();
+       isrinit();
+       dmainit();
+
+       /*
+        * Look over each hardware device actually found and attempt
+        * to match it with an ioconf.c table entry.
+        */
+       for (hw = sc_table; hw->hw_type; hw++) {
+               if (hw->hw_type & CONTROLLER)
+                       found = find_controller(hw);
+               else
+                       found = find_device(hw);
+#ifdef DEBUG
+               if (!found) {
+                       int sc = addrtosc((u_int)hw->hw_addr);
+
+                       printf("unconfigured %s ", hw->hw_name);
+                       if (sc < 256)
+                               printf("at sc%d\n", sc);
+                       else
+                               printf("csr at %x\n", sc);
+               }
+#endif
+       }
+
+#include "cd.h"
+#if NCD > 0
+       /*
+        * Now deal with concatenated disks
+        */
+       find_cdevices();
+#endif
+
+#if GENERIC
+       if ((boothowto & RB_ASKNAME) == 0)
+               setroot();
+       setconf();
+#else
+       setroot();
+#endif
+       swapconf();
+       cold = 0;
+}
+
+#define dr_type(d, s)  \
+       ((d)->d_name[0] == (s)[0] && (d)->d_name[1] == (s)[1])
+
+#define same_hw_ctlr(hw, hc) \
+       ((hw)->hw_type == HPIB && dr_type((hc)->hp_driver, "hpib") || \
+        (hw)->hw_type == SCSI && dr_type((hc)->hp_driver, "scsi"))
+
+find_controller(hw)
+       register struct hp_hw *hw;
+{
+       register struct hp_ctlr *hc;
+       struct hp_ctlr *match_c;
+       caddr_t oaddr;
+       int sc;
+
+#ifdef DEBUG
+       if (acdebug)
+               printf("find_controller: hw: %s at sc%d (%x), type %x...",
+                      hw->hw_name, hw->hw_sc, hw->hw_addr, hw->hw_type);
+#endif
+       sc = hw->hw_sc;
+       match_c = NULL;
+       for (hc = hp_cinit; hc->hp_driver; hc++) {
+               if (hc->hp_alive)
+                       continue;
+               /*
+                * Make sure we are looking at the right
+                * controller type.
+                */
+               if (!same_hw_ctlr(hw, hc))
+                       continue;
+               /*
+                * Exact match; all done
+                */
+               if ((int)hc->hp_addr == sc) {
+                       match_c = hc;
+                       break;
+               }
+               /*
+                * Wildcard; possible match so remember first instance
+                * but continue looking for exact match.
+                */
+               if ((int)hc->hp_addr == WILD_CARD_CTLR && match_c == NULL)
+                       match_c = hc;
+       }
+#ifdef DEBUG
+       if (acdebug) {
+               if (match_c)
+                       printf("found %s%d\n",
+                              match_c->hp_driver->d_name,
+                              match_c->hp_unit);
+               else
+                       printf("not found\n");
+       }
+#endif
+       /*
+        * Didn't find an ioconf entry for this piece of hardware,
+        * just ignore it.
+        */
+       if (match_c == NULL)
+               return(0);
+       /*
+        * Found a match, attempt to initialize and configure all attached
+        * slaves.  Note, we can still fail if HW won't initialize.
+        */
+       hc = match_c;
+       oaddr = hc->hp_addr;
+       hc->hp_addr = hw->hw_addr;
+       if ((*hc->hp_driver->d_init)(hc)) {
+               hc->hp_alive = 1;
+               printf("%s%d", hc->hp_driver->d_name, hc->hp_unit);
+               sc = addrtosc((u_int)hc->hp_addr);
+               if (sc < 256)
+                       printf(" at sc%d,", sc);
+               else
+                       printf(" csr 0x%x,", sc);
+               printf(" ipl %d", hc->hp_ipl);
+               if (hc->hp_flags)
+                       printf(" flags 0x%x", hc->hp_flags);
+               printf("\n");
+               find_slaves(hc);
+       } else
+               hc->hp_addr = oaddr;
+       return(1);
+}
+
+find_device(hw)
+       register struct hp_hw *hw;
+{
+       register struct hp_device *hd;
+       struct hp_device *match_d;
+       caddr_t oaddr;
+       int sc;
+
+#ifdef DEBUG
+       if (acdebug)
+               printf("find_device: hw: %s at sc%d (%x), type %x...",
+                      hw->hw_name, hw->hw_sc, hw->hw_addr, hw->hw_type);
+#endif
+       match_d = NULL;
+       for (hd = hp_dinit; hd->hp_driver; hd++) {
+               if (hd->hp_alive)
+                       continue;
+               /* Must not be a slave */
+               if (hd->hp_cdriver)
+                       continue;
+               /*
+                * XXX: A graphics device that was found as part of the
+                * console init will have the hp_addr field already set
+                * (i.e. no longer the select code).  Gotta perform a
+                * slightly different check for an exact match.
+                */
+               if (hw->hw_type == BITMAP && hd->hp_addr >= (caddr_t)IOBASE) {
+                       /* must be an exact match */
+                       if (hd->hp_addr == hw->hw_addr) {
+                               match_d = hd;
+                               break;
+                       }
+                       continue;
+               }
+               sc = (int) hd->hp_addr;
+               /*
+                * Exact match; all done.
+                */
+               if (sc > 0 && sc == hw->hw_sc) {
+                       match_d = hd;
+                       break;
+               }
+               /*
+                * Wildcard; possible match so remember first instance
+                * but continue looking for exact match.
+                */
+               if (sc == 0 && same_hw_device(hw, hd) && match_d == NULL)
+                       match_d = hd;
+       }
+#ifdef DEBUG
+       if (acdebug) {
+               if (match_d)
+                       printf("found %s%d\n",
+                              match_d->hp_driver->d_name,
+                              match_d->hp_unit);
+               else
+                       printf("not found\n");
+       }
+#endif
+       /*
+        * Didn't find an ioconf entry for this piece
+        * of hardware, just ignore it.
+        */
+       if (match_d == NULL)
+               return(0);
+       /*
+        * Found a match, attempt to initialize.
+        * Note, we can still fail if HW won't initialize.
+        */
+       hd = match_d;
+       oaddr = hd->hp_addr;
+       hd->hp_addr = hw->hw_addr;
+       if ((*hd->hp_driver->d_init)(hd)) {
+               hd->hp_alive = 1;
+               printf("%s%d", hd->hp_driver->d_name, hd->hp_unit);
+               sc = addrtosc((u_int)hd->hp_addr);
+               if (sc < 32)
+                       printf(" at sc%d", sc);
+               else
+                       printf(" csr 0x%x", sc);
+               if (hd->hp_ipl)
+                       printf(", ipl %d", hd->hp_ipl);
+               if (hd->hp_flags)
+                       printf(", flags 0x%x", hd->hp_flags);
+               printf("\n");
+       } else
+               hd->hp_addr = oaddr;
+       return(1);
+}
+
+find_slaves(hc)
+       struct hp_ctlr *hc;
+{
+       /*
+        * The SCSI bus is structured very much like the HP-IB 
+        * except that the host adaptor is slave 7 so we only want
+        * to look at the first 6 slaves.
+        */
+       if (dr_type(hc->hp_driver, "hpib"))
+               find_busslaves(hc, MAXSLAVES);
+       else if (dr_type(hc->hp_driver, "scsi"))
+               find_busslaves(hc, MAXSLAVES-1);
+}
+
+/*
+ * Search each BUS controller found for slaves attached to it.
+ * The bad news is that we don't know how to uniquely identify all slaves
+ * (e.g. PPI devices on HP-IB).  The good news is that we can at least
+ * differentiate those from slaves we can identify.  At worst (a totally
+ * wildcarded entry) this will cause us to locate such a slave at the first
+ * unused position instead of where it really is.  To save grief, non-
+ * identifing devices should always be fully qualified.
+ */
+find_busslaves(hc, maxslaves)
+       register struct hp_ctlr *hc;
+       int maxslaves;
+{
+       register int s;
+       register struct hp_device *hd;
+       struct hp_device *match_s;
+       int new_s, new_c, old_s, old_c;
+       int rescan;
+       
+#ifdef DEBUG
+       if (acdebug)
+               printf("find_busslaves: for %s%d\n",
+                      hc->hp_driver->d_name, hc->hp_unit);
+#endif
+       for (s = 0; s < maxslaves; s++) {
+               rescan = 1;
+               match_s = NULL;
+               for (hd = hp_dinit; hd->hp_driver; hd++) {
+                       /*
+                        * Rule out the easy ones:
+                        * 1. slave already assigned or not a slave
+                        * 2. not of the proper type
+                        * 3. controller specified but not this one
+                        * 4. slave specified but not this one
+                        */
+                       if (hd->hp_alive || hd->hp_cdriver == NULL)
+                               continue;
+                       if (!dr_type(hc->hp_driver, hd->hp_cdriver->d_name))
+                               continue;
+                       if (hd->hp_ctlr >= 0 && hd->hp_ctlr != hc->hp_unit)
+                               continue;
+                       if (hd->hp_slave >= 0 && hd->hp_slave != s)
+                               continue;
+                       /*
+                        * Case 0: first possible match.
+                        * Remember it and keep looking for better.
+                        */
+                       if (match_s == NULL) {
+                               match_s = hd;
+                               new_c = hc->hp_unit;
+                               new_s = s;
+                               continue;
+                       }
+                       /*
+                        * Case 1: exact match.
+                        * All done.  Note that we do not attempt any other
+                        * matches if this one fails.  This allows us to
+                        * "reserve" locations for dynamic addition of
+                        * disk/tape drives by fully qualifing the location.
+                        */
+                       if (hd->hp_slave == s && hd->hp_ctlr == hc->hp_unit) {
+                               match_s = hd;
+                               rescan = 0;
+                               break;
+                       }
+                       /*
+                        * Case 2: right controller, wildcarded slave.
+                        * Remember first and keep looking for an exact match.
+                        */
+                       if (hd->hp_ctlr == hc->hp_unit &&
+                           match_s->hp_ctlr < 0) {
+                               match_s = hd;
+                               new_s = s;
+                               continue;
+                       }
+                       /*
+                        * Case 3: right slave, wildcarded controller.
+                        * Remember and keep looking for a better match.
+                        */
+                       if (hd->hp_slave == s &&
+                           match_s->hp_ctlr < 0 && match_s->hp_slave < 0) {
+                               match_s = hd;
+                               new_c = hc->hp_unit;
+                               continue;
+                       }
+                       /*
+                        * OW: we had a totally wildcarded spec.
+                        * If we got this far, we have found a possible
+                        * match already (match_s != NULL) so there is no
+                        * reason to remember this one.
+                        */
+                       continue;
+               }
+               /*
+                * Found a match.  We need to set hp_ctlr/hp_slave properly
+                * for the init routines but we also need to remember all
+                * the old values in case this doesn't pan out.
+                */
+               if (match_s) {
+                       hd = match_s;
+                       old_c = hd->hp_ctlr;
+                       old_s = hd->hp_slave;
+                       if (hd->hp_ctlr < 0)
+                               hd->hp_ctlr = new_c;
+                       if (hd->hp_slave < 0)
+                               hd->hp_slave = new_s;
+#ifdef DEBUG
+                       if (acdebug)
+                               printf("looking for %s%d at slave %d...",
+                                      hd->hp_driver->d_name,
+                                      hd->hp_unit, hd->hp_slave);
+#endif
+
+                       if ((*hd->hp_driver->d_init)(hd)) {
+#ifdef DEBUG
+                               if (acdebug)
+                                       printf("found\n");
+#endif
+                               printf("%s%d at %s%d, slave %d",
+                                      hd->hp_driver->d_name, hd->hp_unit,
+                                      hc->hp_driver->d_name, hd->hp_ctlr,
+                                      hd->hp_slave);
+                               if (hd->hp_flags)
+                                       printf(" flags 0x%x", hd->hp_flags);
+                               printf("\n");
+                               hd->hp_alive = 1;
+                               if (hd->hp_dk && dkn < DK_NDRIVE)
+                                       hd->hp_dk = dkn++;
+                               else
+                                       hd->hp_dk = -1;
+                               rescan = 1;
+                       } else {
+#ifdef DEBUG
+                               if (acdebug)
+                                       printf("not found\n");
+#endif
+                               hd->hp_ctlr = old_c;
+                               hd->hp_slave = old_s;
+                       }
+                       /*
+                        * XXX: This should be handled better.
+                        * Re-scan a slave.  There are two reasons to do this.
+                        * 1. It is possible to have both a tape and disk
+                        *    (e.g. 7946) or two disks (e.g. 9122) at the
+                        *    same slave address.  Here we need to rescan
+                        *    looking only at entries with a different
+                        *    physical unit number (hp_flags).
+                        * 2. It is possible that an init failed because the
+                        *    slave was there but of the wrong type.  In this
+                        *    case it may still be possible to match the slave
+                        *    to another ioconf entry of a different type.
+                        *    Here we need to rescan looking only at entries
+                        *    of different types.
+                        * In both cases we avoid looking at undesirable
+                        * ioconf entries of the same type by setting their
+                        * alive fields to -1.
+                        */
+                       if (rescan) {
+                               for (hd = hp_dinit; hd->hp_driver; hd++) {
+                                       if (hd->hp_alive)
+                                               continue;
+                                       if (match_s->hp_alive == 1) {   /* 1 */
+                                               if (hd->hp_flags == match_s->hp_flags)
+                                                       hd->hp_alive = -1;
+                                       } else {                        /* 2 */
+                                               if (hd->hp_driver == match_s->hp_driver)
+                                                       hd->hp_alive = -1;
+                                       }
+                               }
+                               s--;
+                               continue;
+                       }
+               }
+               /*
+                * Reset bogon alive fields prior to attempting next slave
+                */
+               for (hd = hp_dinit; hd->hp_driver; hd++)
+                       if (hd->hp_alive == -1)
+                               hd->hp_alive = 0;
+       }
+}
+
+sctoaddr(addr)
+       register int addr;
+{
+       extern int internalhpib;
+
+       if (addr == 7)
+               addr = internalhpib;
+       else if (addr < 32)
+               addr = IOV(EXTIOBASE + (addr * IOCARDSIZE));
+       else
+               addr = IOV(addr);
+       return(addr);
+}
+
+addrtosc(addr)
+       register u_int addr;
+{
+       extern int internalhpib;
+
+#if defined(HP360) || defined(HP370)
+       extern char grfregs[];
+
+       if (addr == (u_int)grfregs)
+               addr = 132;
+       else
+#endif
+       if (addr == internalhpib)
+               addr = 7;
+       else if (addr >= IOV(IOBASE)) {
+               addr = UNIOV(addr);
+               if (addr >= EXTIOBASE)
+                       addr = (addr - EXTIOBASE) / IOCARDSIZE;
+       }
+       return((int)addr);
+}
+
+same_hw_device(hw, hd)
+       struct hp_hw *hw;
+       struct hp_device *hd;
+{
+       int found = 0;
+
+       switch (hw->hw_type) {
+       case HPIB:
+       case RD:
+       case PPI:
+       case CT:
+               found = dr_type(hd->hp_driver, "hpib");
+               break;
+       case BITMAP:
+               found = dr_type(hd->hp_driver, "grf");
+               break;
+       case NET:
+               found = dr_type(hd->hp_driver, "le");
+               break;
+       case COMM:
+               found = dr_type(hd->hp_driver, "dca") ||
+                       dr_type(hd->hp_driver, "dcm");
+               break;
+       case SCSI:
+               found = dr_type(hd->hp_driver, "scsi");
+               break;
+       case FPA:    /* Unsupported so far */
+       case VME:
+       case FLINK:
+       case MISC:
+               break;
+       }
+       return(found);
+}
+
+find_devs()
+{
+       short sc;
+       u_char *id_reg;
+       register int addr;
+       register struct hp_hw *hw;
+
+       hw = sc_table;
+       for (sc = -1; sc < 32; sc++) {
+#if defined(HP360) || defined(HP370)
+               /*
+                * XXX: special check for bit-mapped display
+                * at SC132 in DIO II space on the 340.
+                */
+               if (sc == -1 && machineid == HP_340) {
+                       extern struct pte Grfmap[];
+                       extern char grfregs[];
+
+                       physaccess(Grfmap, (caddr_t)DIOIIBASE,
+                                  DIOIICSIZE, PG_RW|PG_CI);
+                       addr = (int) grfregs;
+                       /*
+                        * Nothing there or not a display,
+                        * try the usual internal display address.
+                        */
+                       if (badaddr((caddr_t)addr) ||
+                           (((u_char *)addr)[1] & 0xff) != 57)
+                               addr = IOV(GRFIADDR);
+               } else
+#endif
+               /*
+                * Probe all select codes + internal display addr
+                */
+               if (sc == -1)
+                       addr = IOV(GRFIADDR);
+               else
+                       addr = sctoaddr(sc);
+               if (badaddr((caddr_t)addr))
+                       continue;
+
+               id_reg = (u_char *) addr;
+               hw->hw_id = id_reg[1] & 0xff;
+               hw->hw_sc = sc;
+               hw->hw_addr = (char *) addr;
+
+               /*
+                * XXX: the following could be in a big static table
+                */
+               switch (hw->hw_id) {
+               /* Null device? */
+               case 0:
+                       break;
+               case 2:
+                       hw->hw_name = "98626A";
+                       hw->hw_type = COMM;
+                       break;
+               case 3:
+                       hw->hw_name = "98622A";
+                       hw->hw_type = MISC;
+                       break;
+               case 4:
+                       hw->hw_name = "98623A";
+                       hw->hw_type = MISC;
+                       break;
+               case 5:
+                       hw->hw_name = "98642A";
+                       hw->hw_type = COMM;
+                       break;
+               case 7:
+               case 39:
+               case 71:
+               case 103:
+                       hw->hw_name = "98265A";
+                       hw->hw_type = SCSI;
+                       break;
+               case 8:
+                       hw->hw_name = "98625B";
+                       hw->hw_type = HPIB;
+                       break;
+               case 9:
+                       hw->hw_name = "98287A";
+                       hw->hw_type = KEYBOARD;
+                       break;
+               case 10:
+                       hw->hw_name = "98635A";
+                       hw->hw_type = FPA;
+                       break;
+               case 11:
+                       hw->hw_name = "Timer";
+                       hw->hw_type = MISC;
+                       break;
+               case 18:
+                       hw->hw_name = "98640A";
+                       hw->hw_type = MISC;
+                       break;
+               case 20:
+                       hw->hw_name = "98628A";
+                       hw->hw_type = COMM;
+                       break;
+               case 21:
+                       hw->hw_name = "98643A";
+                       hw->hw_type = NET;
+                       break;
+               case 22:
+                       hw->hw_name = "98659A";
+                       hw->hw_type = COMM;
+                       break;
+               case 25:
+                       hw->hw_name = "237";
+                       hw->hw_type = BITMAP;
+                       break;
+               case 26:
+                       hw->hw_name = "Quad";
+                       hw->hw_type = MISC;
+                       break;
+               case 27:
+                       hw->hw_name = "98253A";
+                       hw->hw_type = MISC;
+                       break;
+               case 28:
+                       hw->hw_name = "98627A";
+                       hw->hw_type = BITMAP;
+                       break;
+               case 29:
+                       hw->hw_name = "98633A";
+                       hw->hw_type = BITMAP;
+                       break;
+               case 30:
+                       hw->hw_name = "98259A";
+                       hw->hw_type = MISC;
+                       break;
+               case 31:
+                       hw->hw_name = "8741";
+                       hw->hw_type = MISC;
+                       break;
+               case 49:
+                       hw->hw_name = "98577A";
+                       hw->hw_type = VME;
+                       sc++;
+                       break;
+               case 57:
+                       hw->hw_type = BITMAP;
+                       hw->hw_id2 = id_reg[0x15];
+                       switch (hw->hw_id2) {
+                       case 1:
+                               hw->hw_name = "98700 ";
+                               break;
+                       case 2:
+                               hw->hw_name = "TOPCAT";
+                               break;
+                       case 4:
+                               hw->hw_name = "98720 ";
+                               sc++;
+                               break;
+                       case 5:
+                       case 6:
+                       case 7:
+                       case 9:
+                               hw->hw_name = "CATSEYE";
+                               break;
+                       case 8:
+                               hw->hw_name = "98730 ";
+                               sc++;
+                               break;
+                       default:
+                               hw->hw_name = "987xx ";
+                               break;
+                       }
+                       break;
+               case 66:
+                       hw->hw_name = "98644A";
+                       hw->hw_type = COMM;
+                       break;
+               case 128:
+                       hw->hw_name = "98624A";
+                       hw->hw_type = HPIB;
+                       break;
+               default:
+                       hw->hw_name = "DEFAULT";
+                       hw->hw_type = MISC;
+                       break;
+               }
+               hw++;
+       }
+}
+
+#if NCD > 0
+#include "../hpdev/cdvar.h"
+
+find_cdevices()
+{
+       register struct cddevice *cd;
+
+       for (cd = cddevice; cd->cd_unit >= 0; cd++) {
+               /*
+                * XXX
+                * Assign disk index first so that init routine
+                * can use it (saves having the driver drag around
+                * the cddevice pointer just to set up the dk_*
+                * info in the open routine).
+                */
+               if (dkn < DK_NDRIVE)
+                       cd->cd_dk = dkn++;
+               else
+                       cd->cd_dk = -1;
+               if (cdinit(cd))
+                       printf("cd%d configured\n", cd->cd_unit);
+               else if (cd->cd_dk >= 0) {
+                       cd->cd_dk = -1;
+                       dkn--;
+               }
+       }
+}
+#endif
+
+isrinit()
+{
+       register int i;
+
+       for (i = 0; i < NISR; i++)
+               isrqueue[i].isr_forw = isrqueue[i].isr_back = &isrqueue[i];
+}
+
+void
+isrlink(isr)
+       register struct isr *isr;
+{
+       int i = ISRIPL(isr->isr_ipl);
+
+       if (i < 0 || i >= NISR) {
+               printf("bad IPL %d\n", i);
+               panic("configure");
+       }
+       insque(isr, isrqueue[i].isr_back);
+}
+
+/*
+ * Configure swap space and related parameters.
+ */
+swapconf()
+{
+       register struct swdevt *swp;
+       register int nblks;
+
+       for (swp = swdevt; swp->sw_dev; 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;
+               }
+       dumpconf();
+}
+
+#define        DOSWAP                  /* Change swdevt, argdev, and dumpdev too */
+u_long bootdev;                /* should be dev_t, but not until 32 bits */
+
+static char devname[][2] = {
+       0,0,            /* 0 = ct */
+       0,0,            /* 1 = xx */
+       'r','d',        /* 2 = rd */
+       0,0,            /* 3 = sw */
+       's','d',        /* 4 = rd */
+};
+
+#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()
+{
+       register struct hp_ctlr *hc;
+       register struct hp_device *hd;
+       int  majdev, mindev, unit, part, adaptor;
+       dev_t temp, orootdev;
+       struct swdevt *swp;
+
+       if (boothowto & RB_DFLTROOT ||
+           (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
+               return;
+       majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
+       if (majdev > sizeof(devname) / sizeof(devname[0]))
+               return;
+       adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
+       part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
+       unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
+       /*
+        * First, find the controller type which support this device.
+        */
+       for (hd = hp_dinit; hd->hp_driver; hd++)
+               if (hd->hp_driver->d_name[0] == devname[majdev][0] &&
+                   hd->hp_driver->d_name[1] == devname[majdev][1])
+                       break;
+       if (hd->hp_driver == 0)
+               return;
+       /*
+        * Next, find the controller of that type corresponding to
+        * the adaptor number.
+        */
+       for (hc = hp_cinit; hc->hp_driver; hc++)
+               if (hc->hp_alive && hc->hp_unit == adaptor &&
+                   hc->hp_driver == hd->hp_cdriver)
+                       break;
+       if (hc->hp_driver == 0)
+               return;
+       /*
+        * Finally, find the device in question attached to that controller.
+        */
+       for (hd = hp_dinit; hd->hp_driver; hd++)
+               if (hd->hp_alive && hd->hp_slave == unit &&
+                   hd->hp_cdriver == hc->hp_driver &&
+                   hd->hp_ctlr == hc->hp_unit)
+                       break;
+       if (hd->hp_driver == 0)
+               return;
+       mindev = hd->hp_unit;
+       /*
+        * Form a new rootdev
+        */
+       mindev = (mindev << 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],
+               mindev >> PARTITIONSHIFT, part + 'a');
+
+#ifdef DOSWAP
+       mindev &= ~PARTITIONMASK;
+       for (swp = swdevt; swp->sw_dev; swp++) {
+               if (majdev == major(swp->sw_dev) &&
+                   mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
+                       temp = swdevt[0].sw_dev;
+                       swdevt[0].sw_dev = swp->sw_dev;
+                       swp->sw_dev = temp;
+                       break;
+               }
+       }
+       if (swp->sw_dev == 0)
+               return;
+
+       /*
+        * If argdev and dumpdev were the same as the old primary swap
+        * device, move them to the new primary swap device.
+        */
+       if (temp == dumpdev)
+               dumpdev = swdevt[0].sw_dev;
+       if (temp == argdev)
+               argdev = swdevt[0].sw_dev;
+#endif
+}
diff --git a/usr/src/sys/hp300/hp300/clock.c b/usr/src/sys/hp300/hp300/clock.c
new file mode 100644 (file)
index 0000000..dc0f0af
--- /dev/null
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: clock.c 1.17 89/11/30$
+ *
+ *     @(#)clock.c     7.1 (Berkeley) %G%
+ */
+
+#include "param.h"
+#include "user.h"
+#include "kernel.h"
+#include "../hpdev/hilreg.h"
+#include "clockreg.h"
+
+#include "machine/psl.h"
+#include "machine/cpu.h"
+
+#if defined(GPROF) && defined(PROFTIMER)
+#include "gprof.h"
+#endif
+
+int    clkstd[] = { IOV(0x5F8000) };
+
+static int month_days[12] = {
+       31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+struct bbc_tm *gmt_to_bbc();
+u_char bbc_registers[13];
+u_char write_bbc_reg(), read_bbc_reg();
+struct hil_dev *bbcaddr = NULL;
+
+/*
+ * 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.
+ *
+ * Resettodr restores the time of day hardware after a time change.
+ *
+ * A note on the real-time clock:
+ * We actually load the clock with CLK_INTERVAL-1 instead of CLK_INTERVAL.
+ * This is because the counter decrements to zero after N+1 enabled clock
+ * periods where N is the value loaded into the counter.
+ */
+
+/*
+ * Start the real-time clock.
+ */
+startrtclock()
+{
+       register struct clkreg *clk = (struct clkreg *)clkstd[0];
+
+       clk->clk_cr2 = CLK_CR1;
+       clk->clk_cr1 = CLK_RESET;
+       clk->clk_cr2 = CLK_CR3;
+       clk->clk_cr3 = 0;
+       clk->clk_msb1 = (CLK_INTERVAL-1) >> 8 & 0xFF;
+       clk->clk_lsb1 = (CLK_INTERVAL-1) & 0xFF;
+       clk->clk_msb2 = 0;
+       clk->clk_lsb2 = 0;
+       clk->clk_msb3 = 0;
+       clk->clk_lsb3 = 0;
+       clk->clk_cr2 = CLK_CR1;
+       clk->clk_cr1 = CLK_IENAB;
+}
+
+/*
+ * Returns number of usec since last recorded clock "tick"
+ * (i.e. clock interrupt).
+ */
+clkread()
+{
+       register struct clkreg *clk = (struct clkreg *) clkstd[0];
+       register int high, low;
+
+       high = clk->clk_msb1;
+       low = clk->clk_lsb1;
+       if (high != clk->clk_msb1)
+               high = clk->clk_msb1;
+
+       high = (CLK_INTERVAL-1) - ((high << 8) | low);
+       /*
+        * Pending interrupt indicates that the counter has wrapped
+        * since we went to splhigh().  Need to compensate.
+        */
+       if (clk->clk_sr & CLK_INT1)
+               high += CLK_INTERVAL;
+       return((high * tick) / CLK_INTERVAL);
+}
+
+#include "clock.h"
+#if NCLOCK > 0
+/*
+ * /dev/clock: mappable high resolution timer.
+ *
+ * This code implements a 32-bit recycling counter (with a 4 usec period)
+ * using timers 2 & 3 on the 6840 clock chip.  The counter can be mapped
+ * RO into a user's address space to achieve low overhead (no system calls),
+ * high-precision timing.
+ *
+ * Note that timer 3 is also used for the high precision profiling timer
+ * (PROFTIMER code above).  Care should be taken when both uses are
+ * configured as only a token effort is made to avoid conflicting use.
+ */
+#include "proc.h"
+#include "ioctl.h"
+#include "mapmem.h"
+#include "malloc.h"
+#include "clockioctl.h"
+
+int clockon = 0;               /* non-zero if high-res timer enabled */
+#ifdef PROFTIMER
+int  profprocs = 0;            /* # of procs using profiling timer */
+#endif
+#ifdef DEBUG
+int clockdebug = 0;
+#endif
+
+/*ARGSUSED*/
+clockopen(dev, flags)
+       dev_t dev;
+{
+#ifdef PROFTIMER
+#ifdef GPROF
+       /*
+        * Kernel profiling enabled, give up.
+        */
+       if (profiling)
+               return(EBUSY);
+#endif
+       /*
+        * If any user processes are profiling, give up.
+        */
+       if (profprocs)
+               return(EBUSY);
+#endif
+       if (!clockon) {
+               startclock();
+               clockon++;
+       }
+       return(0);
+}
+
+/*ARGSUSED*/
+clockclose(dev, flags)
+       dev_t dev;
+{
+#ifdef MAPMEM
+       (void) clockunmmap(dev, (caddr_t)0);
+#endif
+       stopclock();
+       clockon = 0;
+       return(0);
+}
+
+/*ARGSUSED*/
+clockioctl(dev, cmd, data, flag)
+       dev_t dev;
+       caddr_t data;
+{
+       int error = 0;
+       
+       switch (cmd) {
+
+#ifdef MAPMEM
+       case CLOCKMAP:
+               error = clockmmap(dev, (caddr_t *)data);
+               break;
+
+       case CLOCKUNMAP:
+               error = clockunmmap(dev, *(caddr_t *)data);
+               break;
+
+       case CLOCKGETRES:
+               *(int *)data = CLK_RESOLUTION;
+               break;
+#endif
+
+       default:
+               error = EINVAL;
+               break;
+       }
+       return(error);
+}
+
+/*ARGSUSED*/
+clockmap(dev, off, prot)
+       dev_t dev;
+{
+#ifdef MMAP
+       return((off + (IOBASE+CLKSR-1)) >> PGSHIFT);
+#endif
+}
+
+#ifdef MAPMEM
+
+struct mapmemops clockops = {
+       (int (*)())0, (int (*)())0, (int (*)())0, (int (*)())0
+};
+
+clockmmap(dev, addrp)
+       dev_t dev;
+       caddr_t *addrp;
+{
+       register struct mapmem *mp;
+       int id, clockmapin();
+
+       id = minor(dev);        /* XXX */
+       mp = mmalloc(id, addrp, NBPG, MM_RO|MM_CI|MM_NOCORE, &clockops);
+#ifdef DEBUG
+       if (clockdebug)
+               printf("clockmmap(%d): addr %x\n", u.u_procp->p_pid, *addrp);
+#endif
+       if (mp == MMNIL)
+               return(u.u_error);
+       if (!mmmapin(mp, clockmapin)) {
+               mmfree(mp);
+               return(u.u_error);
+       }
+       return(0);
+}
+
+clockunmmap(dev, addr)
+       dev_t dev;
+       caddr_t addr;
+{
+       register struct mapmem *mp, **mpp;
+       int found, id;
+
+#ifdef DEBUG
+       if (clockdebug)
+               printf("clockunmmap(%d): addr %x\n", u.u_procp->p_pid, addr);
+#endif
+       id = minor(dev);        /* XXX */
+       found = 0;
+       mpp = &u.u_mmap;
+       for (mp = *mpp; mp; mp = *mpp) {
+               if (mp->mm_id != id || mp->mm_ops != &clockops) {
+                       mpp = &mp->mm_next;
+                       continue;
+               }
+               if (addr &&
+                   (addr < mp->mm_uva || addr >= mp->mm_uva+mp->mm_size)) {
+                       mpp = &mp->mm_next;
+                       continue;
+               }
+               mmmapout(mp);
+               mmfree(mp);
+               found++;
+       }
+       return(found ? 0 : EINVAL);
+}
+
+/*ARGSUSED*/
+clockmapin(mp, off)
+       struct mapmem *mp;
+{
+       return((off + (IOBASE+CLKSR-1)) >> PGSHIFT);
+}
+#endif
+
+startclock()
+{
+       register struct clkreg *clk = (struct clkreg *)clkstd[0];
+
+       clk->clk_msb2 = -1; clk->clk_lsb2 = -1;
+       clk->clk_msb3 = -1; clk->clk_lsb3 = -1;
+
+       clk->clk_cr2 = CLK_CR3;
+       clk->clk_cr3 = CLK_OENAB|CLK_8BIT;
+       clk->clk_cr2 = CLK_CR1;
+       clk->clk_cr1 = CLK_IENAB;
+}
+
+stopclock()
+{
+       register struct clkreg *clk = (struct clkreg *)clkstd[0];
+
+       clk->clk_cr2 = CLK_CR3;
+       clk->clk_cr3 = 0;
+       clk->clk_cr2 = CLK_CR1;
+       clk->clk_cr1 = CLK_IENAB;
+}
+#endif
+
+#ifdef PROFTIMER
+/*
+ * This code allows the hp300 kernel to use one of the extra timers on
+ * the clock chip for profiling, instead of the regular system timer.
+ * The advantage of this is that the profiling timer can be turned up to
+ * a higher interrupt rate, giving finer resolution timing. The profclock
+ * routine is called from the lev6intr in locore, and is a specialized
+ * routine that calls addupc. The overhead then is far less than if
+ * hardclock/softclock was called. Further, the context switch code in
+ * locore has been changed to turn the profile clock on/off when switching
+ * into/out of a process that is profiling (startprofclock/stopprofclock).
+ * This reduces the impact of the profiling clock on other users, and might
+ * possibly increase the accuracy of the profiling. 
+ */
+int  profint   = PRF_INTERVAL; /* Clock ticks between interrupts */
+int  profscale = 0;            /* Scale factor from sys clock to prof clock */
+char profon    = 0;            /* Is profiling clock on? */
+
+/* profon values - do not change, locore.s assumes these values */
+#define PRF_NONE       0x00
+#define        PRF_USER        0x01
+#define        PRF_KERNEL      0x80
+
+initprofclock()
+{
+#if NCLOCK > 0
+       /*
+        * If the high-res timer is running, force profiling off.
+        * Unfortunately, this gets reflected back to the user not as
+        * an error but as a lack of results.
+        */
+       if (clockon) {
+               u.u_prof.pr_scale = 0;
+               return;
+       }
+       /*
+        * Keep track of the number of user processes that are profiling
+        * by checking the scale value.
+        *
+        * XXX: this all assumes that the profiling code is well behaved;
+        * i.e. profil() is called once per process with pcscale non-zero
+        * to turn it on, and once with pcscale zero to turn it off.
+        * Also assumes you don't do any forks or execs.  Oh well, there
+        * is always adb...
+        */
+       if (u.u_prof.pr_scale)
+               profprocs++;
+       else
+               profprocs--;
+#endif
+       /*
+        * The profile interrupt interval must be an even divisor
+        * of the CLK_INTERVAL so that scaling from a system clock
+        * tick to a profile clock tick is possible using integer math.
+        */
+       if (profint > CLK_INTERVAL || (CLK_INTERVAL % profint) != 0)
+               profint = CLK_INTERVAL;
+       profscale = CLK_INTERVAL / profint;
+}
+
+startprofclock()
+{
+       register struct clkreg *clk = (struct clkreg *)clkstd[0];
+
+       clk->clk_msb3 = (profint-1) >> 8 & 0xFF;
+       clk->clk_lsb3 = (profint-1) & 0xFF;
+
+       clk->clk_cr2 = CLK_CR3;
+       clk->clk_cr3 = CLK_IENAB;
+}
+
+stopprofclock()
+{
+       register struct clkreg *clk = (struct clkreg *)clkstd[0];
+
+       clk->clk_cr2 = CLK_CR3;
+       clk->clk_cr3 = 0;
+}
+
+#ifdef GPROF
+/*
+ * profclock() is expanded in line in lev6intr() unless profiling kernel.
+ * Assumes it is called with clock interrupts blocked.
+ */
+profclock(pc, ps)
+       caddr_t pc;
+       int ps;
+{
+       /*
+        * Came from user mode.
+        * If this process is being profiled record the tick.
+        */
+       if (USERMODE(ps)) {
+               if (u.u_prof.pr_scale)
+                       addupc(pc, &u.u_prof, 1);
+       }
+       /*
+        * Came from kernel (supervisor) mode.
+        * If we are profiling the kernel, record the tick.
+        */
+       else if (profiling < 2) {
+               register int s = pc - s_lowpc;
+
+               if (s < s_textsize)
+                       kcount[s / (HISTFRACTION * sizeof (*kcount))]++;
+       }
+       /*
+        * Kernel profiling was on but has been disabled.
+        * Mark as no longer profiling kernel and if all profiling done,
+        * disable the clock.
+        */
+       if (profiling && (profon & PRF_KERNEL)) {
+               profon &= ~PRF_KERNEL;
+               if (profon == PRF_NONE)
+                       stopprofclock();
+       }
+}
+#endif
+#endif
+
+/*
+ * Initialize the time of day register, based on the time base which is, e.g.
+ * from a filesystem.
+ */
+inittodr(base)
+       time_t base;
+{
+       u_long timbuf = base;   /* assume no battery clock exists */
+       static int bbcinited = 0;
+
+       /* XXX */
+       if (!bbcinited) {
+               if (badbaddr(&BBCADDR->hil_stat))
+                       printf("WARNING: no battery clock\n");
+               else
+                       bbcaddr = BBCADDR;
+               bbcinited = 1;
+       }
+
+       /*
+        * bbc_to_gmt converts and stores the gmt in timbuf.
+        * If an error is detected in bbc_to_gmt, or if the filesystem
+        * time is more recent than the gmt time in the clock,
+        * then use the filesystem time and warn the user.
+        */
+       if (!bbc_to_gmt(&timbuf) || timbuf < base) {
+               printf("WARNING: bad date in battery clock\n");
+               timbuf = base;
+       }
+       if (base < 5*SECYR) {
+               printf("WARNING: preposterous time in file system");
+               timbuf = 6*SECYR + 186*SECDAY + SECDAY/2;
+               printf(" -- CHECK AND RESET THE DATE!\n");
+       }
+       
+       /* Battery clock does not store usec's, so forget about it. */
+       time.tv_sec = timbuf;
+}
+
+resettodr()
+{
+       register int i;
+       register struct bbc_tm *tmptr;
+
+       tmptr = gmt_to_bbc(time.tv_sec);
+
+       decimal_to_bbc(0, 1,  tmptr->tm_sec);
+       decimal_to_bbc(2, 3,  tmptr->tm_min);
+       decimal_to_bbc(4, 5,  tmptr->tm_hour);
+       decimal_to_bbc(7, 8,  tmptr->tm_mday);
+       decimal_to_bbc(9, 10, tmptr->tm_mon);
+       decimal_to_bbc(11, 12, tmptr->tm_year);
+
+       /* Some bogusness to deal with seemingly broken hardware. Nonsense */
+       bbc_registers[5] = ((tmptr->tm_hour / 10) & 0x03) + 8;
+
+       write_bbc_reg(15, 13);  /* reset prescalar */
+
+       for (i = 0; i <= NUM_BBC_REGS; i++)
+               if (bbc_registers[i] != write_bbc_reg(i, bbc_registers[i])) {
+                       printf("Cannot set battery backed clock\n");
+                       break;
+               }
+}
+
+struct bbc_tm *
+gmt_to_bbc(tim)
+       long tim;
+{
+       register int i;
+       register long hms, day;
+       static struct bbc_tm rt;
+
+       day = tim / SECDAY;
+       hms = tim % SECDAY;
+
+       /* Hours, minutes, seconds are easy */
+       rt.tm_hour = hms / 3600;
+       rt.tm_min  = (hms % 3600) / 60;
+       rt.tm_sec  = (hms % 3600) % 60;
+
+       /* Number of years in days */
+       for (i = STARTOFTIME - 1900; day >= days_in_year(i); i++)
+               day -= days_in_year(i);
+       rt.tm_year = i;
+       
+       /* Number of months in days left */
+       if (leapyear(rt.tm_year))
+               days_in_month(FEBRUARY) = 29;
+       for (i = 1; day >= days_in_month(i); i++)
+               day -= days_in_month(i);
+       days_in_month(FEBRUARY) = 28;
+       rt.tm_mon = i;
+
+       /* Days are what is left over (+1) from all that. */
+       rt.tm_mday = day + 1;  
+       
+       return(&rt);
+}
+
+bbc_to_gmt(timbuf)
+       u_long *timbuf;
+{
+       register int i;
+       register u_long tmp;
+       int year, month, day, hour, min, sec;
+
+       read_bbc();
+
+       sec = bbc_to_decimal(1, 0);
+       min = bbc_to_decimal(3, 2);
+
+       /*
+        * Hours are different for some reason. Makes no sense really.
+        */
+       hour  = ((bbc_registers[5] & 0x03) * 10) + bbc_registers[4];
+       day   = bbc_to_decimal(8, 7);
+       month = bbc_to_decimal(10, 9);
+       year  = bbc_to_decimal(12, 11) + 1900;
+
+       range_test(hour, 0, 23);
+       range_test(day, 1, 31);
+       range_test(month, 1, 12);
+       range_test(year, STARTOFTIME, 2000);
+
+       tmp = 0;
+
+       for (i = STARTOFTIME; i < year; i++)
+               tmp += days_in_year(i);
+       if (leapyear(year) && month > FEBRUARY)
+               tmp++;
+
+       for (i = 1; i < month; i++)
+               tmp += days_in_month(i);
+       
+       tmp += (day - 1);
+       tmp = ((tmp * 24 + hour) * 60 + min) * 60 + sec;
+
+       *timbuf = tmp;
+       return(1);
+}
+
+read_bbc()
+{
+       register int i, read_okay;
+
+       read_okay = 0;
+       while (!read_okay) {
+               read_okay = 1;
+               for (i = 0; i <= NUM_BBC_REGS; i++)
+                       bbc_registers[i] = read_bbc_reg(i);
+               for (i = 0; i <= NUM_BBC_REGS; i++)
+                       if (bbc_registers[i] != read_bbc_reg(i))
+                               read_okay = 0;
+       }
+}
+
+u_char
+read_bbc_reg(reg)
+       int reg;
+{
+       u_char data = reg;
+
+       if (bbcaddr) {
+               send_hil_cmd(bbcaddr, BBC_SET_REG, &data, 1, NULL);
+               send_hil_cmd(bbcaddr, BBC_READ_REG, NULL, 0, &data);
+       }
+       return(data);
+}
+
+u_char
+write_bbc_reg(reg, data)
+       u_int data;
+{
+       u_char tmp;
+
+       tmp = (u_char) ((data << HIL_SSHIFT) | reg);
+
+       if (bbcaddr) {
+               send_hil_cmd(bbcaddr, BBC_SET_REG, &tmp, 1, NULL);
+               send_hil_cmd(bbcaddr, BBC_WRITE_REG, NULL, 0, NULL);
+               send_hil_cmd(bbcaddr, BBC_READ_REG, NULL, 0, &tmp);
+       }
+       return(tmp);
+}      
diff --git a/usr/src/sys/hp300/hp300/clockioctl.h b/usr/src/sys/hp300/hp300/clockioctl.h
new file mode 100644 (file)
index 0000000..82c1135
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 1989 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: clockioctl.h 1.0 89/11/05$
+ *
+ *     @(#)clockioctl.h        7.1 (Berkeley) %G%
+ */
+
+#define        CLOCKMAP        _IOWR('C', 1, int)
+#define        CLOCKUNMAP      _IOW('C', 2, int)
+#define        CLOCKGETRES     _IOR('C', 3, int)
diff --git a/usr/src/sys/hp300/hp300/clockreg.h b/usr/src/sys/hp300/hp300/clockreg.h
new file mode 100644 (file)
index 0000000..4f73db6
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: clockreg.h 1.13 89/11/30$
+ *
+ *     @(#)clockreg.h  7.1 (Berkeley) %G%
+ */
+
+/*
+ * HP300 "real time clock" (MC6840) registers
+ */
+
+struct clkreg {
+       u_char  clk_dummy1;
+       u_char  clk_cr3;
+#define        clk_cr1 clk_cr3
+       u_char  clk_dummy2;
+       u_char  clk_cr2;
+#define        clk_sr  clk_cr2
+       u_char  clk_dummy3;
+       u_char  clk_msb1;
+       u_char  clk_dummy4;
+       u_char  clk_lsb1;
+       u_char  clk_dummy5;
+       u_char  clk_msb2;
+       u_char  clk_dummy6;
+       u_char  clk_lsb2;
+       u_char  clk_dummy7;
+       u_char  clk_msb3;
+       u_char  clk_dummy8;
+       u_char  clk_lsb3;
+};
+
+#define CLKCR1         IOP(0x5F8001)
+#define CLKCR2         IOP(0x5F8003)
+#define CLKCR3         CLKCR1
+#define        CLKSR           CLKCR2
+#define        CLKMSB1         IOP(0x5F8005)
+#define        CLKMSB2         IOP(0x5F8009)
+#define        CLKMSB3         IOP(0x5F800D)
+
+/* output of counter 3 clocks counter 2 */
+
+#define        CLK_OENAB       0x80    /* output enable */
+#define        CLK_IENAB       0x40    /* interrupt enable */
+#define        CLK_8BIT        0x04    /* 8 bit mode */
+#define        CLK_RESET       0x01    /* chip reset (CR1 only) */
+#define        CLK_CR1         0x01    /* select CR1 (CR2 only) */
+#define        CLK_CR3         0x00    /* select CR3 (CR2 only) */
+#define CLK_INT1       0x01    /* interrupt flag for timer 1 (SR only) */
+#define CLK_INT2       0x02    /* interrupt flag for timer 2 (SR only) */
+#define CLK_INT3       0x04    /* interrupt flag for timer 3 (SR only) */
+#define        CLK_INTR        0x80    /* composite interrupt flag (SR only) */
+
+#define CLK_RESOLUTION 4       /* 4 usec resolution (250Khz) */
+#define        CLK_INTERVAL    2500    /* 10msec interval at 250KHz */
+/* #define CLK_INTERVAL        5000    /* 20msec interval at 250Khz */
+
+#ifndef PRF_INTERVAL
+#define PRF_INTERVAL    CLK_INTERVAL
+#endif
+
+/*
+ * HP300 battery-backed clock
+ */
+
+struct bbc_tm {
+       int     tm_sec;
+       int     tm_min;
+       int     tm_hour;
+       int     tm_mday;
+       int     tm_mon;
+       int     tm_year;
+};
+
+#define FEBRUARY       2
+#define        STARTOFTIME     1970
+#define SECDAY         86400L
+#define SECYR          (SECDAY * 365)
+
+#define BBC_SET_REG    0xe0
+#define BBC_WRITE_REG  0xc2
+#define BBC_READ_REG   0xc3
+#define NUM_BBC_REGS   12
+
+#define        leapyear(year)          ((year) % 4 == 0)
+#define        range_test(n, l, h)     if ((n) < (l) || (n) > (h)) return(0)
+#define        days_in_year(a)         (leapyear(a) ? 366 : 365)
+#define        days_in_month(a)        (month_days[(a) - 1])
+#define        bbc_to_decimal(a,b)     (bbc_registers[a] * 10 + bbc_registers[b])
+#define        decimal_to_bbc(a,b,n)   { \
+       bbc_registers[a] = (n) % 10; \
+       bbc_registers[b] = (n) / 10; \
+}
diff --git a/usr/src/sys/hp300/hp300/conf.c b/usr/src/sys/hp300/hp300/conf.c
new file mode 100644 (file)
index 0000000..7427005
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 1982, 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)conf.c      7.1 (Berkeley) %G%
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "buf.h"
+#include "ioctl.h"
+#include "tty.h"
+#include "conf.h"
+
+int    nulldev(), nodev(), rawread(), rawwrite(), swstrategy();
+
+#include "ct.h"
+#if NCT > 0
+int    ctopen(),ctclose(),ctstrategy(),ctread(),ctwrite(),ctdump(),ctioctl();
+#else
+#define        ctopen          nodev
+#define        ctclose         nodev
+#define        ctstrategy      nodev
+#define        ctread          nodev
+#define        ctwrite         nodev
+#define        ctdump          nodev
+#define        ctioctl         nodev
+#endif
+#include "rd.h"
+#if NRD > 0
+int    rdopen(),rdstrategy(),rdread(),rdwrite(),rddump(),rdioctl(),rdsize();
+#else
+#define        rdopen          nodev
+#define        rdstrategy      nodev
+#define        rdread          nodev
+#define        rdwrite         nodev
+#define        rddump          nodev
+#define        rdioctl         nodev
+#define        rdsize          0
+#endif
+#include "sd.h"
+#if NSD > 0
+int    sdopen(),sdstrategy(),sdread(),sdwrite(),sddump(),sdioctl(),sdsize();
+#else
+#define        sdopen          nodev
+#define        sdstrategy      nodev
+#define        sdread          nodev
+#define        sdwrite         nodev
+#define        sddump          nodev
+#define        sdioctl         nodev
+#define        sdsize          0
+#endif
+#include "cd.h"
+#if NCD > 0
+int    cdopen(),cdstrategy(),cdread(),cdwrite(),cddump(),cdioctl(),cdsize();
+#else
+#define        cdopen          nodev
+#define        cdstrategy      nodev
+#define        cdread          nodev
+#define        cdwrite         nodev
+#define        cddump          nodev
+#define        cdioctl         nodev
+#define        cdsize          0
+#endif
+#include "fd.h"
+#if NFD > 0
+int    fdopen(),fdstrategy(),fdread(),fdwrite(),fddump(),fdioctl(),fdsize();
+#else
+#define        fdopen          nodev
+#define        fdstrategy      nodev
+#define        fdread          nodev
+#define        fdwrite         nodev
+#define        fddump          nodev
+#define        fdioctl         nodev
+#define        fdsize          0
+#endif
+
+struct bdevsw  bdevsw[] =
+{
+       { ctopen,       ctclose,        ctstrategy,     ctioctl,        /*0*/
+         ctdump,       0,              B_TAPE },
+       { nodev,        nodev,          nodev,          nodev,          /*1*/
+         nodev,        0,              0 },
+       { rdopen,       nulldev,        rdstrategy,     rdioctl,        /*2*/
+         rddump,       rdsize,         0 },
+       { nodev,        nodev,          swstrategy,     nodev,          /*3*/
+         nodev,        0,              0 },
+       { sdopen,       nulldev,        sdstrategy,     sdioctl,        /*4*/
+         sddump,       sdsize,         0 },
+       { cdopen,       nulldev,        cdstrategy,     cdioctl,        /*5*/
+         cddump,       cdsize,         0 },
+       { fdopen,       nulldev,        fdstrategy,     fdioctl,        /*6*/
+         fddump,       fdsize,         0 },
+};
+int    nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
+
+int    cnopen(),cnclose(),cnread(),cnwrite(),cnioctl(),cnselect();
+
+int    syopen(),syread(),sywrite(),syioctl(),syselect();
+
+int    mmrw();
+#define        mmselect        seltrue
+
+#include "pty.h"
+#if NPTY > 0
+int    ptsopen(),ptsclose(),ptsread(),ptswrite(),ptsstop();
+int    ptcopen(),ptcclose(),ptcread(),ptcwrite(),ptcselect();
+int    ptyioctl();
+struct tty pt_tty[];
+#else
+#define ptsopen                nodev
+#define ptsclose       nodev
+#define ptsread                nodev
+#define ptswrite       nodev
+#define ptcopen                nodev
+#define ptcclose       nodev
+#define ptcread                nodev
+#define ptcwrite       nodev
+#define ptyioctl       nodev
+#define        pt_tty          0
+#define        ptcselect       nodev
+#define        ptsstop         nulldev
+#endif
+
+#include "ppi.h"
+#if NPPI > 0
+int    ppiopen(),ppiclose(),ppiread(),ppiwrite();
+#else
+#define ppiopen                nodev
+#define ppiclose       nodev
+#define ppiread                nodev
+#define ppiwrite       nodev
+#endif
+
+#include "ite.h"
+#if NITE > 0
+int    iteopen(),iteclose(),iteread(),itewrite(),iteioctl();
+struct tty ite_tty[];
+#else
+#define iteopen                nodev
+#define iteclose       nodev
+#define iteread                nodev
+#define itewrite       nodev
+#define itestop                nulldev
+#define iteioctl       nodev
+#define ite_tty                0
+#endif
+
+#include "dca.h"
+#if NDCA > 0
+int    dcaopen(),dcaclose(),dcaread(),dcawrite(),dcastop(),dcaioctl();
+struct tty dca_tty[];
+#else
+#define dcaopen                nodev
+#define dcaclose       nodev
+#define dcaread                nodev
+#define dcawrite       nodev
+#define dcastop                nulldev
+#define dcaioctl       nodev
+#define dca_tty                0
+#endif
+
+#include "dcm.h"
+#if NDCM > 0
+int    dcmopen(),dcmclose(),dcmread(),dcmwrite(),dcmstop(),dcmioctl();
+struct tty dcm_tty[];
+#else
+#define dcmopen                nodev
+#define dcmclose       nodev
+#define dcmread                nodev
+#define dcmwrite       nodev
+#define dcmstop                nulldev
+#define dcmioctl       nodev
+#define dcm_tty                0
+#endif
+
+#include "clock.h"
+#if NCLOCK > 0
+int    clockopen(),clockclose(),clockioctl(),clockmap();
+#else
+#define clockopen      nodev
+#define clockclose     nodev
+#define clockioctl     nodev
+#define clockmap       nodev
+#endif
+
+int    logopen(),logclose(),logread(),logioctl(),logselect();
+
+int    ttselect(), seltrue();
+
+int    grfopen(),grfclose(),grfioctl(),grfselect(),grfmap();
+
+int    hilopen(),hilclose(),hilioctl(),hilmap(),hilselect(),hilread();
+
+struct cdevsw  cdevsw[] =
+{
+       cnopen,         cnclose,        cnread,         cnwrite,        /*0*/
+       cnioctl,        nulldev,        nulldev,        NULL,
+       cnselect,       nodev,          NULL,
+       syopen,         nulldev,        syread,         sywrite,        /*1*/
+       syioctl,        nulldev,        nulldev,        NULL,
+       syselect,       nodev,          NULL,
+       nulldev,        nulldev,        mmrw,           mmrw,           /*2*/
+       nodev,          nulldev,        nulldev,        NULL,
+       mmselect,       nodev,          NULL,
+       nulldev,        nulldev,        rawread,        rawwrite,       /*3*/
+       nodev,          nodev,          nulldev,        NULL,
+       nodev,          nodev,          swstrategy,
+       ptsopen,        ptsclose,       ptsread,        ptswrite,       /*4*/
+       ptyioctl,       ptsstop,        nulldev,        pt_tty,
+       ttselect,       nodev,          NULL,
+       ptcopen,        ptcclose,       ptcread,        ptcwrite,       /*5*/
+       ptyioctl,       nulldev,        nulldev,        pt_tty,
+       ptcselect,      nodev,          NULL,
+       logopen,        logclose,       logread,        nodev,          /*6*/
+       logioctl,       nodev,          nulldev,        NULL,
+       logselect,      nodev,          NULL,
+       ctopen,         ctclose,        ctread,         ctwrite,        /*7*/
+       ctioctl,        nodev,          nulldev,        NULL,
+       seltrue,        nodev,          ctstrategy,
+       sdopen,         nulldev,        sdread,         sdwrite,        /*8*/
+       sdioctl,        nodev,          nulldev,        NULL,
+       seltrue,        nodev,          sdstrategy,
+       rdopen,         nulldev,        rdread,         rdwrite,        /*9*/
+       rdioctl,        nodev,          nulldev,        NULL,
+       seltrue,        nodev,          rdstrategy,
+       grfopen,        grfclose,       nulldev,        nulldev,        /*10*/
+       grfioctl,       nodev,          nulldev,        NULL,
+       grfselect,      grfmap,         NULL,
+       ppiopen,        ppiclose,       ppiread,        ppiwrite,       /*11*/
+       nodev,          nodev,          nulldev,        NULL,
+       nodev,          nodev,          NULL,
+       dcaopen,        dcaclose,       dcaread,        dcawrite,       /*12*/
+       dcaioctl,       dcastop,        nulldev,        dca_tty,
+       ttselect,       nodev,          NULL,
+       iteopen,        iteclose,       iteread,        itewrite,       /*13*/
+       iteioctl,       nodev,          nulldev,        ite_tty,
+       ttselect,       nodev,          NULL,
+       hilopen,        hilclose,       hilread,        nulldev,        /*14*/
+       hilioctl,       nodev,          nulldev,        NULL,
+       hilselect,      hilmap,         NULL,
+       dcmopen,        dcmclose,       dcmread,        dcmwrite,       /*15*/
+       dcmioctl,       dcmstop,        nulldev,        dcm_tty,
+       ttselect,       nodev,          NULL,
+       nodev,          nodev,          nodev,          nodev,          /*16*/
+       nodev,          nodev,          nulldev,        NULL,
+       seltrue,        nodev,          NULL,
+       cdopen,         nulldev,        cdread,         cdwrite,        /*17*/
+       cdioctl,        nodev,          nulldev,        NULL,
+       seltrue,        nodev,          cdstrategy,
+       clockopen,      clockclose,     nulldev,        nulldev,        /*18*/
+       clockioctl,     nodev,          nulldev,        NULL,
+       nulldev,        clockmap,       NULL,
+       fdopen,         nulldev,        fdread,         fdwrite,        /*19*/
+       fdioctl,        nodev,          nulldev,        NULL,
+       seltrue,        nodev,          NULL,
+};
+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(3, 0);
diff --git a/usr/src/sys/hp300/hp300/dkbad.c b/usr/src/sys/hp300/hp300/dkbad.c
new file mode 100644 (file)
index 0000000..6937d02
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)dkbad.c     7.1 (Berkeley) %G%
+ */
+
+#ifndef NOBADSECT
+#include "param.h"
+#include "buf.h"
+#include "dkbad.h"
+
+/*
+ * Search the bad sector table looking for
+ * the specified sector.  Return index if found.
+ * Return -1 if not found.
+ */
+
+isbad(bt, cyl, trk, sec)
+       register struct dkbad *bt;
+{
+       register int i;
+       register long blk, bblk;
+
+       blk = ((long)cyl << 16) + (trk << 8) + sec;
+       for (i = 0; i < 126; i++) {
+               bblk = ((long)bt->bt_bad[i].bt_cyl << 16) + bt->bt_bad[i].bt_trksec;
+               if (blk == bblk)
+                       return (i);
+               if (blk < bblk || bblk < 0)
+                       break;
+       }
+       return (-1);
+}
+#endif
diff --git a/usr/src/sys/hp300/hp300/genassym.c b/usr/src/sys/hp300/hp300/genassym.c
new file mode 100644 (file)
index 0000000..0a9a369
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)genassym.c  7.1 (Berkeley) %G%
+ */
+
+#define KERNEL
+
+#include "pte.h"
+
+#include "param.h"
+#include "buf.h"
+#include "vmmeter.h"
+#include "vmparam.h"
+#include "user.h"
+#include "cmap.h"
+#include "map.h"
+#include "proc.h"
+#include "text.h"
+#include "mbuf.h"
+#include "msgbuf.h"
+#include "cpu.h"
+#include "trap.h"
+#include "psl.h"
+#include "reg.h"
+#include "clockreg.h"
+#include "syscall.h"
+
+main()
+{
+       register struct proc *p = (struct proc *)0;
+       register struct vmmeter *vm = (struct vmmeter *)0;
+       register struct user *up = (struct user *)0;
+       register struct rusage *rup = (struct rusage *)0;
+       struct text *tp = (struct text *)0;
+       struct pcb *pcb = (struct pcb *)0;
+       register unsigned i;
+
+       printf("#define\tP_LINK %d\n", &p->p_link);
+       printf("#define\tP_RLINK %d\n", &p->p_rlink);
+       printf("#define\tP_XLINK %d\n", &p->p_xlink);
+       printf("#define\tP_ADDR %d\n", &p->p_addr);
+       printf("#define\tP_PRI %d\n", &p->p_pri);
+       printf("#define\tP_STAT %d\n", &p->p_stat);
+       printf("#define\tP_WCHAN %d\n", &p->p_wchan);
+       printf("#define\tP_TSIZE %d\n", &p->p_tsize);
+       printf("#define\tP_DSIZE %d\n", &p->p_dsize);
+       printf("#define\tP_SSIZE %d\n", &p->p_ssize);
+       printf("#define\tP_P0BR %d\n", &p->p_p0br);
+       printf("#define\tP_SZPT %d\n", &p->p_szpt);
+       printf("#define\tP_TEXTP %d\n", &p->p_textp);
+       printf("#define\tP_FLAG %d\n", &p->p_flag);
+       printf("#define\tSSLEEP %d\n", SSLEEP);
+       printf("#define\tSRUN %d\n", SRUN);
+       printf("#define\tX_CADDR %d\n", &tp->x_caddr);
+       printf("#define\tV_SWTCH %d\n", &vm->v_swtch);
+       printf("#define\tV_TRAP %d\n", &vm->v_trap);
+       printf("#define\tV_SYSCALL %d\n", &vm->v_syscall);
+       printf("#define\tV_INTR %d\n", &vm->v_intr);
+       printf("#define\tV_SOFT %d\n", &vm->v_soft);
+       printf("#define\tV_PDMA %d\n", &vm->v_pdma);
+       printf("#define\tV_FAULTS %d\n", &vm->v_faults);
+       printf("#define\tV_PGREC %d\n", &vm->v_pgrec);
+       printf("#define\tV_FASTPGREC %d\n", &vm->v_fastpgrec);
+       printf("#define\tUPAGES %d\n", UPAGES);
+       printf("#define\tHIGHPAGES %d\n", HIGHPAGES);
+       printf("#define\tP1PAGES %d\n", P1PAGES);
+       printf("#define\tCLSIZE %d\n", CLSIZE);
+       printf("#define\tNBPG %d\n", NBPG);
+       printf("#define\tPGSHIFT %d\n", PGSHIFT);
+       printf("#define\tSYSPTSIZE %d\n", SYSPTSIZE);
+       printf("#define\tUSRPTSIZE %d\n", USRPTSIZE);
+       printf("#define\tUSRIOSIZE %d\n", USRIOSIZE);
+#ifdef SYSVSHM
+       printf("#define\tSHMMAXPGS %d\n", SHMMAXPGS);
+#endif
+       printf("#define\tUSRSTACK %d\n", USRSTACK);
+       printf("#define\tMSGBUFPTECNT %d\n", btoc(sizeof (struct msgbuf)));
+       printf("#define\tNMBCLUSTERS %d\n", NMBCLUSTERS);
+       printf("#define\tMCLBYTES %d\n", MCLBYTES);
+       printf("#define\tNKMEMCLUSTERS %d\n", NKMEMCLUSTERS);
+       printf("#define\tU_PROCP %d\n", &up->u_procp);
+       printf("#define\tU_RU %d\n", &up->u_ru);
+       printf("#define\tU_PROF %d\n", &up->u_prof);
+       printf("#define\tU_PROFSCALE %d\n", &up->u_prof.pr_scale);
+       printf("#define\tRU_MINFLT %d\n", &rup->ru_minflt);
+       printf("#define\tT_BUSERR %d\n", T_BUSERR);
+       printf("#define\tT_ADDRERR %d\n", T_ADDRERR);
+       printf("#define\tT_ILLINST %d\n", T_ILLINST);
+       printf("#define\tT_ZERODIV %d\n", T_ZERODIV);
+       printf("#define\tT_CHKINST %d\n", T_CHKINST);
+       printf("#define\tT_TRAPVINST %d\n", T_TRAPVINST);
+       printf("#define\tT_PRIVINST %d\n", T_PRIVINST);
+       printf("#define\tT_TRACE %d\n", T_TRACE);
+       printf("#define\tT_MMUFLT %d\n", T_MMUFLT);
+       printf("#define\tT_SSIR %d\n", T_SSIR);
+       printf("#define\tT_FMTERR %d\n", T_FMTERR);
+       printf("#define\tT_COPERR %d\n", T_COPERR);
+       printf("#define\tT_FPERR %d\n", T_FPERR);
+       printf("#define\tT_AST %d\n", T_AST);
+       printf("#define\tT_TRAP15 %d\n", T_TRAP15);
+       printf("#define\tPSL_S %d\n", PSL_S);
+       printf("#define\tPSL_IPL7 %d\n", PSL_IPL7);
+       printf("#define\tPSL_LOWIPL %d\n", PSL_LOWIPL);
+       printf("#define\tPSL_HIGHIPL %d\n", PSL_HIGHIPL);
+       printf("#define\tPSL_USER %d\n", PSL_USER);
+       printf("#define\tSPL1 %d\n", PSL_S | PSL_IPL1);
+       printf("#define\tSPL2 %d\n", PSL_S | PSL_IPL2);
+       printf("#define\tSPL3 %d\n", PSL_S | PSL_IPL3);
+       printf("#define\tSPL4 %d\n", PSL_S | PSL_IPL4);
+       printf("#define\tSPL5 %d\n", PSL_S | PSL_IPL5);
+       printf("#define\tSPL6 %d\n", PSL_S | PSL_IPL6);
+       printf("#define\tFC_USERD %d\n", FC_USERD);
+       printf("#define\tFC_PURGE %d\n", FC_PURGE);
+       printf("#define\tMAXADDR %d\n", MAXADDR);
+       printf("#define\tIOMAPSIZE %d\n", IOMAPSIZE);
+       printf("#define\tIOBASE %d\n", IOBASE);
+       printf("#define\tMMUSTAT %d\n", MMUSTAT);
+       printf("#define\tMMUCMD %d\n", MMUCMD);
+       printf("#define\tMMUSSTP %d\n", MMUSSTP);
+       printf("#define\tMMUUSTP %d\n", MMUUSTP);
+       printf("#define\tMMUTBINVAL %d\n", MMUTBINVAL);
+       printf("#define\tMMU_BERR %d\n", MMU_BERR);
+       printf("#define\tMMU_ENAB %d\n", MMU_ENAB);
+       printf("#define\tMMU_FAULT %d\n", MMU_FAULT);
+       printf("#define\tMMU_CEN %d\n", MMU_CEN);
+       printf("#define\tMMU_IEN %d\n", MMU_IEN);
+       printf("#define\tMMU_FPE %d\n", MMU_FPE);
+       printf("#define\tCACHE_ON %d\n", CACHE_ON);
+       printf("#define\tCACHE_OFF %d\n", CACHE_OFF);
+       printf("#define\tCACHE_CLR %d\n", CACHE_CLR);
+       printf("#define\tIC_CLEAR %d\n", IC_CLEAR);
+       printf("#define\tDC_CLEAR %d\n", DC_CLEAR);
+       printf("#define\tPG_V %d\n", PG_V);
+       printf("#define\tPG_NV %d\n", PG_NV);
+       printf("#define\tPG_RO %d\n", PG_RO);
+       printf("#define\tPG_RW %d\n", PG_RW);
+       printf("#define\tPG_CI %d\n", PG_CI);
+       printf("#define\tPG_PROT %d\n", PG_PROT);
+       printf("#define\tPG_FRAME %d\n", PG_FRAME);
+       printf("#define\tSG_V %d\n", SG_V);
+       printf("#define\tSG_NV %d\n", SG_NV);
+       printf("#define\tSG_RW %d\n", SG_RW);
+       printf("#define\tSG_FRAME %d\n", SG_FRAME);
+       printf("#define\tPCB_FLAGS %d\n", &pcb->pcb_flags);
+       printf("#define\tPCB_PS %d\n", &pcb->pcb_ps);
+       printf("#define\tPCB_USTP %d\n", &pcb->pcb_ustp);
+       printf("#define\tPCB_USP %d\n", &pcb->pcb_usp);
+       printf("#define\tPCB_REGS %d\n", pcb->pcb_regs);
+       printf("#define\tPCB_P0BR %d\n", &pcb->pcb_p0br);
+       printf("#define\tPCB_P0LR %d\n", &pcb->pcb_p0lr);
+       printf("#define\tPCB_P1BR %d\n", &pcb->pcb_p1br);
+       printf("#define\tPCB_P1LR %d\n", &pcb->pcb_p1lr);
+       printf("#define\tPCB_SZPT %d\n", &pcb->pcb_szpt);
+       printf("#define\tPCB_CMAP2 %d\n", &pcb->pcb_cmap2);
+       printf("#define\tPCB_SSWAP %d\n", &pcb->pcb_sswap);
+       printf("#define\tPCB_SIGC %d\n", pcb->pcb_sigc);
+       printf("#define\tPCB_ONFAULT %d\n", &pcb->pcb_onfault);
+       printf("#define\tPCB_FPCTX %d\n", &pcb->pcb_fpregs);
+       printf("#define\tSP %d\n", SP);
+       printf("#define\tB_READ %d\n", B_READ);
+       printf("#define\tENOENT %d\n", ENOENT);
+       printf("#define\tEFAULT %d\n", EFAULT);
+       printf("#define\tCLKCR1 %d\n", CLKCR1);
+       printf("#define\tCLKCR2 %d\n", CLKCR2);
+       printf("#define\tCLKCR3 %d\n", CLKCR3);
+       printf("#define\tCLKSR %d\n", CLKSR);
+       printf("#define\tCLKMSB1 %d\n", CLKMSB1);
+       printf("#define\tCLKMSB2 %d\n", CLKMSB2);
+       printf("#define\tCLKMSB3 %d\n", CLKMSB3);
+       printf("#define\tSYS_exit %d\n", SYS_exit);
+       printf("#define\tSYS_execv %d\n", SYS_execv);
+       printf("#define\tSYS_sigreturn %d\n", SYS_sigreturn);
+       for (i = 0; i < 32; i++) {
+               if ((1 << i) & SPTECHG)
+                       printf("#define\tSPTECHGB %d\n", i);
+               if ((1 << i) & PCB_AST)
+                       printf("#define\tPCB_ASTB %d\n", i);
+               if ((1 << i) & PCB_HPUXTRACE)
+                       printf("#define\tPCB_TRCB %d\n", i);
+       }
+       exit(0);
+}
diff --git a/usr/src/sys/hp300/hp300/in_cksum.c b/usr/src/sys/hp300/hp300/in_cksum.c
new file mode 100644 (file)
index 0000000..ef85d61
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1988, 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: in_cksum.c 1.6 89/08/24$
+ *
+ *     @(#)in_cksum.c  7.1 (Berkeley) %G%
+ */
+
+/*
+ * in_cksum - checksum routine for the Internet Protocol family.
+ */
+
+#include "param.h"
+#include "mbuf.h"
+#include "../netinet/in.h"
+#include "../netinet/in_systm.h"
+
+extern int oc_cksum();
+
+/*
+ * Checksum routine for the Internet Protocol family.
+ *
+ * This isn't as bad as it looks.  For ip headers the "while" isn't
+ * executed and we just drop through to the return statement at the
+ * end.  For the usual tcp or udp packet (a single header mbuf
+ * chained onto a cluster of data, we make exactly one trip through
+ * the while (for the header mbuf) and never do the hairy code
+ * inside the "if".  If fact, if m_copydata & sb_compact are doing
+ * their job, we should never do the hairy code inside the "if".
+ */
+in_cksum(m, len)
+       register struct mbuf *m;
+       register int len;
+{
+       register int sum = 0;
+       register int i;
+
+       while (len > m->m_len) {
+               sum = oc_cksum(mtod(m, u_char *), i = m->m_len, sum);
+               m = m->m_next;
+               len -= i;
+               if (i & 1) {
+                       /*
+                        * ouch - we ended on an odd byte with more
+                        * to do.  This xfer is obviously not interested
+                        * in performance so finish things slowly.
+                        */
+                       register u_char *cp;
+
+                       while (len > m->m_len) {
+                               cp = mtod(m, u_char *);
+                               if (i & 1) {
+                                       i = m->m_len - 1;
+                                       --len;
+                                       sum += *cp++;
+                               } else
+                                       i = m->m_len;
+
+                               sum = oc_cksum(cp, i, sum);
+                               m = m->m_next;
+                               len -= i;
+                       }
+                       if (i & 1) {
+                               cp =  mtod(m, u_char *);
+                               sum += *cp++;
+                               return (0xffff & ~oc_cksum(cp, len - 1, sum));
+                       }
+               }
+       }
+       return (0xffff & ~oc_cksum(mtod(m, u_char *), len, sum));
+}
diff --git a/usr/src/sys/hp300/hp300/isr.h b/usr/src/sys/hp300/hp300/isr.h
new file mode 100644 (file)
index 0000000..a8e3a0d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 1982 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)isr.h       7.1 (Berkeley) %G%
+ */
+
+struct isr {
+       struct  isr *isr_forw;
+       struct  isr *isr_back;
+       int     (*isr_intr)();
+       int     isr_arg;
+       int     isr_ipl;
+};
+
+#define        NISR            3
+#define        ISRIPL(x)       ((x) - 3)
diff --git a/usr/src/sys/hp300/hp300/kgdb_stub.c b/usr/src/sys/hp300/hp300/kgdb_stub.c
new file mode 100644 (file)
index 0000000..f35966e
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)kgdb_stub.c 7.1 (Berkeley) %G%
+ */
+
+/*
+ *
+ *    The following gdb commands are supported:
+ *
+ * command          function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#ifdef KGDB
+#include "param.h"
+#include "systm.h"
+#include "trap.h"
+#include "cpu.h"
+#include "psl.h"
+#include "reg.h"
+#include "frame.h"
+#include "buf.h"
+
+extern void printf();
+extern void bcopy();
+extern int kernacc();
+extern void chgkprot();
+
+/* # of additional (beyond 4) bytes in 680x0 exception frame format n */
+static int frame_bytes[16] = {
+       4,      4,      8,      4,
+       4,      4,      4,      4,
+       54,     16,     28,     88,
+       4,      4,      4,      4
+};
+
+#define USER    040             /* (XXX from trap.c) user-mode flag in type */
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound
+ * buffers.  At least NUMREGBYTES*2 are needed for register packets.
+ */
+#define BUFMAX 512
+
+int kgdb_dev = -1;             /* remote debugging device (-1 if none) */
+int kgdb_baud = 9600;          /* baud rate of serial line */
+int kgdb_debug_init = 0;       /* != 0 waits for remote at system init */
+int kgdb_debug = 0;            /* > 0 prints command & checksum errors */
+
+extern int dcacngetc();
+extern void dcacnputc();
+#define GETC (dcacngetc(kgdb_dev))
+#define PUTC(c) (dcacnputc(kgdb_dev, c))
+
+static char hexchars[] = "0123456789abcdef";
+
+/*
+ * There are 180 bytes of registers on a 68020 w/68881.  Many of the fpa
+ * registers are 12 byte (96 bit) registers.
+ */
+#define NUMREGBYTES 180
+
+static char inbuffer[BUFMAX];
+static char outbuffer[BUFMAX];
+
+static inline int 
+hex(ch)
+       char ch;
+{
+       if ((ch >= '0') && (ch <= '9'))
+               return (ch - '0');
+       if ((ch >= 'a') && (ch <= 'f'))
+               return (ch - ('a' - 10));
+       return (0);
+}
+
+/* scan for the sequence $<data>#<checksum>     */
+static void 
+getpacket(char *buffer)
+{
+       unsigned char checksum;
+       unsigned char xmitcsum;
+       int i;
+       int count;
+       char ch;
+
+       do {
+               /*
+                * wait around for the start character, ignore all other
+                * characters
+                */
+               while ((ch = GETC) != '$')
+                       ;
+               checksum = 0;
+               count = 0;
+               xmitcsum = 1;
+
+               /* now, read until a # or end of buffer is found */
+               while (count < BUFMAX) {
+                       ch = GETC;
+                       if (ch == '#')
+                               break;
+                       checksum = checksum + ch;
+                       buffer[count] = ch;
+                       count = count + 1;
+               }
+               buffer[count] = 0;
+
+               if (ch == '#') {
+                       xmitcsum = hex(GETC) << 4;
+                       xmitcsum += hex(GETC);
+                       if (kgdb_debug && (checksum != xmitcsum)) {
+                               printf(
+                       "bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
+                                       checksum, xmitcsum, buffer);
+                       }
+                       if (checksum != xmitcsum)
+                               PUTC('-');      /* failed checksum */
+                       else {
+                               PUTC('+');      /* successful transfer */
+                               /*
+                                * if a sequence char is present, reply the
+                                * sequence ID
+                                */
+                               if (buffer[2] == ':') {
+                                       PUTC(buffer[0]);
+                                       PUTC(buffer[1]);
+                                       /* remove sequence chars from buffer */
+                                       for (i = 3; i <= count; ++i)
+                                               buffer[i - 3] = buffer[i];
+                               }
+                       }
+               }
+       } while (checksum != xmitcsum);
+}
+
+/*
+ * send the packet in buffer.  The host gets one chance to read it.  This
+ * routine does not wait for a positive acknowledge.
+ */
+static void 
+putpacket(char *buffer)
+{
+       unsigned char checksum;
+       int count;
+       char ch;
+
+       /* $<packet info>#<checksum>. */
+       do {
+               PUTC('$');
+               checksum = 0;
+               count = 0;
+
+               while (ch = buffer[count]) {
+                       PUTC(ch);
+                       checksum += ch;
+                       count += 1;
+               }
+               PUTC('#');
+               PUTC(hexchars[checksum >> 4]);
+               PUTC(hexchars[checksum & 15]);
+
+       } while (0);    /* (GETC != '+'); */
+
+}
+
+static inline void 
+debug_error(char *format, char *parm)
+{
+       if (kgdb_debug)
+               printf(format, parm);
+}
+
+/*
+ * Convert at most 'dig' digits of hex data in buf into a value.
+ * Stop on non-hex char.  Return a pointer to next char in buf.
+ */
+static char *
+hex2val(char *buf, int *val, int dig)
+{
+       int i, v;
+       char ch;
+
+       v = 0;
+       for (i = dig; --i >= 0; ) {
+               ch = *buf++;
+               if ((ch >= '0') && (ch <= '9'))
+                       v = (v << 4) | (ch - '0');
+               else if ((ch >= 'a') && (ch <= 'f'))
+                       v = (v << 4) | (ch - ('a' - 10));
+               else {
+                       --buf;
+                       break;
+               }
+       }
+       *val = v;
+       return (buf);
+}
+
+/*
+ * convert the integer value 'val' into 'dig' hex digits, placing
+ * result in buf.  Return a pointer to the last char put in buf (null).
+ */
+static char *
+val2hex(char *buf, int val, int dig)
+{
+       for (dig <<= 2; (dig -= 4) >= 0; )
+               *buf++ = hexchars[(val >> dig) & 0xf];
+       *buf = 0;
+       return (buf);
+}
+
+/*
+ * convert the memory pointed to by mem into hex, placing result in buf.
+ * return a pointer to the last char put in buf (null).
+ */
+static char *
+mem2hex(char *buf, char *mem, int count)
+{
+       if ((count & 1) || ((int)mem & 1)) {
+               char ch;
+
+               while(--count >= 0) {
+                       ch = *mem++;
+                       *buf++ = hexchars[ch >> 4];
+                       *buf++ = hexchars[ch & 15];
+               }
+       } else {
+               u_short s;
+               u_short *mp = (u_short *)mem;
+
+               for (count >>= 1; --count >= 0; ) {
+                       s = *mp++;
+                       *buf++ = hexchars[(s >> 12) & 15];
+                       *buf++ = hexchars[(s >> 8) & 15];
+                       *buf++ = hexchars[(s >> 4) & 15];
+                       *buf++ = hexchars[s & 15];
+               }
+       }
+       *buf = 0;
+       return (buf);
+}
+
+/*
+ * Convert the hex array pointed to by buf into binary to be placed in mem.
+ * Return a pointer to next char in buf.
+ */
+static char *
+hex2mem(char *buf, char *mem, int count)
+{
+       int i;
+       unsigned char ch;
+
+       for (i = 0; i < count; ++i) {
+               ch = hex(*buf++) << 4;
+               ch = ch + hex(*buf++);
+               *mem++ = ch;
+       }
+       return (buf);
+}
+
+/*
+ * Translate a trap number into a unix compatible signal value.
+ * (gdb only understands unix signal numbers).
+ */
+static int 
+computeSignal(int type)
+{
+       int sigval;
+
+       switch (type &~ USER) {
+       case T_BUSERR:
+               sigval = SIGBUS;
+               break;          /* bus error           */
+       case T_ADDRERR:
+               sigval = SIGBUS;
+               break;          /* address error       */
+       case T_ILLINST:
+               sigval = SIGILL;
+               break;          /* illegal instruction */
+       case T_ZERODIV:
+               sigval = SIGFPE;
+               break;          /* zero divide         */
+       case T_CHKINST:
+               sigval = SIGFPE;
+               break;          /* chk instruction     */
+       case T_TRAPVINST:
+               sigval = SIGFPE;
+               break;          /* trapv instruction   */
+       case T_PRIVINST:
+               sigval = SIGILL;
+               break;          /* privilege violation */
+       case T_TRACE:
+               sigval = SIGTRAP;
+               break;          /* trace trap          */
+       case T_MMUFLT:
+               sigval = SIGSEGV;
+               break;
+       case T_SSIR:
+               sigval = SIGSEGV;
+               break;
+       case T_FMTERR:
+               sigval = SIGILL;
+               break;
+       case T_FPERR:
+               sigval = SIGFPE;
+               break;
+       case T_COPERR:
+               sigval = SIGFPE;
+               break;
+       case T_AST:
+               sigval = SIGINT;
+               break;
+       case T_TRAP15:
+               sigval = SIGIOT;
+               break;
+       default:
+               sigval = SIGEMT;
+               break;
+       }
+       return (sigval);
+}
+
+#define RESPOND(str) (bcopy(str, outbuffer, sizeof(str)))
+
+/*
+ * This function does all command procesing for interfacing to 
+ * a remote gdb.
+ */
+int 
+kgdb_trap(int type, unsigned code, unsigned v, struct frame *frame)
+{
+       int sigval;
+       int addr, length;
+       char *ptr;
+
+       if (kgdb_dev < 0)
+               /* not debugging */
+               return (0);
+
+       if (kgdb_debug)
+               printf("type=%d, code=%d, vector=0x%x, pc=0x%x, sr=0x%x\n",
+                       type, code, frame->f_vector, frame->f_pc, frame->f_sr);
+
+       /* reply to host that an exception has occurred */
+       sigval = computeSignal(type);
+       outbuffer[0] = 'S';
+       (void)val2hex(&outbuffer[1], sigval, 2);
+       putpacket(outbuffer);
+
+       while (1) {
+               outbuffer[0] = 0;
+               getpacket(inbuffer);
+               ptr = inbuffer;
+               switch (*ptr++) {
+               case '?':
+                       outbuffer[0] = 'S';
+                       (void)val2hex(&outbuffer[1], sigval, 2);
+                       break;
+               case 'g':       /* return the value of the CPU registers */
+                       ptr = outbuffer;
+                       if (type & USER)
+                               ptr = mem2hex(ptr, (char *)frame->f_regs,
+                                             sizeof(frame->f_regs));
+                       else {
+                               ptr = mem2hex(ptr, (char *)frame->f_regs,
+                                             sizeof(frame->f_regs) - 4);
+                               addr = (int)&frame->f_pc -
+                                       frame_bytes[frame->f_format];
+                               ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
+                       }
+                       addr = frame->f_sr;
+                       ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
+                       ptr = mem2hex(ptr, (char *)&frame->f_pc,
+                                     sizeof(frame->f_pc));
+                       break;
+               case 'G':       /* set the value of the CPU registers */
+                       ptr = hex2mem(ptr, (char *)frame->f_regs,
+                                     sizeof(frame->f_regs) - 4);
+                       ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
+                       ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
+                       frame->f_sr = addr;
+                       ptr = hex2mem(ptr, (char *)&frame->f_pc,
+                                     sizeof(frame->f_pc));
+                       RESPOND("OK");
+                       break;
+
+                       /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
+               case 'm':
+                       ptr = hex2val(ptr, &addr, 8);
+                       if (*ptr++ != ',') {
+                               RESPOND("E01");
+                               debug_error("malformed read memory cmd: %s\n",
+                                           inbuffer);
+                               break;
+                       }
+                       ptr = hex2val(ptr, &length, 8);
+                       if (length <= 0 || length >= BUFMAX*2) {
+                               RESPOND("E02");
+                               if (kgdb_debug)
+                                       printf("bad read memory length: %d\n",
+                                              length);
+                               break;
+                       }
+                       if (! kernacc(addr, length, B_READ)) {
+                               RESPOND("E03");
+                               if (kgdb_debug)
+                                       printf("read access violation addr 0x%x len %d\n", addr, length);
+                               break;
+                       }
+                       (void)mem2hex(outbuffer, (char *)addr, length);
+                       break;
+
+                       /*
+                        * MAA..AA,LLLL: Write LLLL bytes at address AA.AA
+                        * return OK
+                        */
+               case 'M':
+                       ptr = hex2val(ptr, &addr, 8);
+                       if (*ptr++ != ',') {
+                               RESPOND("E01");
+                               debug_error("malformed write memory cmd: %s\n",
+                                           inbuffer);
+                               break;
+                       }
+                       ptr = hex2val(ptr, &length, 8);
+                       if (*ptr++ != ':') {
+                               RESPOND("E01");
+                               debug_error("malformed write memory cmd: %s\n",
+                                           inbuffer);
+                               break;
+                       }
+                       if (length <= 0 || length >= BUFMAX*2 - 32) {
+                               RESPOND("E02");
+                               if (kgdb_debug)
+                                       printf("bad write memory length: %d\n",
+                                              length);
+                               break;
+                       }
+                       if (! kernacc(addr, length, B_READ)) {
+                               RESPOND("E03");
+                               if (kgdb_debug)
+                                       printf("write access violation addr 0x%x len %d\n", addr, length);
+                               break;
+                       }
+                       if (! kernacc(addr, length, B_WRITE))
+                               chgkprot(addr, length, B_WRITE);
+                       (void)hex2mem(ptr, (char *)addr, length);
+                       RESPOND("OK");
+                       break;
+
+                       /*
+                        * cAA..AA  Continue at address AA..AA
+                        * sAA..AA  Step one instruction from AA..AA
+                        * (addresses optional)
+                        */
+               case 'c':
+               case 's':
+                       /*
+                        * try to read optional start address.
+                        */
+                       if (ptr != hex2val(ptr, &addr, 8)) {
+                               frame->f_pc = addr;
+                               if (kgdb_debug)
+                                       printf("new pc = 0x%x\n", addr);
+                       }
+                       /* deal with the trace bit */
+                       if (inbuffer[0] == 's')
+                               frame->f_sr |= PSL_T;
+                       else
+                               frame->f_sr &=~ PSL_T;
+
+                       if (kgdb_debug)
+                               printf("restarting at 0x%x\n", frame->f_pc);
+
+                       return (1);
+
+                       /* kill the program (same as continue for now) */
+               case 'k':
+                       return (1);
+               }
+               /* reply to the request */
+               putpacket(outbuffer);
+       }
+}
+#endif
diff --git a/usr/src/sys/hp300/hp300/locore.s b/usr/src/sys/hp300/hp300/locore.s
new file mode 100644 (file)
index 0000000..004c505
--- /dev/null
@@ -0,0 +1,2521 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1980, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: locore.s 1.47 89/10/08$
+ *
+ *     @(#)locore.s    7.1 (Berkeley) %G%
+ */
+
+       .text
+/*
+ * This is where we wind up if the kernel jumps to location 0.
+ * (i.e. a bogus PC)  This is known to immediately follow the vector
+ * table and is hence at 0x400 (see reset vector in vectors.s).
+ */
+       .globl  _panic
+       pea     Ljmp0panic
+       jbsr    _panic
+       /* NOTREACHED */
+Ljmp0panic:
+       .asciz  "kernel jump to zero"
+       .even
+
+/*
+ * Do a dump.
+ * Called by auto-restart.
+ */
+       .globl  _dumpsys
+       .globl  _doadump
+_doadump:
+       jbsr    _dumpsys
+       jbsr    _doboot
+       /*NOTREACHED*/
+
+/*
+ * Trap/interrupt vector routines
+ */ 
+
+       .globl  _trap, _nofault, _longjmp
+_buserr:
+       tstl    _nofault                | device probe?
+       jeq     _addrerr                | no, handle as usual
+       movl    _nofault,sp@-           | yes,
+       jbsr    _longjmp                |  longjmp(nofault)
+_addrerr:
+       clrw    sp@-                    | pad SR to longword
+       moveml  #0xFFFF,sp@-            | save user registers
+       movl    usp,a0                  | save the user SP
+       movl    a0,sp@(60)              |   in the savearea
+       lea     sp@(64),a1              | grab base of HW berr frame
+       movw    a1@(12),d0              | grab SSW for fault processing
+       btst    #12,d0                  | RB set?
+       jeq     LbeX0                   | no, test RC
+       bset    #14,d0                  | yes, must set FB
+       movw    d0,a1@(12)              | for hardware too
+LbeX0:
+       btst    #13,d0                  | RC set?
+       jeq     LbeX1                   | no, skip
+       bset    #15,d0                  | yes, must set FC
+       movw    d0,a1@(12)              | for hardware too
+LbeX1:
+       btst    #8,d0                   | data fault?
+       jeq     Lbe0                    | no, check for hard cases
+       movl    a1@(18),d1              | fault address is as given in frame
+       jra     Lbe10                   | thats it
+Lbe0:
+       btst    #4,a1@(8)               | long (type B) stack frame?
+       jne     Lbe4                    | yes, go handle
+       movl    a1@(4),d1               | no, can use save PC
+       btst    #14,d0                  | FB set?
+       jeq     Lbe3                    | no, try FC
+       addql   #4,d1                   | yes, adjust address
+       jra     Lbe10                   | done
+Lbe3:
+       btst    #15,d0                  | FC set?
+       jeq     Lbe10                   | no, done
+       addql   #2,d1                   | yes, adjust address
+       jra     Lbe10                   | done
+Lbe4:
+       movl    a1@(38),d1              | long format, use stage B address
+       btst    #15,d0                  | FC set?
+       jeq     Lbe10                   | no, all done
+       subql   #2,d1                   | yes, adjust address
+Lbe10:
+       movl    d1,sp@-                 | push fault VA
+       movw    d0,sp@-                 | and SSW
+       clrw    sp@-                    |   padded to longword
+       movw    a1@(8),d0               | get frame format/vector offset
+       andw    #0x0FFF,d0              | clear out frame format
+       cmpw    #12,d0                  | address error vector?
+       jeq     Lisaerr                 | yes, go to it
+#if defined(HP330) || defined(HP360) || defined(HP370)
+       tstl    _mmutype                | HP MMU?
+       jeq     Lbehpmmu                | yes, skip
+       movl    d1,a0                   | fault address
+       .long   0xf0109e11              | ptestr #1,a0@,#7
+       .long   0xf0176200              | pmove psr,sp@
+       btst    #7,sp@                  | bus error bit set?
+       jeq     Lismerr                 | no, must be MMU fault
+       clrw    sp@                     | yes, re-clear pad word
+       jra     Lisberr                 | and process as normal bus error
+Lbehpmmu:
+#endif
+#if defined(HP320) || defined(HP350)
+       lea     _IObase+MMUSTAT,a0      | no, get addr of MMU status
+       movl    a0@,d0                  | read status
+       btst    #3,d0                   | MMU fault?
+       jeq     Lisberr                 | no, just a non-MMU bus error so skip
+       andl    #~MMU_FAULT,a0@         | yes, clear fault bits
+       movw    d0,sp@                  | pass MMU stat in upper half of code
+#endif
+Lismerr:
+       movl    #T_MMUFLT,sp@-          | show that we are an MMU fault
+       jra     Lbexit                  | and deal with it
+Lisaerr:
+       movl    #T_ADDRERR,sp@-         | mark address error
+       jra     Lbexit                  | and deal with it
+Lisberr:
+       movl    #T_BUSERR,sp@-          | mark bus error
+Lbexit:
+       jbsr    _trap                   | handle the error
+       lea     sp@(12),sp              | pop value args
+       movl    sp@(60),a0              | restore user SP
+       movl    a0,usp                  |   from save area
+       moveml  sp@+,#0x7FFF            | restore most user regs
+       addql   #4,sp                   | toss SSP
+       tstw    sp@+                    | do we need to clean up stack?
+       jeq     rei                     | no, just continue
+       btst    #7,sp@(6)               | type 9/10/11 frame?
+       jeq     rei                     | no, nothing to do
+       btst    #5,sp@(6)               | type 9?
+       jne     Lbex1                   | no, skip
+       movw    sp@,sp@(12)             | yes, push down SR
+       movl    sp@(2),sp@(14)          | and PC
+       clrw    sp@(18)                 | and mark as type 0 frame
+       lea     sp@(12),sp              | clean the excess
+       jra     rei                     | all done
+Lbex1:
+       btst    #4,sp@(6)               | type 10?
+       jne     Lbex2                   | no, skip
+       movw    sp@,sp@(24)             | yes, push down SR
+       movl    sp@(2),sp@(26)          | and PC
+       clrw    sp@(30)                 | and mark as type 0 frame
+       lea     sp@(24),sp              | clean the excess
+       jra     rei                     | all done
+Lbex2:
+       movw    sp@,sp@(84)             | type 11, push down SR
+       movl    sp@(2),sp@(86)          | and PC
+       clrw    sp@(90)                 | and mark as type 0 frame
+       lea     sp@(84),sp              | clean the excess
+       jra     rei                     | all done
+
+_illinst:
+       clrw    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_ILLINST,d0
+       jra     _fault
+
+_zerodiv:
+       clrw    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_ZERODIV,d0
+       jra     _fault
+
+_chkinst:
+       clrw    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_CHKINST,d0
+       jra     _fault
+
+_trapvinst:
+       clrw    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_TRAPVINST,d0
+       jra     _fault
+
+_privinst:
+       clrw    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_PRIVINST,d0
+       jra     _fault
+
+_coperr:
+       clrw    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_COPERR,d0
+       jra     _fault
+
+_fmterr:
+       clrw    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_FMTERR,d0
+       jra     _fault
+
+_fptrap:
+#ifdef FPCOPROC
+       clrw    sp@-            | pad SR to longword
+       moveml  #0xFFFF,sp@-    | save user registers
+       movl    usp,a0          | and save
+       movl    a0,sp@(60)      |   the user stack pointer
+       clrl    sp@-            | no VA arg
+       lea     _u+PCB_FPCTX,a0 | address of FP savearea
+       .word   0xf310          | fsave a0@
+       tstb    a0@             | null state frame?
+       jeq     Lfptnull        | yes, safe
+       clrw    d0              | no, need to tweak BIU
+       movb    a0@(1),d0       | get frame size
+       bset    #3,a0@(0,d0:w)  | set exc_pend bit of BIU
+Lfptnull:
+       .word   0xf227,0xa800   | fmovem fpsr,sp@- (code arg)
+       .word   0xf350          | frestore a0@
+       movl    #T_FPERR,sp@-   | push type arg
+       jbsr    _trap           | call trap
+       lea     sp@(12),sp      | pop value args
+       movl    sp@(60),a0      | restore
+       movl    a0,usp          |   user SP
+       moveml  sp@+,#0x7FFF    | and remaining user registers
+       addql   #6,sp           | pop SSP and align word
+       jra     rei             | all done
+#else
+       jra     _badtrap        | treat as an unexpected trap
+#endif
+
+       .globl  _fault
+_fault:
+       movl    usp,a0          | get and save
+       movl    a0,sp@(60)      |   the user stack pointer
+       clrl    sp@-            | no VA arg
+       clrl    sp@-            | or code arg
+       movl    d0,sp@-         | push trap type
+       jbsr    _trap           | handle trap
+       lea     sp@(12),sp      | pop value args
+       movl    sp@(60),a0      | restore
+       movl    a0,usp          |   user SP
+       moveml  sp@+,#0x7FFF    | restore most user regs
+       addql   #6,sp           | pop SP and pad word
+       jra     rei             | all done
+
+       .globl  _straytrap
+_badtrap:
+       clrw    sp@-
+       moveml  #0xC0C0,sp@-
+       movw    sp@(24),sp@-
+       clrw    sp@-
+       jbsr    _straytrap
+       addql   #4,sp
+       moveml  sp@+,#0x0303
+       addql   #2,sp
+       jra     rei
+
+       .globl  _syscall
+_trap0:
+       clrw    sp@-                    | pad SR to longword
+       moveml  #0xFFFF,sp@-            | save user registers
+       movl    usp,a0                  | save the user SP
+       movl    a0,sp@(60)              |   in the savearea
+       movl    d0,sp@-                 | push syscall number
+       jbsr    _syscall                | handle it
+       addql   #4,sp                   | pop syscall arg
+       movl    sp@(60),a0              | grab and restore
+       movl    a0,usp                  |   user SP
+       moveml  sp@+,#0x7FFF            | restore most registers
+       addql   #6,sp                   | pop SSP and align word
+       jra     rei                     | all done
+
+/*
+ * Routines for traps 1 and 2.  The meaning of the two traps depends
+ * on whether we are an HPUX compatible process or a native 4.3 process.
+ * Our native 4.3 implementation uses trap 1 as sigreturn() and trap 2
+ * as a breakpoint trap.  HPUX uses trap 1 for a breakpoint, so we have
+ * to make adjustments so that trap 2 is used for sigreturn.
+ */
+_trap1:
+       btst    #PCB_TRCB,_u+PCB_FLAGS+1| being traced by an HPUX process?
+       jeq     sigreturn               | no, trap1 is sigreturn
+       jra     _trace                  | yes, trap1 is breakpoint
+
+_trap2:
+       btst    #PCB_TRCB,_u+PCB_FLAGS+1| being traced by an HPUX process?
+       jeq     _trace                  | no, trap2 is breakpoint
+       jra     sigreturn               | yes, trap2 is sigreturn
+
+/*
+ * Trap 15 is used for:
+ *     - KGDB traps
+ *     - trace traps for SUN binaries (not fully supported yet)
+ * We just pass it on and let trap() sort it all out
+ */
+_trap15:
+       clrw    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_TRAP15,d0
+       jra     _fault
+
+/*
+ * Hit a breakpoint (trap 1 or 2) instruction.
+ * Push the code and treat as a normal fault.
+ */
+_trace:
+       clrw    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_TRACE,d0
+       jra     _fault
+
+/*
+ * The sigreturn() syscall comes here.  It requires special handling
+ * because we must open a hole in the stack to fill in the (possibly much
+ * larger) original stack frame.
+ */
+sigreturn:
+       lea     sp@(-84),sp             | leave enough space for largest frame
+       movl    sp@(84),sp@             | move up current 8 byte frame
+       movl    sp@(88),sp@(4)
+       movw    #0xFFFF,sp@-            | default: must clean stack
+       moveml  #0xFFFF,sp@-            | save user registers
+       movl    usp,a0                  | save the user SP
+       movl    a0,sp@(60)              |   in the savearea
+       movl    #SYS_sigreturn,sp@-     | push syscall number
+       jbsr    _syscall                | handle it
+       addql   #4,sp                   | pop syscall#
+       movl    sp@(60),a0              | grab and restore
+       movl    a0,usp                  |   user SP
+       lea     sp@(64),a1              | pointer to HW frame
+       tstw    a1@+                    | do we need to clean up stack?
+       jeq     Lsigr1                  | no, just continue
+       movb    a1@(6),d0               | grab format byte
+       lsrb    #4,d0                   | get rid of excess
+       cmpb    #10,d0                  | type 10 frame?
+       jne     Lsigr2                  | no, continue
+       movw    #32,d1                  | yes, frame size is 32 bytes
+       jra     Lsigrcp                 | go to it
+Lsigr2:
+       cmpb    #9,d0                   | type 9?
+       jne     Lsigr3                  | no, continue
+       movw    #20,d1                  | yes, frame size is 20 bytes
+       jra     Lsigrcp                 | go to it
+Lsigr3:
+       cmpb    #2,d0                   | type 2?
+       jne     Lsigr4                  | no, continue
+       movw    #12,d1                  | yes, frame size is 12 bytes
+       jra     Lsigrcp                 | go to it
+Lsigr4:
+       movw    #8,d1                   | must be type 0/1, size is 8 bytes
+Lsigrcp:
+       lea     a1@(92),a0              | destination
+       addw    d1,a1                   | source
+       lsrw    #1,d1                   | convert to word count
+       subqw   #1,d1                   | minus 1 for dbf
+Lsigrlp:
+       movw    a1@-,a0@-               | copy a word
+       dbf     d1,Lsigrlp              | continue
+       movl    a0,a1                   | new HW frame base
+Lsigr1:
+       movl    a1,sp@(60)              | new SP value
+       moveml  sp@+,#0x7FFF            | restore user registers
+       movl    sp@,sp                  | and our SP
+       jra     rei                     | all done
+
+/*
+ * Interrupt handlers.
+ * All DIO device interrupts are auto-vectored.  Most can be configured
+ * to interrupt in the range IPL3 to IPL5.  Here are our assignments:
+ *
+ *     Level 0:        Spurious: ignored.
+ *     Level 1:        HIL
+ *     Level 2:
+ *     Level 3:        Internal HP-IB
+ *     Level 4:        "Fast" HP-IBs, SCSI
+ *     Level 5:        DMA, Ethernet, Built-in RS232
+ *     Level 6:        Clock
+ *     Level 7:        Non-maskable: parity errors, RESET key
+ */
+       .globl  _hilint, _intrhand, _hardclock, _nmihand
+
+_spurintr:
+       addql   #1,_intrcnt+0
+       addql   #1,_cnt+V_INTR
+       jra     rei
+
+_lev1intr:
+       addql   #1,_intrcnt+4
+       clrw    sp@-
+       moveml  #0xC0C0,sp@-
+       jbsr    _hilint
+       moveml  sp@+,#0x0303
+       addql   #2,sp
+       addql   #1,_cnt+V_INTR
+       jra     rei
+
+/* check for DMA first to reduce overhead */
+_lev5intr:
+       clrw    sp@-
+       moveml  #0xC0C0,sp@-
+       jbsr    _dmaintr
+       tstl    d0
+       jeq     Lnotdma
+       addql   #1,_intrcnt+24
+       moveml  sp@+,#0x0303
+       addql   #2,sp
+       addql   #1,_cnt+V_INTR
+       jra     rei
+
+_lev2intr:
+_lev3intr:
+_lev4intr:
+       clrw    sp@-
+       moveml  #0xC0C0,sp@-
+Lnotdma:
+       lea     _intrcnt,a0
+       movw    sp@(24),d0              | use vector offset
+       andw    #0xfff,d0               |   sans frame type
+       addql   #1,a0@(-0x60,d0:w)      |     to increment apropos counter
+       movw    sr,sp@-                 | push current SR value
+       clrw    sp@-                    |    padded to longword
+       jbsr    _intrhand               | handle interrupt
+       addql   #4,sp                   | pop SR
+       moveml  sp@+,#0x0303
+       addql   #2,sp
+       addql   #1,_cnt+V_INTR
+       jra     rei
+
+_lev6intr:
+       clrw    sp@-
+       moveml  #0xC0C0,sp@-
+#ifdef DEBUG
+       .globl  _panicstr, _regdump, _panic
+       tstl    timebomb                | set to go off?
+       jeq     Lnobomb                 | no, skip it
+       subql   #1,timebomb             | decrement
+       jne     Lnobomb                 | not ready to go off
+       moveml  sp@+,#0x0303            | temporarily restore regs
+       jra     Luseours                | go die
+Lnobomb:
+       cmpl    #_u+NBPG+NBPG,sp        | our we still in stack page?
+       jcc     Lstackok                | yes, continue normally
+       tstl    _panicstr               | have we paniced?
+       jne     Lstackok                | yes, do not re-panic
+       moveml  sp@+,#0x0303            | no, temporarily restore regs
+       cmpl    #_u+NBPG+0x400,sp       | our we safely in redzone?
+       jcc     Luseours                | yes, panic with this stack
+       lea     tmpstk,sp               | no, switch to tmpstk
+Luseours:
+       moveml  #0xFFFF,sp@-            | push all registers
+       movl    sp,a0                   | remember this spot
+       movl    #256,sp@-               | longword count
+       movl    a0,sp@-                 | and reg pointer
+       jbsr    _regdump                | dump core
+       addql   #8,sp                   | pop params
+       movl    #Lstkrip,sp@-           | push panic message
+       jbsr    _panic                  | ES and D
+Lstkrip:
+       .asciz  "k-stack overflow"
+       .even
+Lstackok:
+#endif
+       movb    _IObase+CLKSR,d0        | read clock status
+#ifdef PROFTIMER
+       .globl  _profon
+       tstb    _profon                 | profile clock on?
+       jeq     Ltimer1                 | no, then must be timer1 interrupt
+       btst    #2,d0                   | timer3 interrupt?
+       jeq     Ltimer1                 | no, must be timer1
+       movb    _IObase+CLKMSB3,d1      | clear timer3 interrupt
+       lea     sp@(16),a1              | get pointer to PS
+#ifdef GPROF
+       .globl  _profclock
+       movl    d0,sp@-                 | save status so jsr will not clobber
+       movl    a1@,sp@-                | push padded PS
+       movl    a1@(4),sp@-             | push PC
+       jbsr    _profclock              | profclock(pc, ps)
+       addql   #8,sp                   | pop params
+#else
+       btst    #5,a1@(2)               | saved PS in user mode?
+       jne     Lttimer1                | no, go check timer1
+       tstl    _u+U_PROFSCALE          | process being profiled?
+       jeq     Lttimer1                | no, go check timer1
+       movl    d0,sp@-                 | save status so jsr will not clobber
+       movl    #1,sp@-
+       movl    #_u+U_PROF,sp@-
+       movl    a1@(4),sp@-
+       jbsr    _addupc                 | addupc(pc, &u.u_prof, 1)
+       lea     sp@(12),sp              | pop params
+#endif
+       addql   #1,_intrcnt+32          | add another profile clock interrupt
+       movl    sp@+,d0                 | get saved clock status
+Lttimer1:
+       btst    #0,d0                   | timer1 interrupt?
+       jeq     Ltimend                 | no, check state of kernel profiling
+Ltimer1:
+#endif
+       movb    _IObase+CLKMSB1,d1      | clear timer1 interrupt
+       lea     sp@(16),a1              | get pointer to PS
+       movl    a1@,sp@-                | push padded PS
+       movl    a1@(4),sp@-             | push PC
+       jbsr    _hardclock              | call generic clock int routine
+       addql   #8,sp                   | pop params
+       addql   #1,_intrcnt+28          | add another system clock interrupt
+#ifdef PROFTIMER
+Ltimend:
+#ifdef GPROF
+       .globl  _profiling, _startprofclock
+       tstl    _profiling              | kernel profiling desired?
+       jne     Ltimdone                | no, all done
+       bset    #7,_profon              | mark continuous timing
+       jne     Ltimdone                | was already enabled, all done
+       jbsr    _startprofclock         | else turn it on
+Ltimdone:
+#endif
+#endif
+       moveml  sp@+,#0x0303            | restore scratch regs
+       addql   #2,sp                   | pop pad word
+       addql   #1,_cnt+V_INTR          | chalk up another interrupt
+       jra     rei                     | all done
+
+_lev7intr:
+#ifdef PROFTIMER
+       addql   #1,_intrcnt+36
+#else
+       addql   #1,_intrcnt+32
+#endif
+       clrw    sp@-                    | pad SR to longword
+       moveml  #0xFFFF,sp@-            | save registers
+       movl    usp,a0                  | and save
+       movl    a0,sp@(60)              |   the user stack pointer
+       jbsr    _nmihand                | call handler
+       movl    sp@(60),a0              | restore
+       movl    a0,usp                  |   user SP
+       moveml  sp@+,#0x7FFF            | and remaining registers
+       addql   #6,sp                   | pop SSP and align word
+       jra     rei                     | all done
+
+/*
+ * Emulation of VAX REI instruction.
+ *
+ * This code deals with checking for and servicing ASTs
+ * (profiling, scheduling) and software interrupts (network, softclock).
+ * We check for ASTs first, just like the VAX.  To avoid excess overhead
+ * the T_AST handling code will also check for software interrupts so we
+ * do not have to do it here.
+ *
+ * This code is complicated by the fact that sendsig may have been called
+ * necessitating a stack cleanup.  A cleanup should only be needed at this
+ * point for coprocessor mid-instruction frames (type 9), but we also test
+ * for bus error frames (type 10 and 11).
+ */
+       .comm   _ssir,1
+rei:
+#ifdef DEBUG
+       tstl    _panicstr               | have we paniced?
+       jne     Ldorte                  | yes, do not make matters worse
+#endif
+       btst    #PCB_ASTB,_u+PCB_FLAGS+1| AST pending?
+       jeq     Lchksir                 | no, go check for SIR
+       btst    #5,sp@                  | yes, are we returning to user mode?
+       jne     Lchksir                 | no, go check for SIR
+       clrw    sp@-                    | pad SR to longword
+       moveml  #0xFFFF,sp@-            | save all registers
+       movl    usp,a1                  | including
+       movl    a1,sp@(60)              |    the users SP
+       clrl    sp@-                    | VA == none
+       clrl    sp@-                    | code == none
+       movl    #T_AST,sp@-             | type == async system trap
+       jbsr    _trap                   | go handle it
+       lea     sp@(12),sp              | pop value args
+       movl    sp@(60),a0              | restore
+       movl    a0,usp                  |   user SP
+       moveml  sp@+,#0x7FFF            | and all remaining registers
+       addql   #4,sp                   | toss SSP
+       tstw    sp@+                    | do we need to clean up stack?
+       jeq     Ldorte                  | no, just continue
+       btst    #7,sp@(6)               | type 9/10/11 frame?
+       jeq     Ldorte                  | no, nothing to do
+       btst    #5,sp@(6)               | type 9?
+       jne     Last1                   | no, skip
+       movw    sp@,sp@(12)             | yes, push down SR
+       movl    sp@(2),sp@(14)          | and PC
+       clrw    sp@(18)                 | and mark as type 0 frame
+       lea     sp@(12),sp              | clean the excess
+       jra     Ldorte                  | all done
+Last1:
+       btst    #4,sp@(6)               | type 10?
+       jne     Last2                   | no, skip
+       movw    sp@,sp@(24)             | yes, push down SR
+       movl    sp@(2),sp@(26)          | and PC
+       clrw    sp@(30)                 | and mark as type 0 frame
+       lea     sp@(24),sp              | clean the excess
+       jra     Ldorte                  | all done
+Last2:
+       movw    sp@,sp@(84)             | type 11, push down SR
+       movl    sp@(2),sp@(86)          | and PC
+       clrw    sp@(90)                 | and mark as type 0 frame
+       lea     sp@(84),sp              | clean the excess
+       jra     Ldorte                  | all done
+Lchksir:
+       tstb    _ssir                   | SIR pending?
+       jeq     Ldorte                  | no, all done
+       movl    d0,sp@-                 | need a scratch register
+       movw    sp@(4),d0               | get SR
+       andw    #PSL_IPL7,d0            | mask all but IPL
+       jne     Lnosir                  | came from interrupt, no can do
+       movl    sp@+,d0                 | restore scratch register
+Lgotsir:
+       movw    #SPL1,sr                | prevent others from servicing int
+       tstb    _ssir                   | too late?
+       jeq     Ldorte                  | yes, oh well...
+       clrw    sp@-                    | pad SR to longword
+       moveml  #0xFFFF,sp@-            | save all registers
+       movl    usp,a1                  | including
+       movl    a1,sp@(60)              |    the users SP
+       clrl    sp@-                    | VA == none
+       clrl    sp@-                    | code == none
+       movl    #T_SSIR,sp@-            | type == software interrupt
+       jbsr    _trap                   | go handle it
+       lea     sp@(12),sp              | pop value args
+       movl    sp@(60),a0              | restore
+       movl    a0,usp                  |   user SP
+       moveml  sp@+,#0x7FFF            | and all remaining registers
+       addql   #6,sp                   | pop SSP and align word
+       rte
+Lnosir:
+       movl    sp@+,d0                 | restore scratch register
+Ldorte:
+       rte                             | real return
+
+/*
+ * System page table
+ * Mbmap, Usrptmap, and Usriomap are enlarged by CLSIZE entries
+ * as they are managed by resource maps starting with index 1 or CLSIZE.
+ * Usrptmap is allocated last so that we can also use the pad space up
+ * to eSysmap. (no point in wasting it!)
+ */ 
+#define        vaddr(x)        x-_Sysmap/4*NBPG
+#define SYSMAP(mname,vname,size) \
+       .globl  _/**/mname,_/**/vname; \
+_/**/mname: \
+       .space  size*4; \
+       _/**/vname = vaddr(_/**/mname)
+#define        ADDMAP(npte)    .space  npte*4
+
+       .data
+       SYSMAP(Sysmap   ,Sysbase        ,SYSPTSIZE      )
+       SYSMAP(Forkmap  ,forkutl        ,UPAGES         )
+       SYSMAP(Xswapmap ,xswaputl       ,UPAGES         )
+       SYSMAP(Xswap2map,xswap2utl      ,UPAGES         )
+       SYSMAP(Swapmap  ,swaputl        ,UPAGES         )
+       SYSMAP(Pushmap  ,pushutl        ,UPAGES         )
+       SYSMAP(Vfmap    ,vfutl          ,UPAGES         )
+       SYSMAP(CMAP1    ,CADDR1         ,1              )
+       SYSMAP(CMAP2    ,CADDR2         ,1              )
+       SYSMAP(mmap     ,vmmap          ,1              )
+       SYSMAP(msgbufmap,msgbuf         ,MSGBUFPTECNT   )
+       SYSMAP(Umap     ,u              ,UPAGES         )
+       SYSMAP(Mbmap    ,mbutl          ,NMBCLUSTERS*MCLBYTES/NBPG+CLSIZE )
+       /*
+        * This is the map used by the kernel memory allocator.
+        * It is expanded as necessary by the special features
+        * that use it.
+        *
+        * XXX: NEED way to compute kmem size from maxusers,
+        * device complement
+        */
+       SYSMAP(kmempt   ,kmembase       ,NKMEMCLUSTERS*CLSIZE )
+#ifdef SYSVSHM
+                               ADDMAP( SHMMAXPGS       )
+#endif
+#ifdef GPROF
+                               ADDMAP( 768*1024/NBPG   )
+#endif
+       SYSMAP(ekmempt  ,kmemlimit      ,0              )
+       SYSMAP(IOmap    ,IObase         ,IOMAPSIZE      )   /* map DIO space */
+       SYSMAP(eIOmap   ,IOlimit        ,0              )
+#if defined(HP360) || defined(HP370)
+       SYSMAP(Grfmap   ,grfregs        ,1024           )   /* 340 @ SC132 */
+#endif
+       SYSMAP(Usriomap ,usrio          ,USRIOSIZE+CLSIZE ) /* for PHYSIO */
+       SYSMAP(Usrptmap ,usrpt          ,USRPTSIZE+CLSIZE )
+       . = . + NBPG - 1 & -NBPG        /* align to page boundry */
+eSysmap:
+
+/*
+ * System segment table.  1 page is sufficient to map the entire
+ * 4Gb address space. (funny how that works out...)
+ */
+       .globl  _Sysseg
+_Sysseg:
+       .space  NBPG
+eSysseg:
+
+       .globl  _Syssize, _Usrptsize
+_Syssize       = eSysmap-_Sysmap/4
+_Usrptsize     = eSysmap-_Usrptmap/4
+
+/*
+ * Initialization
+ *
+ * A5 contains physical load point from boot
+ * VBR contains zero from ROM.  Exceptions will continue to vector
+ * through ROM until MMU is turned on at which time they will vector
+ * through our table (vectors.s).
+ */
+       .comm   _lowram,4
+
+       .text
+       .globl  _edata
+       .globl  _etext,_end
+       .globl  start
+start:
+       movw    #PSL_HIGHIPL,sr         | no interrupts
+       lea     _lowram,a0
+       addl    a5,a0
+       movl    a5,a0@                  | store start of physical memory
+       movl    #CACHE_OFF,d0
+       movc    d0,cacr                 | clear and disable on-chip cache(s)
+
+/* determine our CPU/MMU combo - check for all regardless of kernel config */
+       movl    #0x200,d0               | data freeze bit
+       movc    d0,cacr                 |   only exists on 68030
+       movc    cacr,d0                 | read it back
+       tstl    d0                      | zero?
+       jeq     Lis68020                | yes, we have 68020
+       lea     _mmutype,a0             | no, we have 68030
+       addl    a5,a0
+       movl    #-1,a0@                 | set to reflect 68030 PMMU
+       lea     _machineid,a0
+       addl    a5,a0
+       movl    #3,a0@                  | type is at least a 360
+       movl    #0x80,IOBASE+MMUCMD     | set magic cookie
+       movl    IOBASE+MMUCMD,d0        | read it back
+       btst    #7,d0                   | cookie still on?
+       jeq     Lstart1                 | no, just a 360
+       movl    #0,IOBASE+MMUCMD        | clear magic cookie
+       movl    IOBASE+MMUCMD,d0        | read it back
+       btst    #7,d0                   | still on?
+       jeq     Lisa370                 | no, must be a 370
+       movl    #5,a0@                  | yes, must be a 340
+       jra     Lstart1
+Lisa370:
+       movl    #4,a0@                  | set to 370
+       lea     _ectype,a0
+       addl    a5,a0
+       movl    #-1,a0@                 | also has a physical address cache
+       jra     Lstart1
+Lis68020:
+       movl    #1,IOBASE+MMUCMD        | a 68020, write HP MMU location
+       movl    IOBASE+MMUCMD,d0        | read it back
+       btst    #0,d0                   | non-zero?
+       jne     Lishpmmu                | yes, we have HP MMU
+       lea     _mmutype,a0
+       addl    a5,a0
+       movl    #1,a0@                  | no, we have PMMU
+       lea     _machineid,a0
+       addl    a5,a0
+       movl    #1,a0@                  | and 330 CPU
+       jra     Lstart1
+Lishpmmu:
+       lea     _ectype,a0              | 320 or 350
+       addl    a5,a0
+       movl    #1,a0@                  | both have a virtual address cache
+       movl    #0x80,IOBASE+MMUCMD     | set magic cookie
+       movl    IOBASE+MMUCMD,d0        | read it back
+       btst    #7,d0                   | cookie still on?
+       jeq     Lstart1                 | no, just a 320
+       lea     _machineid,a0
+       addl    a5,a0
+       movl    #2,a0@                  | yes, a 350
+
+Lstart1:
+       movl    #0,IOBASE+MMUCMD        | clear out MMU again
+/* initialize source/destination control registers for movs */
+       moveq   #FC_USERD,d0            | user space
+       movc    d0,sfc                  |   as source
+       movc    d0,dfc                  |   and destination of transfers
+/* initialize proc. 0 (system) page table */
+       movl    #_Sysmap,a0             | SYSPT map addr
+       addl    a5,a0                   | relocate
+/* text pages are read-only */
+       clrl    d0                      | assume load at VA 0
+       movl    a5,d1                   | get load PA
+       andl    #PG_FRAME,d1            | convert to a page frame
+       orl     #PG_RO+PG_V,d1          | mark as valid and RO
+       movl    #_etext,a1              | go til end of text
+Lispt1:
+       movl    d1,a0@+                 | load PTE
+       addl    #NBPG,d1                | increment page frame number
+       addl    #NBPG,d0                | and address counter
+       cmpl    a1,d0                   | done yet?
+       jcs     Lispt1                  | no, keep going
+/* data and bss are read/write */
+       andl    #PG_FRAME,d1            | mask out old prot bits
+       orl     #PG_RW+PG_V,d1          | mark as valid and RW
+       movl    #_end,a1                | go til end of data/bss
+Lispt2:
+       movl    d1,a0@+                 | load PTE
+       addl    #NBPG,d1                | increment page frame number
+       addl    #NBPG,d0                | and address counter
+       cmpl    a1,d0                   | done yet?
+       jcs     Lispt2                  | no, keep going
+/* invalidate remainder of system page table */
+       movl    #eSysmap,a1             | end of map
+       addl    a5,a1                   | relocate
+Lispt3:
+       movl    #PG_NV,a0@+             | invalidate PTE
+       cmpl    a1,a0                   | done yet?
+       jcs     Lispt3                  | no, keep going
+/* go back and initialize IOmap */
+       movl    #_IOmap,a0              | IO map addr
+       addl    a5,a0                   | relocate
+       movl    #_eIOmap,a1             | end of map
+       addl    a5,a1                   | relocate
+       movl    #IOBASE,d1              | physical IO base
+       andl    #PG_FRAME,d1            | mask to frame number
+       orl     #PG_RW+PG_CI+PG_V,d1    | mark valid, RW and CI
+Lispt4:
+       movl    d1,a0@+                 | load PTE
+       addl    #NBPG,d1                | increment page frame number
+       cmpl    a1,a0                   | done yet?
+       jcs     Lispt4                  | no, keep going
+/* initialize proc. 0 (system) segment table */
+       movl    #_Sysseg,a0             | segment table
+       addl    a5,a0                   | relocate
+       movl    #eSysmap-_Sysmap/NBPG*4,a1 | bytes of PTEs for Sysmap
+       addl    a0,a1                   | make an end count
+       movl    #_Sysmap,d1             | system PT addr
+       addl    a5,d1                   | relocate
+       andl    #SG_FRAME,d1            | mask to frame number
+       orl     #SG_RW+SG_V,d1          | mark as RW and valid
+Lispt5:
+       movl    d1,a0@+                 | load STE
+       addl    #NBPG,d1                | increment page frame number
+       cmpl    a1,a0                   | done yet?
+       jcs     Lispt5                  | no, keep going
+/* invalidate the unused part */
+       movl    #eSysseg,a1             | end of segment table
+       addl    a5,a1                   | relocate
+Lispt6:
+       movl    #SG_NV,a0@+             | invalidate STE
+       cmpl    a1,a0                   | done yet?
+       jcs     Lispt6                  | no, keep going
+
+/*
+ * Setup page table for process 0.
+ *
+ * We set up page table access for the kernel via Usrptmap (usrpt)
+ * and access to the u-area itself via Umap (u).  First page beyond
+ * kernel BSS (d0) is used for proc0 page table.  Next UPAGES pages
+ * following are for u-area.
+ */
+       addl    a5,d0                   | relocate PT address
+       movl    d0,d1
+       andl    #PG_FRAME,d1            | mask to page frame number
+       orl     #PG_RW+PG_V,d1          | RW and valid
+       movl    #_Usrptmap,a1           | get PT map address
+       addl    a5,a1                   | relocate
+       movl    d1,a1@                  | validate PTE for proc0 PT
+       movl    d0,a0                   | base of proc0 PT
+       addl    #NBPG,d0                | plus one page yields
+       movl    d0,a2                   | base of u-area
+/* invalidate entire page table */
+Liudot1:
+       movl    #PG_NV,a0@+             | invalidate PTE
+       cmpl    a2,a0                   | done yet?
+       jcs     Liudot1                 | no, keep going
+/* now go back and validate u-area PTEs */
+       subl    #HIGHPAGES*4,a0         | base of PTEs for u-area (p_addr)
+       movl    a0,a1
+       addl    #UPAGES*4,a1            | end of PTEs for u-area
+       movl    d0,d1                   | get base of u-area
+       andl    #PG_FRAME,d1            | mask to page frame number
+       orl     #PG_RW+PG_V,d1          | add valid and writable
+       movl    #_Umap,a3               | address of u
+       addl    a5,a3                   | relocate
+Liudot2:
+       movl    d1,a0@+                 | validate p_addr PTE
+       movl    d1,a3@+                 | validate u PTE
+       addl    #NBPG,d1                | to next page
+       cmpl    a1,a0                   | done yet?
+       jcs     Liudot2                 | no, keep going
+/* clear process 0 u-area */
+       addl    #NBPG*UPAGES,d0         | end of u-area
+Lclru1:
+       clrl    a2@+                    | clear
+       cmpl    d0,a2                   | done yet?
+       jcs     Lclru1                  | no, keep going
+       movl    a2,a4                   | save addr of first avail page
+
+/*
+ * Prepare to enable MMU.
+ * Since the kernel is not mapped logical == physical we must insure
+ * that when the MMU is turned on, all prefetched addresses (including
+ * the PC) are valid.  In order guarentee that, we map the last page of
+ * memory logical == physical and load up that page with enough code to
+ * defeat the prefetch, then we execute the jump back to here.
+ *
+ * Is this all really necessary, or am I paranoid??
+ */
+       movl    #_Sysseg,d1             | system segment table addr
+       addl    a5,d1                   | relocate
+       lea     _mmutype,a0
+       addl    a5,a0
+       tstl    a0@                     | HP MMU?
+       jeq     Lhpmmu2                 | yes, skip
+       lea     _protorp,a0
+       addl    a5,a0
+       movl    #0x80000202,a0@         | nolimit + share global + 4 byte PTEs
+       movl    d1,a0@(4)               | + segtable address
+       .long   0xf0104800              | pmove a0@,srp
+       movl    #0x80000002,a0@         | reinit upper half for CRP loads
+       jra     Lstploaddone            | done
+Lhpmmu2:
+       moveq   #PGSHIFT,d2
+       lsrl    d2,d1                   | convert to page frame
+       movl    d1,IOBASE+MMUSSTP       | load in sysseg table register
+Lstploaddone:
+       movl    #eSysseg-4,a1           | last entry in sysseg table
+       addl    a5,a1                   | relocate
+       movl    d0,d1                   | use page after proc0 u for tmp PT
+       andl    #SG_FRAME,d1            | mask to page frame
+       orl     #SG_RW+SG_V,d1          | mark valid and writable
+       movl    d1,a1@                  | load in segment table
+       movl    d0,a1                   | page table address
+       addl    #NBPG-4,a1              | move to last entry
+       movl    #MAXADDR,d1             | address of last page of memory
+       movl    d1,a2
+       andl    #PG_FRAME,d1            | mask to page frame
+       orl     #PG_RW+PG_V,d1          | mark valid and writable
+       movl    d1,a1@                  | store PTE in table
+       movl    #Lhighcode,a1           | addr of high code
+       addl    a5,a1                   | relocate
+       movl    #Lehighcode,a3          | end addr
+       addl    a5,a3                   | relocate
+Lcodecopy:
+       movw    a1@+,a2@+               | copy a word
+       cmpl    a3,a1                   | done yet?
+       jcs     Lcodecopy               | no, keep going
+       jmp     MAXADDR                 | go for it!
+
+Lhighcode:
+       lea     _mmutype,a0
+       addl    a5,a0
+       tstl    a0@                             | HP MMU?
+       jeq     Lhpmmu3                         | yes, skip
+       movl    #MMU_IEN+MMU_FPE,IOBASE+MMUCMD  | enable 68881 and i-cache
+       movl    #0x82c0aa00,a2@                 | value to load TC with
+       .long   0xf0124000                      | pmove a2@,tc
+       jmp     Lenab1
+Lhpmmu3:
+       movl    #0,IOBASE+MMUCMD                | clear external cache
+       movl    #MMU_ENAB,IOBASE+MMUCMD         | turn on MMU
+       jmp     Lenab1                          | jmp to mapped code
+Lehighcode:
+
+/*
+ * Should be running mapped from this point on
+ */
+Lenab1:
+/* init mem sizes */
+       movl    #MAXADDR,d1             | last page
+       moveq   #PGSHIFT,d2
+       lsrl    d2,d1                   | convert to page (click) number
+       movl    d1,_maxmem              | save as maxmem
+       movl    _lowram,d0              | lowram value from ROM via boot
+       lsrl    d2,d0                   | convert to page number
+       subl    d0,d1                   | compute amount of RAM present
+       movl    d1,_freemem             | save as freemem
+       movl    d1,_physmem             | and physmem
+/* initialize (slightly) the pcb */
+       movl    #_u,a1                  | proc0 u-area
+       movl    a1,sp
+       addl    #UPAGES*NBPG-4,sp       | set kernel stack to end of u-area
+       movl    #USRSTACK-4,a2
+       movl    a2,usp                  | init user SP
+       movl    #_usrpt,a1@(PCB_P0BR)   | p0br: SVA of text/data user PT
+       clrl    a1@(PCB_P0LR)           | p0lr: 0 (does not really exist)
+       movl    #_usrpt+NBPG,d0         | addr of end of PT
+       subl    #P1PAGES*4,d0           | backup size of P1 region
+       movl    d0,a1@(PCB_P1BR)        | p1br: P1PAGES from end of PT
+       movl    #P1PAGES-HIGHPAGES,a1@(PCB_P1LR)        | p1lr: vax style
+       movl    #CLSIZE,a1@(PCB_SZPT)   | page table size
+       clrw    a1@(PCB_FLAGS)          | clear flags
+#ifdef FPCOPROC
+       clrl    a1@(PCB_FPCTX)          | ensure null FP context
+       movl    a1,sp@-
+       jbsr    _m68881_restore         | restore it (does not kill a1)
+       addql   #4,sp
+#endif
+       addl    #PCB_SIGC,a1            | address of proc0 sig trampoline code
+       movl    #Lsigcode,a2            | address of sig trampoline proto
+Lsigc:
+       movw    a2@+,a1@+               | copy
+       cmpl    #Lesigcode,a2           | done yet?
+       jcs     Lsigc                   | no, keep going
+/* flush TLB and turn on caches */
+       movl    #PG_NV,eSysseg-4        | invalidate last page
+       jbsr    _TBIA                   | invalidate TLB
+       movl    #CACHE_ON,d0
+       movc    d0,cacr                 | clear cache(s)
+       tstl    _ectype
+       jeq     Lnocache0
+       orl     #MMU_CEN,_IObase+MMUCMD | turn on external cache
+Lnocache0:
+/* final setup for C code */
+       movw    #PSL_LOWIPL,sr          | lower SPL
+       movl    d7,_boothowto           | save reboot flags
+       movl    d6,_bootdev             |   and boot device
+       movl    a4,d1                   | addr of first available RAM
+       moveq   #PGSHIFT,d2
+       lsrl    d2,d1                   | convert to click
+       movl    d1,sp@-                 | param to main
+       jbsr    _main                   | main(firstaddr)
+       addql   #4,sp
+/* proc[1] == init now running here;
+ * create a null exception frame and return to user mode in icode
+ */
+       clrw    sp@-                    | vector offset/frame type
+       clrl    sp@-                    | return to icode location 0
+       movw    #PSL_USER,sp@-          | in user mode
+       rte
+
+/*
+ * Signal "trampoline" code (18 bytes).  Invoked from RTE setup by sendsig().
+ * 
+ * Stack looks like:
+ *
+ *     sp+0 -> signal number
+ *     sp+4    signal specific code
+ *     sp+8    pointer to signal context frame (scp)
+ *     sp+12   address of handler
+ *     sp+16   saved hardware state
+ *                     .
+ *                     .
+ *     scp+0-> beginning of signal context frame
+ */
+Lsigcode:
+       movl    sp@(12),a0              | signal handler addr   (4 bytes)
+       jsr     a0@                     | call signal handler   (2 bytes)
+       addql   #4,sp                   | pop signo             (2 bytes)
+       trap    #1                      | special syscall entry (2 bytes)
+       movl    d0,sp@(4)               | save errno            (4 bytes)
+       moveq   #1,d0                   | syscall == exit       (2 bytes)
+       trap    #0                      | exit(errno)           (2 bytes)
+Lesigcode:
+
+/*
+ * Icode is copied out to process 1 to exec init.
+ * If the exec fails, process 1 exits.
+ */
+       argv1 = argv-_icode
+       init1 = init-_icode
+       .globl  _icode,_initflags,_szicode
+_icode:
+       movl    #argv1,sp@-
+       movl    #init1,sp@-
+       clrl    sp@-
+       moveq   #SYS_execv,d0
+       trap    #0
+       moveq   #SYS_exit,d0
+       trap    #0
+
+init:
+#ifdef COMPAT_UTAH
+       .asciz  "/etc/init"
+#else
+       .asciz  "/sbin/init"
+#endif
+       .even
+_initflags:
+       .long   0
+argv:
+#ifdef COMPAT_UTAH
+       .long   init+5-_icode
+#else
+       .long   init+6-_icode
+#endif
+       .long   _initflags-_icode
+       .long   0
+_szicode:
+       .long   _szicode-_icode
+
+/*
+ * Primitives
+ */ 
+
+#ifdef GPROF
+#ifdef __GNUC__
+#define        ENTRY(name) \
+       .globl _/**/name; _/**/name: link a6,#0; jbsr mcount; unlk a6
+#define ALTENTRY(name, rname) \
+       ENTRY(name); jra rname+12
+#else
+#define        ENTRY(name) \
+       .globl _/**/name; _/**/name: jbsr mcount
+#define ALTENTRY(name, rname) \
+       ENTRY(name); jra rname+6
+#endif
+#else
+#define        ENTRY(name) \
+       .globl _/**/name; _/**/name:
+#define ALTENTRY(name, rname) \
+       .globl _/**/name; _/**/name:
+#endif
+
+/*
+ * update profiling information for the user
+ * addupc(pc, &u.u_prof, ticks)
+ */
+ENTRY(addupc)
+       movl    a2,sp@-                 | scratch register
+       movl    sp@(12),a2              | get &u.u_prof
+       movl    sp@(8),d0               | get user pc
+       subl    a2@(8),d0               | pc -= pr->pr_off
+       jlt     Lauexit                 | less than 0, skip it
+       movl    a2@(12),d1              | get pr->pr_scale
+       lsrl    #1,d0                   | pc /= 2
+       lsrl    #1,d1                   | scale /= 2
+       mulul   d1,d0                   | pc /= scale
+       moveq   #14,d1
+       lsrl    d1,d0                   | pc >>= 14
+       bclr    #0,d0                   | pc &= ~1
+       cmpl    a2@(4),d0               | too big for buffer?
+       jge     Lauexit                 | yes, screw it
+       addl    a2@,d0                  | no, add base
+       movl    d0,sp@-                 | push address
+       jbsr    _fusword                | grab old value
+       movl    sp@+,a0                 | grab address back
+       cmpl    #-1,d0                  | access ok
+       jeq     Lauerror                | no, skip out
+       addw    sp@(18),d0              | add tick to current value
+       movl    d0,sp@-                 | push value
+       movl    a0,sp@-                 | push address
+       jbsr    _susword                | write back new value
+       addql   #8,sp                   | pop params
+       tstl    d0                      | fault?
+       jeq     Lauexit                 | no, all done
+Lauerror:
+       clrl    a2@(12)                 | clear scale (turn off prof)
+Lauexit:
+       movl    sp@+,a2                 | restore scratch reg
+       rts
+
+/*
+ * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
+ *
+ * Copy a null terminated string from the user address space into
+ * the kernel address space.
+ * NOTE: maxlength must be < 64K
+ */
+ENTRY(copyinstr)
+       movl    sp@(4),a0               | a0 = fromaddr
+       movl    sp@(8),a1               | a1 = toaddr
+       moveq   #0,d0
+       movw    sp@(14),d0              | d0 = maxlength
+       jlt     Lcisflt1                | negative count, error
+       jeq     Lcisdone                | zero count, all done
+       movl    #Lcisflt1,_u+PCB_ONFAULT | set up to catch faults
+       subql   #1,d0                   | set up for dbeq
+Lcisloop:
+       movsb   a0@+,d1                 | grab a byte
+       movb    d1,a1@+                 | copy it
+       dbeq    d0,Lcisloop             | if !null and more, continue
+       jne     Lcisflt2                | ran out of room, error
+       moveq   #0,d0                   | got a null, all done
+Lcisdone:
+       tstl    sp@(16)                 | return length desired?
+       jeq     Lcisret                 | no, just return
+       subl    sp@(4),a0               | determine how much was copied
+       movl    sp@(16),a1              | return location
+       movl    a0,a1@                  | stash it
+Lcisret:
+       clrl    _u+PCB_ONFAULT          | clear fault addr
+       rts
+Lcisflt1:
+       moveq   #EFAULT,d0              | copy fault
+       jra     Lcisdone
+Lcisflt2:
+       moveq   #ENOENT,d0              | ran out of space
+       jra     Lcisdone        
+
+/*
+ * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
+ *
+ * Copy a null terminated string from the kernel
+ * address space to the user address space.
+ * NOTE: maxlength must be < 64K
+ */
+ENTRY(copyoutstr)
+       movl    sp@(4),a0               | a0 = fromaddr
+       movl    sp@(8),a1               | a1 = toaddr
+       moveq   #0,d0
+       movw    sp@(14),d0              | d0 = maxlength
+       jlt     Lcosflt1                | negative count, error
+       jeq     Lcosdone                | zero count, all done
+       movl    #Lcosflt1,_u+PCB_ONFAULT| set up to catch faults
+       subql   #1,d0                   | set up for dbeq
+Lcosloop:
+       movb    a0@+,d1                 | grab a byte
+       movsb   d1,a1@+                 | copy it
+       dbeq    d0,Lcosloop             | if !null and more, continue
+       jne     Lcosflt2                | ran out of room, error
+       moveq   #0,d0                   | got a null, all done
+Lcosdone:
+       tstl    sp@(16)                 | return length desired?
+       jeq     Lcosret                 | no, just return
+       subl    sp@(4),a0               | determine how much was copied
+       movl    sp@(16),a1              | return location
+       movl    a0,a1@                  | stash it
+Lcosret:
+       clrl    _u+PCB_ONFAULT          | clear fault addr
+       rts
+Lcosflt1:
+       moveq   #EFAULT,d0              | copy fault
+       jra     Lcosdone
+Lcosflt2:
+       moveq   #ENOENT,d0              | ran out of space
+       jra     Lcosdone        
+
+/*
+ * copystr(fromaddr, toaddr, maxlength, &lencopied)
+ *
+ * Copy a null terminated string from one point to another in
+ * the kernel address space.
+ * NOTE: maxlength must be < 64K
+ */
+ENTRY(copystr)
+       movl    sp@(4),a0               | a0 = fromaddr
+       movl    sp@(8),a1               | a1 = toaddr
+       moveq   #0,d0
+       movw    sp@(14),d0              | d0 = maxlength
+       jlt     Lcsflt1                 | negative count, error
+       jeq     Lcsdone                 | zero count, all done
+       movl    #Lcsflt1,_u+PCB_ONFAULT | set up to catch faults
+       subql   #1,d0                   | set up for dbeq
+Lcsloop:
+       movb    a0@+,a1@+               | copy a byte
+       dbeq    d0,Lcsloop              | if !null and more, continue
+       jne     Lcsflt2                 | ran out of room, error
+       moveq   #0,d0                   | got a null, all done
+Lcsdone:
+       tstl    sp@(16)                 | return length desired?
+       jeq     Lcsret                  | no, just return
+       subl    sp@(4),a0               | determine how much was copied
+       movl    sp@(16),a1              | return location
+       movl    a0,a1@                  | stash it
+Lcsret:
+       clrl    _u+PCB_ONFAULT          | clear fault addr
+       rts
+Lcsflt1:
+       moveq   #EFAULT,d0              | copy fault
+       jra     Lcsdone
+Lcsflt2:
+       moveq   #ENOENT,d0              | ran out of space
+       jra     Lcsdone 
+
+/* 
+ * Copyin(from, to, len)
+ *
+ * Copy specified amount of data from user space into the kernel.
+ * NOTE: len must be < 64K
+ */
+ENTRY(copyin)
+       movl    d2,sp@-                 | scratch register
+       movl    #Lciflt,_u+PCB_ONFAULT  | catch faults
+       movl    sp@(16),d2              | check count
+       jlt     Lciflt                  | negative, error
+       jeq     Lcidone                 | zero, done
+       movl    sp@(8),a0               | src address
+       movl    sp@(12),a1              | dest address
+       movl    a0,d0
+       btst    #0,d0                   | src address odd?
+       jeq     Lcieven                 | no, go check dest
+       movsb   a0@+,d1                 | yes, get a byte
+       movb    d1,a1@+                 | put a byte
+       subql   #1,d2                   | adjust count
+       jeq     Lcidone                 | exit if done
+Lcieven:
+       movl    a1,d0
+       btst    #0,d0                   | dest address odd?
+       jne     Lcibyte                 | yes, must copy by bytes
+       movl    d2,d0                   | no, get count
+       lsrl    #2,d0                   | convert to longwords
+       jeq     Lcibyte                 | no longwords, copy bytes
+       subql   #1,d0                   | set up for dbf
+Lcilloop:
+       movsl   a0@+,d1                 | get a long
+       movl    d1,a1@+                 | put a long
+       dbf     d0,Lcilloop             | til done
+       andl    #3,d2                   | what remains
+       jeq     Lcidone                 | all done
+Lcibyte:
+       subql   #1,d2                   | set up for dbf
+Lcibloop:
+       movsb   a0@+,d1                 | get a byte
+       movb    d1,a1@+                 | put a byte
+       dbf     d2,Lcibloop             | til done
+Lcidone:
+       moveq   #0,d0                   | success
+Lciexit:
+       clrl    _u+PCB_ONFAULT          | reset fault catcher
+       movl    sp@+,d2                 | restore scratch reg
+       rts
+Lciflt:
+       moveq   #EFAULT,d0              | got a fault
+       jra     Lciexit
+
+/* 
+ * Copyout(from, to, len)
+ *
+ * Copy specified amount of data from kernel to the user space
+ * NOTE: len must be < 64K
+ */
+ENTRY(copyout)
+       movl    d2,sp@-                 | scratch register
+       movl    #Lcoflt,_u+PCB_ONFAULT  | catch faults
+       movl    sp@(16),d2              | check count
+       jlt     Lcoflt                  | negative, error
+       jeq     Lcodone                 | zero, done
+       movl    sp@(8),a0               | src address
+       movl    sp@(12),a1              | dest address
+       movl    a0,d0
+       btst    #0,d0                   | src address odd?
+       jeq     Lcoeven                 | no, go check dest
+       movb    a0@+,d1                 | yes, get a byte
+       movsb   d1,a1@+                 | put a byte
+       subql   #1,d2                   | adjust count
+       jeq     Lcodone                 | exit if done
+Lcoeven:
+       movl    a1,d0
+       btst    #0,d0                   | dest address odd?
+       jne     Lcobyte                 | yes, must copy by bytes
+       movl    d2,d0                   | no, get count
+       lsrl    #2,d0                   | convert to longwords
+       jeq     Lcobyte                 | no longwords, copy bytes
+       subql   #1,d0                   | set up for dbf
+Lcolloop:
+       movl    a0@+,d1                 | get a long
+       movsl   d1,a1@+                 | put a long
+       dbf     d0,Lcolloop             | til done
+       andl    #3,d2                   | what remains
+       jeq     Lcodone                 | all done
+Lcobyte:
+       subql   #1,d2                   | set up for dbf
+Lcobloop:
+       movb    a0@+,d1                 | get a byte
+       movsb   d1,a1@+                 | put a byte
+       dbf     d2,Lcobloop             | til done
+Lcodone:
+       moveq   #0,d0                   | success
+Lcoexit:
+       clrl    _u+PCB_ONFAULT          | reset fault catcher
+       movl    sp@+,d2                 | restore scratch reg
+       rts
+Lcoflt:
+       moveq   #EFAULT,d0              | got a fault
+       jra     Lcoexit
+
+/*
+ * non-local gotos
+ */
+ALTENTRY(savectx, _setjmp)
+ENTRY(setjmp)
+       movl    sp@(4),a0       | savearea pointer
+       moveml  #0xFCFC,a0@     | save d2-d7/a2-a7
+       movl    sp@,a0@(48)     | and return address
+       moveq   #0,d0           | return 0
+       rts
+
+ENTRY(qsetjmp)
+       movl    sp@(4),a0       | savearea pointer
+       lea     a0@(40),a0      | skip regs we do not save
+       movl    a6,a0@+         | save FP
+       movl    sp,a0@+         | save SP
+       movl    sp@,a0@         | and return address
+       moveq   #0,d0           | return 0
+       rts
+
+ENTRY(longjmp)
+       movl    sp@(4),a0
+       moveml  a0@+,#0xFCFC
+       movl    a0@,sp@
+       moveq   #1,d0
+       rts
+
+/*
+ * The following primitives manipulate the run queues.
+ * _whichqs tells which of the 32 queues _qs
+ * have processes in them.  Setrq puts processes into queues, Remrq
+ * removes them from queues.  The running process is on no queue,
+ * other processes are on a queue related to p->p_pri, divided by 4
+ * actually to shrink the 0-127 range of priorities into the 32 available
+ * queues.
+ */
+
+       .globl  _whichqs,_qs,_cnt,_panic
+       .comm   _noproc,4
+       .comm   _runrun,4
+
+/*
+ * Setrq(p)
+ *
+ * Call should be made at spl6(), and p->p_stat should be SRUN
+ */
+ENTRY(setrq)
+       movl    sp@(4),a0
+       tstl    a0@(P_RLINK)
+       jeq     Lset1
+       movl    #Lset2,sp@-
+       jbsr    _panic
+Lset1:
+       clrl    d0
+       movb    a0@(P_PRI),d0
+       lsrb    #2,d0
+       movl    _whichqs,d1
+       bset    d0,d1
+       movl    d1,_whichqs
+       lslb    #3,d0
+       addl    #_qs,d0
+       movl    d0,a0@(P_LINK)
+       movl    d0,a1
+       movl    a1@(P_RLINK),a0@(P_RLINK)
+       movl    a0,a1@(P_RLINK)
+       movl    a0@(P_RLINK),a1
+       movl    a0,a1@(P_LINK)
+       rts
+
+Lset2:
+       .asciz  "setrq"
+       .even
+
+/*
+ * Remrq(p)
+ *
+ * Call should be made at spl6().
+ */
+ENTRY(remrq)
+       movl    sp@(4),a0
+       clrl    d0
+       movb    a0@(P_PRI),d0
+       lsrb    #2,d0
+       movl    _whichqs,d1
+       bclr    d0,d1
+       jne     Lrem1
+       movl    #Lrem3,sp@-
+       jbsr    _panic
+Lrem1:
+       movl    d1,_whichqs
+       movl    a0@(P_LINK),a1
+       movl    a0@(P_RLINK),a1@(P_RLINK)
+       movl    a0@(P_RLINK),a1
+       movl    a0@(P_LINK),a1@(P_LINK)
+       movl    #_qs,a1
+       movl    d0,d1
+       lslb    #3,d1
+       addl    d1,a1
+       cmpl    a1@(P_LINK),a1
+       jeq     Lrem2
+       movl    _whichqs,d1
+       bset    d0,d1
+       movl    d1,_whichqs
+Lrem2:
+       clrl    a0@(P_RLINK)
+       rts
+
+Lrem3:
+       .asciz  "remrq"
+Lsw0:
+       .asciz  "swtch"
+       .even
+
+/*
+ * When no processes are on the runq, Swtch branches to idle
+ * to wait for something to come ready.
+ */
+       .globl  Idle
+Idle:
+idle:
+       movw    #PSL_LOWIPL,sr
+       tstl    _whichqs
+       jne     Lsw1
+       stop    #PSL_LOWIPL
+       jra     idle
+
+Lbadsw:
+       movl    #Lsw0,sp@-
+       jbsr    _panic
+       /*NOTREACHED*/
+
+/*
+ * Swtch()
+ */
+ENTRY(swtch)
+       movw    sr,_u+PCB_PS
+       movl    #1,_noproc
+       addql   #1,_cnt+V_SWTCH
+Lsw1:
+       clrl    d0
+       movl    _whichqs,d1
+Lswchk:
+       btst    d0,d1
+       jne     Lswfnd
+       addqb   #1,d0
+       cmpb    #32,d0
+       jne     Lswchk
+       jra     idle
+Lswfnd:
+       movw    #PSL_HIGHIPL,sr
+       movl    _whichqs,d1
+       bclr    d0,d1
+       jeq     Lsw1
+       movl    d1,_whichqs
+       movl    d0,d1
+       lslb    #3,d1
+       addl    #_qs,d1
+       movl    d1,a1
+       cmpl    a1@(P_LINK),a1
+       jeq     Lbadsw
+       movl    a1@(P_LINK),a0
+       movl    a0@(P_LINK),a1@(P_LINK)
+       movl    a0@(P_LINK),a1
+       movl    a0@(P_RLINK),a1@(P_RLINK)
+       cmpl    a0@(P_LINK),d1
+       jeq     Lsw2
+       movl    _whichqs,d1
+       bset    d0,d1
+       movl    d1,_whichqs
+Lsw2:
+       clrl    _noproc
+       clrl    _runrun
+       tstl    a0@(P_WCHAN)
+       jne     Lbadsw
+       cmpb    #SRUN,a0@(P_STAT)
+       jne     Lbadsw
+       clrl    a0@(P_RLINK)
+       movl    a0@(P_ADDR),d0
+       jra     Lres0
+
+/*
+ * Resume(p_addr)
+ *
+ * NOTE: on the PMMU we attempt to avoid flushing the entire TAC.
+ * The effort involved in selective flushing may not be worth it,
+ * maybe we should just flush the whole thing?
+ */
+ENTRY(resume)
+       movw    sr,_u+PCB_PS
+       movl    sp@(4),d0
+Lres0:
+       lea     _u,a1                   | &u
+       movl    usp,a0                  | grab USP
+       movl    a0,a1@(PCB_USP)         | and save it
+       moveml  #0xFCFC,a1@(PCB_REGS)   | save non-scratch registers
+#ifdef FPCOPROC
+       lea     a1@(PCB_FPCTX),a0       | pointer to FP save area
+       .word   0xf310                  | fsave a0@
+       tstb    a0@                     | null state frame?
+       jeq     Lresnofpsave            | yes, all done
+       .word   0xf228,0xf0ff,0x00d8    | fmovem fp0-fp7,a0@(216)
+       .word   0xf228,0xbc00,0x0138    | fmovem fpcr/fpsr/fpiar,a0@(312)
+Lresnofpsave:
+#endif
+#ifdef PROFTIMER
+       movw    #SPL6,sr                | protect against clock interrupts
+       bclr    #0,_profon              | clear user profiling bit, was set?
+       jeq     Lskipoff                | no, clock off or doing kernel only
+#ifdef GPROF
+       tstb    _profon                 | kernel profiling also enabled?
+       jlt     Lskipoff                | yes, nothing more to do
+#endif
+       movb    #0,_IObase+CLKCR2       | no, just user, select CR3
+       movb    #0,_IObase+CLKCR3       | and turn it off
+Lskipoff:
+#endif
+       movl    _CMAP2,a1@(PCB_CMAP2)   | save temporary map PTE
+       movw    #PSL_HIGHIPL,sr         | go crit while changing PTEs
+       lea     tmpstk,sp               | now goto a tmp stack for NMI
+       movl    d0,a0                   | address of new context
+       lea     _Umap,a1                | address of PTEs for u
+       moveq   #UPAGES-1,d0            | sizeof u
+Lres1:
+       movl    a0@+,d1                 | get PTE
+       andl    #~PG_PROT,d1            | mask out old protection
+       orl     #PG_RW+PG_V,d1          | ensure valid and writable
+       movl    d1,a1@+                 | load it up
+       dbf     d0,Lres1                | til done
+       lea     _u,a1                   | reload &u
+       movl    #CACHE_CLR,d0
+       movc    d0,cacr                 | invalidate cache(s)
+#if defined(HP330) || defined(HP360) || defined(HP370)
+       tstl    _mmutype                | HP MMU?
+       jeq     Lhpmmu4                 | yes, skip
+       jmi     Lnot68851a              | must flush all on 68030 MMU
+#ifdef DEBUG
+       tstl    fullflush               | 68851, conservative?
+       jne     Lnot68851a              | yes, go flush all
+#endif
+       .long   0xf0003494              | no, pflushs #4,#4 (flush super side)
+       jra     Lres2
+Lnot68851a:
+       .long   0xf0002400              | pflusha
+Lres2:
+       movl    a1@(PCB_USTP),d0        | get USTP
+       moveq   #PGSHIFT,d1
+       lsll    d1,d0                   | convert to addr
+       lea     _protorp,a0             | CRP prototype
+       movl    d0,a0@(4)               | stash USTP
+       .long   0xf0104C00              | pmove a0@,crp
+       jra     Lcxswdone               | thats it
+Lhpmmu4:       
+#endif
+#if defined(HP320) || defined(HP350)
+       movl    _IObase+MMUTBINVAL,d1   | invalidate TLB
+       tstl    _ectype                 | got external VAC?
+       jle     Lnocache1               | no, skip
+       movl    #_IObase+MMUCMD,a0      | addr of MMU command register
+       andl    #~MMU_CEN,a0@           | toggle cache enable
+       orl     #MMU_CEN,a0@            | to clear data cache
+Lnocache1:
+       movl    a1@(PCB_USTP),_IObase+MMUUSTP   | context switch
+#endif
+Lcxswdone:
+       movl    a1@(U_PROCP),a0         | u.u_procp
+       bclr    #SPTECHGB-24,a0@(P_FLAG)| clear SPTECHG bit
+#if defined(HP330)
+       jeq     Lnot68851b              | if set need to flush user TLB
+       tstl    _mmutype                | 68851 PMMU?
+       jle     Lnot68851b              | no, skip
+       .long   0xf0003490              | pflushs #0,#4
+Lnot68851b:
+#endif
+       movl    a1@(PCB_CMAP2),_CMAP2   | reload tmp map
+       moveml  a1@(PCB_REGS),#0xFCFC   | and registers
+       movl    a1@(PCB_USP),a0
+       movl    a0,usp                  | and USP
+#ifdef PROFTIMER
+       tstl    a1@(U_PROFSCALE)        | process being profiled?
+       jeq     Lskipon                 | no, do nothing
+       orb     #1,_profon              | turn on user profiling bit
+#ifdef GPROF
+       jlt     Lskipon                 | already profiling kernel, all done
+#endif
+       lea     _IObase+CLKMSB3,a0      | address timer 3 counter
+       movl    _profint,d1             | profiling interval
+       subql   #1,d1                   |   adjusted
+       movepw  d1,a0@(0)               | set interval
+       movb    #0,_IObase+CLKCR2       | select CR3
+       movb    #64,_IObase+CLKCR3      | turn it on
+Lskipon:
+#endif
+#ifdef FPCOPROC
+       lea     a1@(PCB_FPCTX),a0       | pointer to FP save area
+       tstb    a0@                     | null state frame?
+       jeq     Lresfprest              | yes, easy
+       .word   0xf228,0x9c00,0x0138    | fmovem a0@(312),fpcr/fpsr/fpiar
+       .word   0xf228,0xd0ff,0x00d8    | fmovem a0@(216),fp0-fp7
+Lresfprest:
+       .word   0xf350                  | frestore a0@
+#endif
+       tstl    a1@(PCB_SSWAP)          | do an alternate return?
+       jne     Lres3                   | yes, go reload regs
+       movw    a1@(PCB_PS),sr          | no, restore PS
+       rts
+Lres3:
+       movl    a1@(PCB_SSWAP),a0       | addr of saved context
+       clrl    a1@(PCB_SSWAP)          | clear flag
+       moveml  a0@+,#0x7CFC            | restore registers
+       movl    a0@+,a1                 | and SP
+       cmpl    sp,a1                   | paranoia...
+       jge     Lres4                   | ...must be popping, yes?
+       lea     tmpstk,sp               | no! set up a legit stack
+       movl    #Lres5,sp@-             | push a panic message
+       jbsr    _panic                  | and panic
+       /* NOTREACHED */
+Lres4:
+       movl    a1,sp                   | restore SP
+       movl    a0@,sp@                 | and PC
+       moveq   #1,d0                   | arrange for non-zero return
+       movw    #PSL_LOWIPL,sr          | lower SPL
+       rts
+
+Lres5:
+       .asciz  "ldctx"
+       .even
+
+/*
+ * {fu,su},{byte,sword,word}
+ */
+ALTENTRY(fuiword, _fuword)
+ENTRY(fuword)
+       movl    sp@(4),d0               | address to read
+       btst    #0,d0                   | is it odd?
+       jne     Lfserr                  | yes, a fault
+       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
+       movl    d0,a0
+       movsl   a0@,d0                  | do read from user space
+       jra     Lfsdone
+
+ENTRY(fusword)
+       movl    sp@(4),d0
+       btst    #0,d0                   | is address odd?
+       jne     Lfserr                  | yes, a fault
+       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
+       movl    d0,a0                   | address to read
+       moveq   #0,d0
+       movsw   a0@,d0                  | do read from user space
+       jra     Lfsdone
+
+ALTENTRY(fuibyte, _fubyte)
+ENTRY(fubyte)
+       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
+       movl    sp@(4),a0               | address to read
+       moveq   #0,d0
+       movsb   a0@,d0                  | do read from user space
+       jra     Lfsdone
+
+Lfserr:
+       moveq   #-1,d0                  | error indicator
+Lfsdone:
+       clrl    _u+PCB_ONFAULT          | clear fault address
+       rts
+
+ALTENTRY(suiword, _suword)
+ENTRY(suword)
+       movl    sp@(4),d0               | address to write
+       btst    #0,d0                   | is it odd?
+       jne     Lfserr                  | yes, a fault
+       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
+       movl    d0,a0                   | address to write
+       movl    sp@(8),d0               | value to put there
+       movsl   d0,a0@                  | do write to user space
+       moveq   #0,d0                   | indicate no fault
+       jra     Lfsdone
+
+ENTRY(susword)
+       movl    sp@(4),d0               | address to write
+       btst    #0,d0                   | is it odd?
+       jne     Lfserr                  | yes, a fault
+       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
+       movl    d0,a0                   | address to write
+       movw    sp@(10),d0              | value to put there
+       movsw   d0,a0@                  | do write to user space
+       moveq   #0,d0                   | indicate no fault
+       jra     Lfsdone
+
+ALTENTRY(suibyte, _subyte)
+ENTRY(subyte)
+       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
+       movl    sp@(4),a0               | address to write
+       movb    sp@(11),d0              | value to put there
+       movsb   d0,a0@                  | do write to user space
+       moveq   #0,d0                   | indicate no fault
+       jra     Lfsdone
+
+/*
+ * Copy 1 relocation unit (NBPG bytes)
+ * from user virtual address to physical address
+ */
+ENTRY(copyseg)
+       movl    sp@(8),d0                       | destination page number
+       moveq   #PGSHIFT,d1
+       lsll    d1,d0                           | convert to address
+       orl     #PG_CI+PG_RW+PG_V,d0            | make sure valid and writable
+       movl    d0,_CMAP2                       | load in page table
+       movl    #_CADDR2,sp@-                   | destination kernel VA
+       jbsr    _TBIS                           | invalidate any old mapping
+       addql   #4,sp
+       movl    #_CADDR2,a1                     | destination addr
+       movl    sp@(4),a0                       | source addr
+       movl    #NBPG/4-1,d0                    | count
+       movl    #Lcpydone,_u+PCB_ONFAULT        | where to go on a fault
+Lcpyloop:
+       movsl   a0@+,d1                         | read longword
+       movl    d1,a1@+                         | write longword
+       dbf     d0,Lcpyloop                     | continue until done
+Lcpydone:
+       clrl    _u+PCB_ONFAULT                  | clear error catch
+       rts
+
+/*
+ * zero out physical memory
+ * specified in relocation units (NBPG bytes)
+ */
+ENTRY(clearseg)
+       movl    sp@(4),d0                       | destination page number
+       moveq   #PGSHIFT,d1
+       lsll    d1,d0                           | convert to address
+       orl     #PG_CI+PG_RW+PG_V,d0            | make sure valid and writable
+       movl    d0,_CMAP1                       | load in page map
+       movl    #_CADDR1,sp@-                   | destination kernel VA
+       jbsr    _TBIS                           | invalidate any old mapping
+       addql   #4,sp
+       movl    #_CADDR1,a1                     | destination addr
+       movl    #NBPG/4-1,d0                    | count
+/* simple clear loop is fastest on 68020 */
+Lclrloop:
+       clrl    a1@+                            | clear a longword
+       dbf     d0,Lclrloop                     | continue til done
+       rts
+
+/*
+ * Invalidate entire TLB.
+ */
+ENTRY(TBIA)
+__TBIA:
+#if defined(HP330) || defined(HP360) || defined(HP370)
+       tstl    _mmutype                | HP MMU?
+       jeq     Lhpmmu6                 | yes, skip
+       .long   0xf0002400              | no, pflusha
+#if defined(HP360) || defined(HP370)
+       jpl     Lmc68851a               | 68851 implies no d-cache
+       movl    #DC_CLEAR,d0
+       movc    d0,cacr                 | invalidate on-chip d-cache
+Lmc68851a:
+#endif
+       rts
+Lhpmmu6:
+#endif
+#if defined(HP320) || defined(HP350)
+       movl    _IObase+MMUTBINVAL,sp@- | do not ask me, this
+       addql   #4,sp                   |   is how hpux does it
+       jra     __DCIA                  | XXX: invalidate entire cache
+#endif
+       rts
+
+/*
+ * Invalidate any TLB entry for given VA (TB Invalidate Single)
+ */
+ENTRY(TBIS)
+#ifdef DEBUG
+       tstl    fullflush               | being conservative?
+       jne     __TBIA                  | yes, flush entire TLB
+#endif
+#if defined(HP330) || defined(HP360) || defined(HP370)
+       tstl    _mmutype                | HP MMU?
+       jeq     Lhpmmu5                 | yes, skip
+       movl    sp@(4),a0               | get addr to flush
+#if defined(HP360) || defined(HP370)
+       jpl     Lmc68851b               | is 68851?
+       .long   0xf0103810              | pflush #0,#0,a0@
+       movl    #DC_CLEAR,d0
+       movc    d0,cacr                 | invalidate on-chip data cache
+       rts
+Lmc68851b:
+#endif
+       .long   0xf0103c10              | pflushs #0,#0,a0@
+       rts
+Lhpmmu5:
+#endif
+#if defined(HP320) || defined(HP350)
+       movl    sp@(4),d0               | VA to invalidate
+       bclr    #0,d0                   | ensure even
+       movl    d0,a0
+       movw    sr,d1                   | go critical
+       movw    #PSL_HIGHIPL,sr         |   while in purge space
+       moveq   #FC_PURGE,d0            | change address space
+       movc    d0,dfc                  |   for destination
+       moveq   #0,d0                   | zero to invalidate?
+       movsl   d0,a0@                  | hit it
+       moveq   #FC_USERD,d0            | back to old
+       movc    d0,dfc                  |   address space
+       movw    d1,sr                   | restore IPL
+#endif
+       rts
+
+/*
+ * Invalidate supervisor side of TLB
+ */
+ENTRY(TBIAS)
+#ifdef DEBUG
+       tstl    fullflush               | being conservative?
+       jne     __TBIA                  | yes, flush everything
+#endif
+#if defined(HP330) || defined(HP360) || defined(HP370)
+       tstl    _mmutype                | HP MMU?
+       jeq     Lhpmmu7                 | yes, skip
+#if defined(HP360) || defined(HP370)
+       jpl     Lmc68851c               | 68851?
+       .long   0xf0003094              | pflush #4,#4
+       movl    #DC_CLEAR,d0
+       movc    d0,cacr                 | invalidate on-chip d-cache
+       rts
+Lmc68851c:
+#endif
+       .long   0xf0003494              | pflushs #4,#4
+       rts
+Lhpmmu7:
+#endif
+#if defined(HP320) || defined(HP350)
+       movl    #0x8000,d0              | more
+       movl    d0,_IObase+MMUTBINVAL   |   HP magic
+       jra     __DCIS                  | XXX: invalidate entire sup. cache
+#endif
+       rts
+
+/*
+ * Invalidate user side of TLB
+ */
+ENTRY(TBIAU)
+#ifdef DEBUG
+       tstl    fullflush               | being conservative?
+       jne     __TBIA                  | yes, flush everything
+#endif
+#if defined(HP330) || defined(HP360) || defined(HP370)
+       tstl    _mmutype                | HP MMU?
+       jeq     Lhpmmu8                 | yes, skip
+#if defined(HP360) || defined(HP370)
+       jpl     Lmc68851d               | 68851?
+       .long   0xf0003090              | pflush #0,#4
+       movl    #DC_CLEAR,d0
+       movc    d0,cacr                 | invalidate on-chip d-cache
+       rts
+Lmc68851d:
+#endif
+       .long   0xf0003490              | pflushs #0,#4
+       rts
+Lhpmmu8:
+#endif
+#if defined(HP320) || defined(HP350)
+       moveq   #0,d0                   | more
+       movl    d0,_IObase+MMUTBINVAL   |   HP magic
+       jra     __DCIU                  | XXX: invalidate entire user cache
+#endif
+       rts
+
+/*
+ * Invalidate instruction cache
+ */
+ENTRY(ICIA)
+       movl    #IC_CLEAR,d0
+       movc    d0,cacr                 | invalidate i-cache
+       rts
+
+/*
+ * Invalidate data cache.
+ * HP external cache allows for invalidation of user/supervisor portions.
+ */
+ENTRY(DCIA)
+__DCIA:
+#if defined(HP360) || defined(HP370)
+       movl    #DC_CLEAR,d0
+       movc    d0,cacr                 | invalidate on-chip d-cache
+#endif
+#if defined(HP320) || defined(HP350)
+       tstl    _ectype                 | got external VAC?
+       jle     Lnocache2               | no, all done
+       movl    #_IObase+MMUCMD,a0      | MMU control reg
+       andl    #~MMU_CEN,a0@           | disable cache
+       orl     #MMU_CEN,a0@            | reenable cache
+Lnocache2:
+#endif
+       rts
+
+ENTRY(DCIS)
+__DCIS:
+#if defined(HP360) || defined(HP370)
+       movl    #DC_CLEAR,d0
+       movc    d0,cacr                 | invalidate on-chip d-cache
+#endif
+#if defined(HP320) || defined(HP350)
+       tstl    _ectype                 | got external VAC?
+       jle     Lnocache3               | no, all done
+       movl    _IObase+MMUSSTP,d0      | read the supervisor STP
+       movl    d0,_IObase+MMUSSTP      | write it back
+Lnocache3:
+#endif
+       rts
+
+ENTRY(DCIU)
+__DCIU:
+#if defined(HP360) || defined(HP370)
+       movl    #DC_CLEAR,d0
+       movc    d0,cacr                 | invalidate on-chip d-cache
+#endif
+#if defined(HP320) || defined(HP350)
+       tstl    _ectype                 | got external VAC?
+       jle     Lnocache4               | no, all done
+       movl    _IObase+MMUUSTP,d0      | read the user STP
+       movl    d0,_IObase+MMUUSTP      | write it back
+Lnocache4:
+#endif
+       rts
+
+#if defined(HP370)
+ENTRY(PCIA)
+       tstl    _ectype                 | got external PAC?
+       jge     Lnocache6               | no, all done
+       movl    #_IObase+MMUCMD,a0      | MMU control reg
+       andl    #~MMU_CEN,a0@           | disable cache
+       orl     #MMU_CEN,a0@            | reenable cache
+Lnocache6:
+       rts
+#endif
+
+ENTRY(ecacheon)
+       tstl    _ectype
+       jeq     Lnocache7
+       movl    #_IObase+MMUCMD,a0
+       orl     #MMU_CEN,a0@
+Lnocache7:
+       rts
+
+ENTRY(ecacheoff)
+       tstl    _ectype
+       jeq     Lnocache8
+       movl    #_IObase+MMUCMD,a0
+       andl    #~MMU_CEN,a0@
+Lnocache8:
+       rts
+
+       .globl  _getsfc, _getdfc
+_getsfc:
+       movc    sfc,d0
+       rts
+_getdfc:
+       movc    dfc,d0
+       rts
+
+/*
+ * Load a new user segment table pointer.
+ */
+ENTRY(loadustp)
+#if defined(HP330) || defined(HP360) || defined(HP370)
+       tstl    _mmutype                | HP MMU?
+       jeq     Lhpmmu9                 | yes, skip
+       movl    sp@(4),d0               | new USTP
+       moveq   #PGSHIFT,d1
+       lsll    d1,d0                   | convert to addr
+       lea     _protorp,a0             | CRP prototype
+       movl    d0,a0@(4)               | stash USTP
+       .long   0xf0104C00              | pmove a0@,crp
+       movl    #DC_CLEAR,d0
+       movc    d0,cacr                 | invalidate on-chip d-cache
+       rts                             |   since pmove flushes TLB
+Lhpmmu9:
+#endif
+#if defined(HP320) || defined(HP350)
+       movl    sp@(4),_IObase+MMUUSTP  | load a new USTP
+#endif
+       rts
+
+/*
+ * Flush any hardware context associated with given USTP.
+ * Only does something for HP330 where we must flush RPT
+ * and ATC entries in PMMU.
+ */
+ENTRY(flushustp)
+#if defined(HP330)
+       tstl    _mmutype                | 68851 PMMU?
+       jle     Lnot68851               | no, nothing to do
+       movl    sp@(4),d0               | get USTP to flush
+       moveq   #PGSHIFT,d1
+       lsll    d1,d0                   | convert to address
+       movl    d0,_protorp+4           | stash USTP
+       .long   0xf039a000,_protorp     | pflushr _protorp
+Lnot68851:
+#endif
+       rts
+
+ENTRY(ploadw)
+#if defined(HP330) || defined(HP360) || defined(HP370)
+       movl    sp@(4),a0               | address to load
+       .long   0xf0102011              | pload #1,a0@
+#endif
+       rts
+
+/*
+ * Set processor priority level calls.  Most could (should) be replaced
+ * by inline asm expansions.  However, SPL0 and SPLX require special
+ * handling.  If we are returning to the base processor priority (SPL0)
+ * we need to check for our emulated software interrupts.
+ */
+
+ENTRY(spl0)
+       moveq   #0,d0
+       movw    sr,d0                   | get old SR for return
+       movw    #PSL_LOWIPL,sr          | restore new SR
+       jra     Lsplsir
+
+ENTRY(splx)
+       moveq   #0,d0
+       movw    sr,d0                   | get current SR for return
+       movw    sp@(6),d1               | get new value
+       movw    d1,sr                   | restore new SR
+       andw    #PSL_IPL7,d1            | mask all but PSL_IPL
+       jne     Lspldone                | non-zero, all done
+Lsplsir:
+       tstb    _ssir                   | software interrupt pending?
+       jeq     Lspldone                | no, all done
+       subql   #4,sp                   | make room for RTE frame
+       movl    sp@(4),sp@(2)           | position return address
+       clrw    sp@(6)                  | set frame type 0
+       movw    #PSL_LOWIPL,sp@         | and new SR
+       jra     Lgotsir                 | go handle it
+Lspldone:
+       rts
+
+ALTENTRY(splsoftclock, _spl1)
+ALTENTRY(splnet, _spl1)
+ENTRY(spl1)
+       moveq   #0,d0
+       movw    sr,d0
+       movw    #SPL1,sr
+       rts
+
+ENTRY(spl2)
+       moveq   #0,d0
+       movw    sr,d0
+       movw    #SPL2,sr
+       rts
+
+ENTRY(spl3)
+       moveq   #0,d0
+       movw    sr,d0
+       movw    #SPL3,sr
+       rts
+
+ENTRY(spl4)
+       moveq   #0,d0
+       movw    sr,d0
+       movw    #SPL4,sr
+       rts
+
+ALTENTRY(splimp, _spl5)
+ALTENTRY(splbio, _spl5)
+ALTENTRY(spltty, _spl5)
+ENTRY(spl5)
+       moveq   #0,d0
+       movw    sr,d0
+       movw    #SPL5,sr
+       rts
+
+ALTENTRY(splclock, _spl6)
+ENTRY(spl6)
+       moveq   #0,d0
+       movw    sr,d0
+       movw    #SPL6,sr
+       rts
+
+ALTENTRY(splhigh, _spl7)
+ENTRY(spl7)
+       moveq   #0,d0
+       movw    sr,d0
+       movw    #PSL_HIGHIPL,sr
+       rts
+
+#ifdef GPROF
+/*
+ * Special versions of splhigh and splx called by mcount().
+ * Note that __splx does not check for software interrupts.
+ */
+       .globl  __splhigh, __splx
+__splhigh:
+       moveq   #0,d0
+       movw    sr,d0
+       movw    #PSL_HIGHIPL,sr
+       rts
+
+__splx:
+       moveq   #0,d0
+       movw    sr,d0                   | get current SR for return
+       movw    sp@(6),d1               | get new value
+       movw    d1,sr                   | restore new SR
+       rts
+#endif
+
+ENTRY(_insque)
+       movw    sr,d0
+       movw    #PSL_HIGHIPL,sr         | atomic
+       movl    sp@(8),a0               | where to insert (after)
+       movl    sp@(4),a1               | element to insert (e)
+       movl    a0@,a1@                 | e->next = after->next
+       movl    a0,a1@(4)               | e->prev = after
+       movl    a1,a0@                  | after->next = e
+       movl    a1@,a0
+       movl    a1,a0@(4)               | e->next->prev = e
+       movw    d0,sr
+       rts
+
+ENTRY(_remque)
+       movw    sr,d0
+       movw    #PSL_HIGHIPL,sr         | atomic
+       movl    sp@(4),a0               | element to remove (e)
+       movl    a0@,a1
+       movl    a0@(4),a0
+       movl    a0,a1@(4)               | e->next->prev = e->prev
+       movl    a1,a0@                  | e->prev->next = e->next
+       movw    d0,sr
+       rts
+
+ALTENTRY(blkclr, _bzero)
+ENTRY(bzero)
+       movl    sp@(4),a0
+       movl    sp@(8),d0
+       jeq     1$
+       movl    a0,d1
+       btst    #0,d1
+       jeq     2$
+       clrb    a0@+
+       subql   #1,d0
+       jeq     1$
+2$:
+       movl    d0,d1
+       andl    #31,d0
+       lsrl    #5,d1
+       jeq     3$
+4$:
+       clrl    a0@+; clrl      a0@+; clrl      a0@+; clrl      a0@+;
+       clrl    a0@+; clrl      a0@+; clrl      a0@+; clrl      a0@+;
+       subql   #1,d1
+       jne     4$
+       tstl    d0
+       jeq     1$
+3$:
+       clrb    a0@+
+       subql   #1,d0
+       jne     3$
+1$:
+       rts
+
+/*
+ * strlen(str)
+ */
+ENTRY(strlen)
+       moveq   #-1,d0
+       movl    sp@(4),a0       | string
+Lslloop:
+       addql   #1,d0           | increment count
+       tstb    a0@+            | null?
+       jne     Lslloop         | no, keep going
+       rts
+
+/*
+ * bcmp(s1, s2, len)
+ *
+ * WARNING!  This guy only works with counts up to 64K
+ */
+ENTRY(bcmp)
+       movl    sp@(4),a0               | string 1
+       movl    sp@(8),a1               | string 2
+       moveq   #0,d0
+       movw    sp@(14),d0              | length
+       jeq     Lcmpdone                | if zero, nothing to do
+       subqw   #1,d0                   | set up for DBcc loop
+Lcmploop:
+       cmpmb   a0@+,a1@+               | equal?
+       dbne    d0,Lcmploop             | yes, keep going
+       addqw   #1,d0                   | +1 gives zero on match
+Lcmpdone:
+       rts
+       
+/*
+ * {ov}bcopy(from, to, len)
+ *
+ * Works for counts up to 128K.
+ */
+ALTENTRY(ovbcopy, _bcopy)
+ENTRY(bcopy)
+       movl    sp@(12),d0              | get count
+       jeq     Lcpyexit                | if zero, return
+       movl    sp@(4),a0               | src address
+       movl    sp@(8),a1               | dest address
+       cmpl    a1,a0                   | src before dest?
+       jlt     Lcpyback                | yes, copy backwards (avoids overlap)
+       movl    a0,d1
+       btst    #0,d1                   | src address odd?
+       jeq     Lcfeven                 | no, go check dest
+       movb    a0@+,a1@+               | yes, copy a byte
+       subql   #1,d0                   | update count
+       jeq     Lcpyexit                | exit if done
+Lcfeven:
+       movl    a1,d1
+       btst    #0,d1                   | dest address odd?
+       jne     Lcfbyte                 | yes, must copy by bytes
+       movl    d0,d1                   | no, get count
+       lsrl    #2,d1                   | convert to longwords
+       jeq     Lcfbyte                 | no longwords, copy bytes
+       subql   #1,d1                   | set up for dbf
+Lcflloop:
+       movl    a0@+,a1@+               | copy longwords
+       dbf     d1,Lcflloop             | til done
+       andl    #3,d0                   | get remaining count
+       jeq     Lcpyexit                | done if none
+Lcfbyte:
+       subql   #1,d0                   | set up for dbf
+Lcfbloop:
+       movb    a0@+,a1@+               | copy bytes
+       dbf     d0,Lcfbloop             | til done
+Lcpyexit:
+       rts
+Lcpyback:
+       addl    d0,a0                   | add count to src
+       addl    d0,a1                   | add count to dest
+       movl    a0,d1
+       btst    #0,d1                   | src address odd?
+       jeq     Lcbeven                 | no, go check dest
+       movb    a0@-,a1@-               | yes, copy a byte
+       subql   #1,d0                   | update count
+       jeq     Lcpyexit                | exit if done
+Lcbeven:
+       movl    a1,d1
+       btst    #0,d1                   | dest address odd?
+       jne     Lcbbyte                 | yes, must copy by bytes
+       movl    d0,d1                   | no, get count
+       lsrl    #2,d1                   | convert to longwords
+       jeq     Lcbbyte                 | no longwords, copy bytes
+       subql   #1,d1                   | set up for dbf
+Lcblloop:
+       movl    a0@-,a1@-               | copy longwords
+       dbf     d1,Lcblloop             | til done
+       andl    #3,d0                   | get remaining count
+       jeq     Lcpyexit                | done if none
+Lcbbyte:
+       subql   #1,d0                   | set up for dbf
+Lcbbloop:
+       movb    a0@-,a1@-               | copy bytes
+       dbf     d0,Lcbbloop             | til done
+       rts
+
+/*
+ * Emulate fancy VAX string operations:
+ *     scanc(count, startc, table, mask)
+ *     skpc(mask, count, startc)
+ *     locc(mask, count, startc)
+ */
+ENTRY(scanc)
+       movl    sp@(4),d0       | get length
+       jeq     Lscdone         | nothing to do, return
+       movl    sp@(8),a0       | start of scan
+       movl    sp@(12),a1      | table to compare with
+       movb    sp@(19),d1      | and mask to use
+       movw    d2,sp@-         | need a scratch register
+       clrw    d2              | clear it out
+       subqw   #1,d0           | adjust for dbra
+Lscloop:
+       movb    a0@+,d2         | get character
+       movb    a1@(0,d2:w),d2  | get table entry
+       andb    d1,d2           | mask it
+       dbne    d0,Lscloop      | keep going til no more or non-zero
+       addqw   #1,d0           | overshot by one
+       movw    sp@+,d2         | restore scratch
+Lscdone:
+       rts
+
+ENTRY(skpc)
+       movl    sp@(8),d0       | get length
+       jeq     Lskdone         | nothing to do, return
+       movb    sp@(7),d1       | mask to use
+       movl    sp@(12),a0      | where to start
+       subqw   #1,d0           | adjust for dbcc
+Lskloop:
+       cmpb    a0@+,d1         | compate with mask
+       dbne    d0,Lskloop      | keep going til no more or zero
+       addqw   #1,d0           | overshot by one
+Lskdone:
+       rts
+
+ENTRY(locc)
+       movl    sp@(8),d0       | get length
+       jeq     Llcdone         | nothing to do, return
+       movb    sp@(7),d1       | mask to use
+       movl    sp@(12),a0      | where to start
+       subqw   #1,d0           | adjust for dbcc
+Llcloop:
+       cmpb    a0@+,d1         | compate with mask
+       dbeq    d0,Llcloop      | keep going til no more or non-zero
+       addqw   #1,d0           | overshot by one
+Llcdone:
+       rts
+
+/*
+ * Emulate VAX FFS (find first set) instruction.
+ */
+ENTRY(ffs)
+       moveq   #-1,d0
+       movl    sp@(4),d1
+       beq     Lffsdone
+Lffsloop:
+       addql   #1,d0
+       btst    d0,d1
+       beq     Lffsloop
+Lffsdone:
+       addql   #1,d0
+       rts
+
+#ifdef FPCOPROC
+/*
+ * Save and restore 68881 state.
+ * Pretty awful looking since our assembler does not
+ * recognize FP mnemonics.
+ */
+ENTRY(m68881_save)
+       movl    sp@(4),a0               | save area pointer
+       .word   0xf310                  | fsave a0@
+       tstb    a0@                     | null state frame?
+       jeq     Lm68881sdone            | yes, all done
+       .word   0xf228,0xf0ff,0x00d8    | fmovem fp0-fp7,a0@(216)
+       .word   0xf228,0xbc00,0x0138    | fmovem fpcr/fpsr/fpiar,a0@(312)
+Lm68881sdone:
+       rts
+
+ENTRY(m68881_restore)
+       movl    sp@(4),a0               | save area pointer
+       tstb    a0@                     | null state frame?
+       jeq     Lm68881rdone            | yes, easy
+       .word   0xf228,0x9c00,0x0138    | fmovem a0@(312),fpcr/fpsr/fpiar
+       .word   0xf228,0xd0ff,0x00d8    | fmovem a0@(216),fp0-fp7
+Lm68881rdone:
+       .word   0xf350                  | frestore a0@
+       rts
+#endif
+
+/*
+ * Handle the nitty-gritty of rebooting the machine.
+ * Basically we just turn off the MMU and jump to the appropriate ROM routine.
+ * Note that we must be running in an address range that is mapped one-to-one
+ * logical to physical so that the PC is still valid immediately after the MMU
+ * is turned off.
+ */
+       .globl  _doboot
+_doboot:
+       movl    #CACHE_OFF,d0
+       movc    d0,cacr                 | disable on-chip cache(s)
+#if defined(HP320) || defined(HP350) || defined(HP370)
+       tstl    _ectype
+       jeq     Lnocache5
+       andl    #~MMU_CEN,_IObase+MMUCMD| disable external cache
+Lnocache5:
+#endif
+/* one-to-one map the last page of memory */
+       movl    #MAXADDR,d0             | last page of RAM used to pass params
+       orl     #PG_RW+PG_V,d0          | create a PTE
+       movl    d0,_mmap                |   to access that page
+       jbsr    _TBIA                   | invalidate TLB
+       movl    #MAXADDR,d0             | last page of RAM is also used
+       orl     #SG_RW+SG_V,d0          |   as the page table for itself
+       movl    d0,eSysseg-4            |   (ok since it needs only last word)
+       movl    _vmmap+NBPG-4,d2        | save old contents
+       movl    _mmap,_vmmap+NBPG-4     | store PTE in new page table
+       jbsr    _TBIA                   | invalidate again
+       lea     MAXADDR,a0              | can now access last page
+       movl    _boothowto,a0@+         | store howto
+       movl    _bootdev,a0@+           | and devtype
+       lea     Lbootcode,a1            | start of boot code
+       lea     Lebootcode,a3           | end of boot code
+Lbootcopy:
+       movw    a1@+,a0@+               | copy a word
+       cmpl    a3,a1                   | done yet?
+       jcs     Lbootcopy               | no, keep going
+       jmp     MAXADDR+8               | jump to last page
+
+Lbootcode:
+       lea     MAXADDR+0x800,sp        | physical SP in case of NMI
+#if defined(HP330) || defined(HP360) || defined(HP370)
+       tstl    _mmutype                | HP MMU?
+       jeq     LhpmmuB                 | yes, skip
+       movl    #0,a0@                  | value for pmove to TC (turn off MMU)
+       .long   0xf0104000              | pmove a0@,tc
+       movl    d2,MAXADDR+NBPG-4       | restore old high page contents
+       jmp     0x1A4                   | goto REQ_REBOOT
+LhpmmuB:
+#endif
+#if defined(HP320) || defined(HP350)
+       movl    #0xFFFF0000,_IObase+MMUCMD      | totally disable MMU
+       movl    d2,MAXADDR+NBPG-4       | restore old high page contents
+       jmp     0x1A4                   | goto REQ_REBOOT
+#endif
+Lebootcode:
+
+       .data
+       .space  NBPG
+tmpstk:
+       .globl  _machineid
+_machineid:
+       .long   0               | default to 320
+       .globl  _mmutype,_protorp
+_mmutype:
+       .long   0               | default to HP MMU
+_protorp:
+       .long   0,0             | prototype root pointer
+       .globl  _ectype
+_ectype:
+       .long   0               | external cache type, default to none
+       .globl  _cold
+_cold:
+       .long   1               | cold start flag
+#ifdef DEBUG
+       .globl  fullflush
+fullflush:
+       .long   0
+       .globl  timebomb
+timebomb:
+       .long   0
+#endif
+/* interrupt counters */
+       .globl  _intrcnt,_eintrcnt,_intrnames,_eintrnames
+_intrnames:
+       .asciz  "spur"
+       .asciz  "hil"
+       .asciz  "lev2"
+       .asciz  "lev3"
+       .asciz  "lev4"
+       .asciz  "lev5"
+       .asciz  "dma"
+       .asciz  "clock"
+#ifdef PROFTIMER
+       .asciz  "pclock"
+#endif
+       .asciz  "nmi"
+_eintrnames:
+       .even
+_intrcnt:
+#ifdef PROFTIMER
+       .long   0,0,0,0,0,0,0,0,0,0
+#else
+       .long   0,0,0,0,0,0,0,0,0
+#endif
+_eintrcnt:
diff --git a/usr/src/sys/hp300/hp300/machdep.c b/usr/src/sys/hp300/hp300/machdep.c
new file mode 100644 (file)
index 0000000..09db7c9
--- /dev/null
@@ -0,0 +1,1408 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: machdep.c 1.51 89/11/28$
+ *
+ *     @(#)machdep.c   7.1 (Berkeley) %G%
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "user.h"
+#include "kernel.h"
+#include "map.h"
+#include "vm.h"
+#include "proc.h"
+#include "buf.h"
+#include "reboot.h"
+#include "conf.h"
+#include "vnode.h"
+#include "file.h"
+#include "text.h"
+#include "clist.h"
+#include "callout.h"
+#include "cmap.h"
+#include "malloc.h"
+#include "mbuf.h"
+#include "msgbuf.h"
+#include "../ufs/quota.h"
+#ifdef SYSVSHM
+#include "shm.h"
+#endif
+#ifdef HPUXCOMPAT
+#include "../hpux/hpux.h"
+#endif
+
+#include "cpu.h"
+#include "reg.h"
+#include "pte.h"
+#include "psl.h"
+#include "isr.h"
+#include "../net/netisr.h"
+
+/*
+ * 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;           /* set when safe to use msgbuf */
+int    physmem = MAXMEM;       /* max supported memory, changes to actual */
+
+extern u_int lowram;
+
+/*
+ * Machine-dependent startup code
+ */
+startup(firstaddr)
+       int firstaddr;
+{
+       register int unixsize;
+       register unsigned i;
+       register struct pte *pte;
+       int mapaddr, j, n;
+       register caddr_t v;
+       int maxbufs, base, residual;
+       extern long Usrptsize;
+       extern struct map *useriomap;
+
+       /*
+        * Set cpuspeed immediately since cninit() called routines
+        * might use delay.
+        */
+       switch (machineid) {
+       case HP_320:
+       case HP_330:
+       case HP_340:
+               cpuspeed = MHZ_16;
+               break;
+       case HP_350:
+       case HP_360:
+               cpuspeed = MHZ_25;
+               break;
+       case HP_370:
+               cpuspeed = MHZ_33;
+               break;
+       }
+       /*
+         * Find what hardware is attached to this machine.
+         */
+       find_devs();
+       /*
+        * Initialize the console before we print anything out.
+        */
+       cninit();
+       /*
+        * Initialize error message buffer (at end of core).
+        */
+       maxmem -= btoc(sizeof (struct msgbuf));
+       pte = msgbufmap;
+       for (i = 0; i < btoc(sizeof (struct msgbuf)); i++)
+               *(int *)pte++ = PG_CI | PG_V | PG_KW | (ctob(maxmem + i));
+       TBIAS();
+       msgbufmapped = 1;
+
+       /*
+        * Good {morning,afternoon,evening,night}.
+        */
+       printf(version);
+       identifycpu();
+       printf("real mem = %d\n", ctob(physmem));
+
+       /*
+        * Allocate space for system data structures.
+        * The first available real memory address is in "firstaddr".
+        * The first available kernel virtual address is in "v".
+        * As pages of kernel virtual memory are allocated, "v" is incremented.
+        * As pages of memory are allocated and cleared,
+        * "firstaddr" is incremented.
+        * An index into the kernel page table corresponding to the
+        * virtual memory address maintained in "v" is kept in "mapaddr".
+        */
+       v = (caddr_t)((firstaddr * NBPG) - lowram);
+       mapaddr = (int)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)))
+       valloclim(vnode, struct vnode, nvnode, vnodeNVNODE);
+       valloclim(file, struct file, nfile, fileNFILE);
+       valloclim(proc, struct proc, nproc, procNPROC);
+       valloclim(text, struct text, ntext, textNTEXT);
+       valloc(cfree, struct cblock, nclist);
+       valloc(callout, struct callout, ncallout);
+       valloc(swapmap, struct map, nswapmap = nproc * 2);
+       valloc(argmap, struct map, ARGMAPSIZE);
+       valloc(kernelmap, struct map, nproc);
+       valloc(mbmap, struct map, nmbclusters/4);
+       valloc(namecache, struct namecache, nchsize);
+       valloc(kmemmap, struct map, ekmempt - kmempt);
+       valloc(kmemusage, struct kmemusage, ekmempt - kmempt);
+       valloc(useriomap, struct map, nproc);
+#ifdef QUOTA
+       valloclim(quota, struct quota, nquota, quotaNQUOTA);
+       valloclim(dquot, struct dquot, ndquot, dquotNDQUOT);
+#endif
+#ifdef SYSVSHM
+       valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
+#endif
+       
+       /*
+        * Determine how many buffers to allocate.
+        * Since HPs tend to be long on memory and short on disk speed,
+        * we allocate more buffer space than the BSD standard of
+        * use 10% of memory for the first 2 Meg, 5% of remaining.
+        * We just allocate a flat 10%.  Insure 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);
+
+       /*
+        * Now the amount of virtual memory remaining for buffers
+        * can be calculated, estimating needs for the cmap.
+        */
+       ncmap = (maxmem*NBPG - (firstaddr*NBPG + ((int)v - mapaddr))) /
+               (CLBYTES + sizeof(struct cmap)) + 2;
+       maxbufs = ((SYSPTSIZE * NBPG) -
+               (int)(v + ncmap * sizeof(struct cmap))) /
+               (MAXBSIZE + sizeof(struct buf));
+       if (maxbufs < 16)
+               panic("sys pt too small");
+       if (nbuf > maxbufs) {
+               printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs);
+               nbuf = maxbufs;
+       }
+       if (bufpages > nbuf * (MAXBSIZE / CLBYTES))
+               bufpages = nbuf * (MAXBSIZE / CLBYTES);
+       valloc(buf, struct buf, nbuf);
+
+       /*
+        * Allocate space for core map.
+        * Allow space for all of physical memory minus the amount 
+        * dedicated to the system. The amount of physical memory
+        * dedicated to the system is the total virtual memory of
+        * the system thus far, plus core map, buffer pages,
+        * and buffer headers not yet allocated.
+        * Add 2: 1 because the 0th entry is unused, 1 for rounding.
+        */
+       ncmap = (maxmem*NBPG - (firstaddr * NBPG +
+               ((int)(v + bufpages*CLBYTES) - mapaddr))) /
+               (CLBYTES + sizeof(struct cmap)) + 2;
+       valloclim(cmap, struct cmap, ncmap, ecmap);
+
+       /*
+        * Clear space allocated thus far, and make r/w entries
+        * for the space in the kernel map.
+        */
+       unixsize = btoc(v);
+       mapaddr = btoc(mapaddr);
+       while (mapaddr < unixsize) {
+               *(int *)(&Sysmap[mapaddr]) = PG_V | PG_KW | ctob(firstaddr);
+               clearseg((unsigned)firstaddr);
+               firstaddr++;
+               mapaddr++;
+       }
+
+       /*
+        * Now allocate buffers proper.  They are different than the above
+        * in that they usually occupy more virtual memory than physical.
+        */
+       v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET);
+       valloc(buffers, char, MAXBSIZE * nbuf);
+       base = bufpages / nbuf;
+       residual = bufpages % nbuf;
+       for (i = 0; i < nbuf; i++) {
+               n = (i < residual ? base + 1 : base) * CLSIZE;
+               for (j = 0; j < n; j++) {
+                       *(int *)(&Sysmap[mapaddr+j]) =
+                           PG_CI | PG_V | PG_KW | ctob(firstaddr);
+                       clearseg((unsigned)firstaddr);
+                       firstaddr++;
+               }
+               mapaddr += MAXBSIZE / NBPG;
+       }
+
+       unixsize = btoc(v);
+       if (firstaddr - Sysmap[0].pg_pfnum >= physmem - 8*UPAGES)
+               panic("no memory");
+       TBIA();                         /* After we just cleared it all! */
+
+       /*
+        * Initialize callouts
+        */
+       callfree = callout;
+       for (i = 1; i < ncallout; i++)
+               callout[i-1].c_next = &callout[i];
+
+       /*
+        * Initialize memory allocator and swap
+        * and user page table maps.
+        *
+        * THE USER PAGE TABLE MAP IS CALLED ``kernelmap''
+        * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME.
+        */
+       meminit(firstaddr, maxmem);
+       maxmem = freemem;
+       printf("avail mem = %d\n", ctob(maxmem));
+       printf("using %d buffers containing %d bytes of memory\n",
+               nbuf, bufpages * CLBYTES);
+       rminit(kernelmap, (long)&Usrptsize-CLSIZE, (long)1, "usrpt", nproc);
+       rminit(useriomap, (long)USRIOSIZE, (long)1, "usrio", nproc);
+       rminit(mbmap, (long)(nmbclusters * MCLBYTES / NBPG), (long)CLSIZE,
+           "mbclusters", nmbclusters/4);
+       kmeminit();     /* now safe to do malloc/free */
+
+       /*
+        * Set up CPU-specific registers, cache, etc.
+        */
+       initcpu();
+
+       /*
+        * Set up buffers, so they can be used to read disk labels.
+        */
+       bhinit();
+       binit();
+
+       /*
+        * Configure the system.
+        */
+       configure();
+}
+
+#ifdef PGINPROF
+/*
+ * Return the difference (in microseconds)
+ * between the  current time and a previous
+ * time as represented by the arguments.
+ */
+/*ARGSUSED*/
+vmtime(otime, olbolt, oicr)
+       register int otime, olbolt, oicr;
+{
+
+       return (((time.tv_sec-otime)*100 + lbolt-olbolt)*10000);
+}
+#endif
+
+/*
+ * Clear registers on exec
+ */
+setregs(entry)
+       u_long entry;
+{
+       u.u_ar0[PC] = entry & ~1;
+#ifdef FPCOPROC
+       /* restore a null state frame */
+       u.u_pcb.pcb_fpregs.fpf_null = 0;
+       m68881_restore(&u.u_pcb.pcb_fpregs);
+#endif
+#ifdef HPUXCOMPAT
+       if (u.u_procp->p_flag & SHPUX) {
+
+               u.u_ar0[A0] = 0;        /* not 68010 (bit 31), no FPA (30) */
+               u.u_r.r_val1 = 0;       /* no float card */
+#ifdef FPCOPROC
+               u.u_r.r_val2 = 1;       /* yes 68881 */
+#else
+               u.u_r.r_val2 = 0;       /* no 68881 */
+#endif
+       }
+       /*
+        * Ensure we perform the right action on traps type 1 and 2:
+        * If our parent is an HPUX process and we are being traced, turn
+        * on HPUX style interpretation.  Else if we were using the HPUX
+        * style interpretation, revert to the BSD interpretation.
+        *
+        * XXX This doesn't have much to do with setting registers but
+        * I didn't want to muck up kern_exec.c with this code, so I
+        * stuck it here.
+        */
+       if ((u.u_procp->p_pptr->p_flag & SHPUX) &&
+           (u.u_procp->p_flag & STRC)) {
+               tweaksigcode(1);
+               u.u_pcb.pcb_flags |= PCB_HPUXTRACE;
+       } else if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) {
+               tweaksigcode(0);
+               u.u_pcb.pcb_flags &= ~PCB_HPUXTRACE;
+       }
+#endif
+}
+
+identifycpu()
+{
+       printf("HP9000/");
+       switch (machineid) {
+       case HP_320:
+               printf("320 (16.67Mhz");
+               break;
+       case HP_330:
+               printf("318/319/330 (16.67Mhz");
+               break;
+       case HP_340:
+               printf("340 (16.67Mhz");
+               break;
+       case HP_350:
+               printf("350 (25Mhz");
+               break;
+       case HP_360:
+               printf("360 (25Mhz");
+               break;
+       case HP_370:
+               printf("370 (33.33Mhz");
+               break;
+       default:
+               printf("\nunknown machine type %d\n", machineid);
+               panic("startup");
+       }
+       printf(" MC680%s CPU", mmutype == MMU_68030 ? "30" : "20");
+       switch (mmutype) {
+       case MMU_68030:
+               printf("+MMU");
+               break;
+       case MMU_68851:
+               printf(", MC68851 MMU");
+               break;
+       case MMU_HP:
+               printf(", HP MMU");
+               break;
+       default:
+               printf("\nunknown MMU type %d\n", mmutype);
+               panic("startup");
+       }
+       if (mmutype == MMU_68030)
+               printf(", %sMhz MC68882 FPU",
+                      machineid == HP_340 ? "16.67" :
+                      (machineid == HP_360 ? "25" : "33.33"));
+       else
+               printf(", %sMhz MC68881 FPU",
+                      machineid == HP_350 ? "20" : "16.67");
+       switch (ectype) {
+       case EC_VIRT:
+               printf(", %dK virtual-address cache",
+                      machineid == HP_320 ? 16 : 32);
+               break;
+       case EC_PHYS:
+               printf(", 64K physical-address cache");
+               break;
+       }
+       printf(")\n");
+       /*
+        * Now that we have told the user what they have,
+        * let them know if that machine type isn't configured.
+        */
+       switch (machineid) {
+       case -1:                /* keep compilers happy */
+#if !defined(HP320) && !defined(HP350)
+       case HP_320:
+       case HP_350:
+#endif
+#ifndef HP330
+       case HP_330:
+#endif
+#if !defined(HP360) && !defined(HP370)
+       case HP_340:
+       case HP_360:
+       case HP_370:
+#endif
+               panic("CPU type not configured");
+       default:
+               break;
+       }
+}
+
+#ifdef HPUXCOMPAT
+tweaksigcode(ishpux)
+{
+       static short *sigtrap = NULL;
+
+       /* locate trap instruction in pcb_sigc */
+       if (sigtrap == NULL) {
+               register struct pcb *pcp = &u.u_pcb;
+
+               sigtrap = &pcp->pcb_sigc[sizeof(pcp->pcb_sigc)/sizeof(short)];
+               while (--sigtrap >= pcp->pcb_sigc)
+                       if ((*sigtrap & 0xFFF0) == 0x4E40)
+                               break;
+               if (sigtrap < pcp->pcb_sigc)
+                       panic("bogus sigcode\n");
+       }
+       *sigtrap = ishpux ? 0x4E42 : 0x4E41;
+}
+#endif
+
+#define SS_RTEFRAME    1
+#define SS_FPSTATE     2
+#define SS_USERREGS    4
+
+struct sigstate {
+       int     ss_flags;               /* which of the following are valid */
+       struct  frame ss_frame;         /* original exception frame */
+       struct  fpframe ss_fpstate;     /* 68881/68882 state info */
+};
+
+/*
+ * 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  sigstate sf_state;      /* state of the hardware */
+       struct  sigcontext sf_sc;       /* actual context */
+};
+
+#ifdef HPUXCOMPAT
+struct hpuxsigcontext {
+       int     hsc_syscall;
+       char    hsc_action;
+       char    hsc_pad1;
+       char    hsc_pad2;
+       char    hsc_onstack;
+       int     hsc_mask;
+       int     hsc_sp;
+       short   hsc_ps;
+       int     hsc_pc;
+/* the rest aren't part of the context but are included for our convenience */
+       short   hsc_pad;
+       u_int   hsc_magic;              /* XXX sigreturn: cookie */
+       struct  sigcontext *hsc_realsc; /* XXX sigreturn: ptr to BSD context */
+};
+
+/*
+ * For an HP-UX process, a partial hpuxsigframe follows the normal sigframe.
+ * Tremendous waste of space, but some HP-UX applications (e.g. LCL) need it.
+ */
+struct hpuxsigframe {
+       int     hsf_signum;
+       int     hsf_code;
+       struct  sigcontext *hsf_scp;
+       struct  hpuxsigcontext hsf_sc;
+       int     hsf_regs[15];
+};
+#endif
+
+#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.
+ */
+sendsig(catcher, sig, mask, code)
+       sig_t catcher;
+       int sig, mask;
+       unsigned code;
+{
+       register struct proc *p = u.u_procp;
+       register struct sigframe *fp, *kfp;
+       register struct frame *frame;
+       register short ft;
+       int oonstack, fsize;
+
+       frame = (struct frame *)u.u_ar0;
+       ft = frame->f_format;
+       oonstack = u.u_onstack;
+       /*
+        * Allocate and validate space for the signal handler
+        * context. Note that if the stack is in P0 space, the
+        * call to grow() is a nop, and the useracc() check
+        * will fail if the process has not already allocated
+        * the space with a `brk'.
+        */
+#ifdef HPUXCOMPAT
+       if (p->p_flag & SHPUX)
+               fsize = sizeof(struct sigframe) + sizeof(struct hpuxsigframe);
+       else
+#endif
+       fsize = sizeof(struct sigframe);
+       if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) {
+               fp = (struct sigframe *)(u.u_sigsp - fsize);
+               u.u_onstack = 1;
+       } else
+               fp = (struct sigframe *)(frame->f_regs[SP] - fsize);
+       if ((unsigned)fp <= USRSTACK - ctob(u.u_ssize)) 
+               (void)grow((unsigned)fp);
+#ifdef DEBUG
+       if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+               printf("sendsig: pid %d, sig %d ssp %x usp %x scp %x ft %d\n",
+                      p->p_pid, sig, &oonstack, fp, &fp->sf_sc, ft);
+#endif
+       if (useracc((caddr_t)fp, fsize, B_WRITE) == 0) {
+#ifdef DEBUG
+               if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+                       printf("sendsig: pid %d, useracc failed on sig %d\n",
+                              p->p_pid, sig);
+#endif
+               /*
+                * 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;
+       }
+       kfp = (struct sigframe *)malloc((u_long)fsize, M_TEMP, M_WAITOK);
+       /* 
+        * Build the argument list for the signal handler.
+        */
+       kfp->sf_signum = sig;
+       kfp->sf_code = code;
+       kfp->sf_scp = &fp->sf_sc;
+       kfp->sf_handler = catcher;
+       /*
+        * Save necessary hardware state.  Currently this includes:
+        *      - general registers
+        *      - original exception frame (if not a "normal" frame)
+        *      - FP coprocessor state
+        */
+       kfp->sf_state.ss_flags = SS_USERREGS;
+       bcopy((caddr_t)frame->f_regs,
+             (caddr_t)kfp->sf_state.ss_frame.f_regs, sizeof frame->f_regs);
+       if (ft >= FMT9) {
+#ifdef DEBUG
+               if (ft != FMT9 && ft != FMTA && ft != FMTB)
+                       panic("sendsig: bogus frame type");
+#endif
+               kfp->sf_state.ss_flags |= SS_RTEFRAME;
+               kfp->sf_state.ss_frame.f_format = frame->f_format;
+               kfp->sf_state.ss_frame.f_vector = frame->f_vector;
+               bcopy((caddr_t)&frame->F_u,
+                     (caddr_t)&kfp->sf_state.ss_frame.F_u,
+                     (ft == FMT9) ? FMT9SIZE :
+                     (ft == FMTA) ? FMTASIZE : FMTBSIZE);
+               /*
+                * Gag!  Leave an indicator that we need to clean up the
+                * kernel stack.  We do this by setting the "pad word"
+                * above the hardware stack frame.  "bexit" in locore
+                * will then know that it must compress the kernel stack
+                * and create a normal four word stack frame.
+                */
+               frame->f_stackadj = -1;
+#ifdef DEBUG
+               if (sigdebug & SDB_FOLLOW)
+                       printf("sendsig: pid %d, copy out %d of frame %d\n",
+                              p->p_pid,
+                              (ft == FMT9) ? FMT9SIZE :
+                              (ft == FMTA) ? FMTASIZE : FMTBSIZE, ft);
+#endif
+       }
+#ifdef FPCOPROC
+       kfp->sf_state.ss_flags |= SS_FPSTATE;
+       m68881_save(&kfp->sf_state.ss_fpstate);
+#ifdef DEBUG
+       if ((sigdebug & SDB_FPSTATE) && *(char *)&kfp->sf_state.ss_fpstate)
+               printf("sendsig: pid %d, copy out FP state (%x) to %x\n",
+                      p->p_pid, *(u_int *)&kfp->sf_state.ss_fpstate,
+                      &kfp->sf_state.ss_fpstate);
+#endif
+#endif
+       /*
+        * Build the signal context to be used by sigreturn.
+        */
+       kfp->sf_sc.sc_onstack = oonstack;
+       kfp->sf_sc.sc_mask = mask;
+       kfp->sf_sc.sc_sp = frame->f_regs[SP];
+       kfp->sf_sc.sc_fp = frame->f_regs[A6];
+       kfp->sf_sc.sc_ap = (int)&fp->sf_state;
+       kfp->sf_sc.sc_pc = frame->f_pc;
+       kfp->sf_sc.sc_ps = frame->f_sr;
+#ifdef HPUXCOMPAT
+       /*
+        * Create an HP-UX style sigcontext structure and associated goo
+        */
+       if (p->p_flag & SHPUX) {
+               register struct hpuxsigframe *hkfp;
+
+               hkfp = (struct hpuxsigframe *)&kfp[1];
+               hkfp->hsf_signum = bsdtohpuxsig(kfp->sf_signum);
+               hkfp->hsf_code = kfp->sf_code;
+               hkfp->hsf_scp = (struct sigcontext *)
+                       &((struct hpuxsigframe *)(&fp[1]))->hsf_sc;
+               hkfp->hsf_sc.hsc_syscall = 0;           /* XXX */
+               hkfp->hsf_sc.hsc_action = 0;            /* XXX */
+               hkfp->hsf_sc.hsc_pad1 = hkfp->hsf_sc.hsc_pad2 = 0;
+               hkfp->hsf_sc.hsc_onstack = kfp->sf_sc.sc_onstack;
+               hkfp->hsf_sc.hsc_mask = kfp->sf_sc.sc_mask;
+               hkfp->hsf_sc.hsc_sp = kfp->sf_sc.sc_sp;
+               hkfp->hsf_sc.hsc_ps = kfp->sf_sc.sc_ps;
+               hkfp->hsf_sc.hsc_pc = kfp->sf_sc.sc_pc;
+               hkfp->hsf_sc.hsc_pad = 0;
+               hkfp->hsf_sc.hsc_magic = 0xdeadbeef;
+               hkfp->hsf_sc.hsc_realsc = kfp->sf_scp;
+               bcopy((caddr_t)frame->f_regs, (caddr_t)hkfp->hsf_regs,
+                     sizeof (hkfp->hsf_regs));
+
+               kfp->sf_signum = hkfp->hsf_signum;
+               kfp->sf_scp = hkfp->hsf_scp;
+       }
+#endif
+       (void) copyout((caddr_t)kfp, (caddr_t)fp, fsize);
+       frame->f_regs[SP] = (int)fp;
+#ifdef DEBUG
+       if (sigdebug & SDB_FOLLOW)
+               printf("sendsig: pid %d, scp %x, fp %x, sc_ap %x\n",
+                      p->p_pid, kfp->sf_scp, fp, kfp->sf_sc.sc_ap);
+#endif
+       /*
+        * User PC is set to signal trampoline code.  The catch is that
+        * it must be set to reference the pcb via the user space address
+        * NOT via u.  Assumption: u-area is at USRSTACK.
+        */
+       frame->f_pc = (int)((struct user *)USRSTACK)->u_pcb.pcb_sigc;
+#ifdef DEBUG
+       if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+               printf("sendsig: pid %d, sig %d, returns\n",
+                      p->p_pid, sig);
+#endif
+       free((caddr_t)kfp, M_TEMP);
+}
+
+/*
+ * 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.
+ */
+sigreturn()
+{
+       struct a {
+               struct sigcontext *sigcntxp;
+       };
+       register struct sigcontext *scp;
+       register struct frame *frame;
+       register int rf;
+       struct sigcontext tsigc;
+       struct sigstate tstate;
+       int flags;
+
+       scp = ((struct a *)(u.u_ap))->sigcntxp;
+#ifdef DEBUG
+       if (sigdebug & SDB_FOLLOW)
+               printf("sigreturn: pid %d, scp %x\n", u.u_procp->p_pid, scp);
+#endif
+       if ((int)scp & 1) {
+               u.u_error = EINVAL;
+               return;
+       }
+#ifdef HPUXCOMPAT
+       /*
+        * Grab context as an HP-UX style context and determine if it
+        * was one that we contructed in sendsig.
+        */
+       if (u.u_procp->p_flag & SHPUX) {
+               struct hpuxsigcontext *hscp = (struct hpuxsigcontext *)scp;
+               struct hpuxsigcontext htsigc;
+
+               if (useracc((caddr_t)hscp, sizeof (*hscp), B_WRITE) == 0 ||
+                   copyin((caddr_t)hscp, (caddr_t)&htsigc, sizeof htsigc))
+                       return;
+               /*
+                * If not generated by sendsig or we cannot restore the
+                * BSD-style sigcontext, just restore what we can -- state
+                * will be lost, but them's the breaks.
+                */
+               hscp = &htsigc;
+               if (hscp->hsc_magic != 0xdeadbeef ||
+                   (scp = hscp->hsc_realsc) == 0 ||
+                   useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
+                   copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc)) {
+                       u.u_eosys = JUSTRETURN;
+                       u.u_onstack = hscp->hsc_onstack & 01;
+                       u.u_procp->p_sigmask = hscp->hsc_mask &~ sigcantmask;
+                       frame = (struct frame *) u.u_ar0;
+                       frame->f_regs[SP] = hscp->hsc_sp;
+                       frame->f_pc = hscp->hsc_pc;
+                       frame->f_sr = hscp->hsc_ps &~ PSL_USERCLR;
+                       return;
+               }
+               /*
+                * Otherwise, overlay BSD context with possibly modified
+                * HP-UX values.
+                */
+               tsigc.sc_onstack = hscp->hsc_onstack;
+               tsigc.sc_mask = hscp->hsc_mask;
+               tsigc.sc_sp = hscp->hsc_sp;
+               tsigc.sc_ps = hscp->hsc_ps;
+               tsigc.sc_pc = hscp->hsc_pc;
+       } else
+#endif
+       /*
+        * Test and fetch the context structure.
+        * We grab it all at once for speed.
+        */
+       if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
+           copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc))
+               return;
+       scp = &tsigc;
+       if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0) {
+               u.u_error = EINVAL;
+               return;
+       }
+       /*
+        * Restore the user supplied information
+        */
+       u.u_eosys = JUSTRETURN;
+       u.u_onstack = scp->sc_onstack & 01;
+       u.u_procp->p_sigmask = scp->sc_mask &~ sigcantmask;
+       frame = (struct frame *) u.u_ar0;
+       frame->f_regs[SP] = scp->sc_sp;
+       frame->f_regs[A6] = scp->sc_fp;
+       frame->f_pc = scp->sc_pc;
+       frame->f_sr = scp->sc_ps;
+       /*
+        * Grab pointer to hardware state information.
+        * If zero, the user is probably doing a longjmp.
+        */
+       if ((rf = scp->sc_ap) == 0)
+               return;
+       /*
+        * See if there is anything to do before we go to the
+        * expense of copying in close to 1/2K of data
+        */
+       flags = fuword((caddr_t)rf);
+#ifdef DEBUG
+       if (sigdebug & SDB_FOLLOW)
+               printf("sigreturn: pid %d, sc_ap %x, flags %x\n",
+                      u.u_procp->p_pid, rf, flags);
+#endif
+       if (flags == 0 || copyin((caddr_t)rf, (caddr_t)&tstate, sizeof tstate))
+               return;
+#ifdef DEBUG
+       if ((sigdebug & SDB_KSTACK) && u.u_procp->p_pid == sigpid)
+               printf("sigreturn: pid %d, ssp %x usp %x scp %x ft %d\n",
+                      u.u_procp->p_pid, &flags, scp->sc_sp,
+                      ((struct a *)(u.u_ap))->sigcntxp,
+                      (flags&SS_RTEFRAME) ? tstate.ss_frame.f_format : -1);
+#endif
+       /*
+        * Restore most of the users registers except for A6 and SP
+        * which were handled above.
+        */
+       if (flags & SS_USERREGS)
+               bcopy((caddr_t)tstate.ss_frame.f_regs,
+                     (caddr_t)frame->f_regs, sizeof(frame->f_regs)-2*NBPW);
+       /*
+        * Restore long stack frames.  Note that we do not copy
+        * back the saved SR or PC, they were picked up above from
+        * the sigcontext structure.
+        */
+       if (flags & SS_RTEFRAME) {
+               register int sz;
+               
+               /* grab frame type and validate */
+               sz = tstate.ss_frame.f_format;
+               if (sz == FMT9)
+                       sz = FMT9SIZE;
+               else if (sz == FMTA)
+                       sz = FMTASIZE;
+               else if (sz == FMTB) {
+                       sz = FMTBSIZE;
+                       /* no k-stack adjustment necessary */
+                       frame->f_stackadj = 0;
+               } else {
+                       u.u_error = EINVAL;
+                       return;
+               }
+               frame->f_format = tstate.ss_frame.f_format;
+               frame->f_vector = tstate.ss_frame.f_vector;
+               bcopy((caddr_t)&tstate.ss_frame.F_u, (caddr_t)&frame->F_u, sz);
+#ifdef DEBUG
+               if (sigdebug & SDB_FOLLOW)
+                       printf("sigreturn: copy in %d of frame type %d\n",
+                              sz, tstate.ss_frame.f_format);
+#endif
+       }
+#ifdef FPCOPROC
+       /*
+        * Finally we restore the original FP context
+        */
+       if (flags & SS_FPSTATE)
+               m68881_restore(&tstate.ss_fpstate);
+#ifdef DEBUG
+       if ((sigdebug & SDB_FPSTATE) && *(char *)&tstate.ss_fpstate)
+               printf("sigreturn: pid %d, copied in FP state (%x) at %x\n",
+                      u.u_procp->p_pid, *(u_int *)&tstate.ss_fpstate,
+                      &tstate.ss_fpstate);
+#endif
+#endif
+#ifdef DEBUG
+       if ((sigdebug & SDB_FOLLOW) ||
+           ((sigdebug & SDB_KSTACK) && u.u_procp->p_pid == sigpid))
+               printf("sigreturn: pid %d, returns\n", u.u_procp->p_pid);
+#endif
+}
+
+int    waittime = -1;
+
+boot(howto)
+       register int howto;
+{
+       /* take a snap shot before clobbering any registers */
+       resume((u_int)pcbb(u.u_procp));
+
+       boothowto = howto;
+       if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
+               register struct buf *bp;
+               int iter, nbusy;
+
+               waittime = 0;
+               (void) spl0();
+               printf("syncing disks... ");
+               /*
+                * Release vnodes held by texts before sync.
+                */
+               if (panicstr == 0)
+                       xumount(NULL);
+#include "fd.h"
+#if NFD > 0
+               fdshutdown();
+#endif
+               sync((struct sigcontext *)0);
+
+               for (iter = 0; iter < 20; iter++) {
+                       nbusy = 0;
+                       for (bp = &buf[nbuf]; --bp >= buf; )
+                               if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
+                                       nbusy++;
+                       if (nbusy == 0)
+                               break;
+                       printf("%d ", nbusy);
+                       DELAY(40000 * iter);
+               }
+               if (nbusy)
+                       printf("giving up\n");
+               else
+                       printf("done\n");
+               /*
+                * If we've been adjusting the clock, the todr
+                * will be out of synch; adjust it now.
+                */
+               resettodr();
+       }
+       splhigh();                      /* extreme priority */
+       if (howto&RB_HALT) {
+               printf("halted\n\n");
+               asm("   stop    #0x2700");
+       } else {
+               if (howto & RB_DUMP)
+                       dumpsys();
+               doboot();
+               /*NOTREACHED*/
+       }
+       /*NOTREACHED*/
+}
+
+int    dumpmag = 0x8fca0101;   /* magic number for savecore */
+int    dumpsize = 0;           /* also for savecore */
+
+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()
+{
+
+       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 ((*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("succeeded\n");
+               break;
+       }
+}
+
+/*
+ * Return the best possible estimate of the time in the timeval
+ * to which tvp points.  We do this by returning the current time
+ * plus the amount of time since the last clock interrupt (clock.c:clkread).
+ *
+ * Check that this time is no less than any previously-reported time,
+ * which could happen around the time of a clock adjustment.  Just for fun,
+ * we guarantee that the time will be greater than the value obtained by a
+ * previous call.
+ */
+microtime(tvp)
+       register struct timeval *tvp;
+{
+       int s = splhigh();
+       static struct timeval lasttime;
+
+       *tvp = time;
+       tvp->tv_usec += clkread();
+       while (tvp->tv_usec > 1000000) {
+               tvp->tv_sec++;
+               tvp->tv_usec -= 1000000;
+       }
+       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()
+{
+       parityenable();
+}
+
+straytrap(addr)
+       register int addr;
+{
+       printf("stray trap, addr 0x%x\n", addr);
+}
+
+int    *nofault;
+
+badaddr(addr)
+       register caddr_t addr;
+{
+       register int i;
+       label_t faultbuf;
+
+#ifdef lint
+       i = *addr; if (i) return(0);
+#endif
+       nofault = (int *) &faultbuf;
+       if (setjmp((label_t *)nofault)) {
+               nofault = (int *) 0;
+               return(1);
+       }
+       i = *(volatile short *)addr;
+       nofault = (int *) 0;
+       return(0);
+}
+
+badbaddr(addr)
+       register caddr_t addr;
+{
+       register int i;
+       label_t faultbuf;
+
+#ifdef lint
+       i = *addr; if (i) return(0);
+#endif
+       nofault = (int *) &faultbuf;
+       if (setjmp((label_t *)nofault)) {
+               nofault = (int *) 0;
+               return(1);
+       }
+       i = *(volatile char *)addr;
+       nofault = (int *) 0;
+       return(0);
+}
+
+netintr()
+{
+#ifdef INET
+       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
+}
+
+#ifdef DEBUG
+int panicbutton = 1;   /* non-zero if panic buttons are enabled */
+int crashandburn = 0;
+int candbdelay = 50;   /* give em half a second */
+
+candbtimer()
+{
+       crashandburn = 0;
+}
+#endif
+
+intrhand(sr)
+       int sr;
+{
+       register struct isr *isr;
+       register int found = 0;
+       register int ipl;
+       extern struct isr isrqueue[];
+
+       ipl = (sr >> 8) & 7;
+       switch (ipl) {
+
+       case 3:
+       case 4:
+       case 5:
+               ipl = ISRIPL(ipl);
+               isr = isrqueue[ipl].isr_forw;
+               for (; isr != &isrqueue[ipl]; isr = isr->isr_forw) {
+                       if ((isr->isr_intr)(isr->isr_arg)) {
+                               found++;
+                               break;
+                       }
+               }
+               if (found == 0)
+                       printf("stray interrupt, sr 0x%x\n", sr);
+               break;
+
+       case 0:
+       case 1:
+       case 2:
+       case 6:
+       case 7:
+               printf("intrhand: unexpected sr 0x%x\n", sr);
+               break;
+       }
+}
+
+/*
+ * Level 7 interrupts can be caused by the keyboard or parity errors.
+ */
+nmihand(frame)
+       struct frame frame;
+{
+       if (kbdnmi()) {
+#ifdef DEBUG
+               printf("Got a keyboard NMI\n");
+               if (panicbutton && !panicstr) {
+                       if (crashandburn) {
+#ifdef BELLS
+                               panicstr = "Yow!!";
+#endif
+                               panic("forced crash");
+                       }
+                       crashandburn++;
+                       timeout(candbtimer, (caddr_t)0, candbdelay);
+               }
+#endif
+               return;
+       }
+       if (parityerror(&frame))
+               return;
+       /* panic?? */
+       printf("unexpected level 7 interrupt ignored\n");
+}
+
+/*
+ * Parity error section.  Contains magic.
+ */
+#define PARREG         ((volatile short *)IOV(0x5B0000))
+static int gotparmem = 0;
+#ifdef DEBUG
+int ignorekperr = 0;   /* ignore kernel parity errors */
+#endif
+
+/*
+ * Enable parity detection
+ */
+parityenable()
+{
+       label_t faultbuf;
+
+       nofault = (int *) &faultbuf;
+       if (setjmp((label_t *)nofault)) {
+               nofault = (int *) 0;
+#ifdef DEBUG
+               printf("No parity memory\n");
+#endif
+               return;
+       }
+       *PARREG = 1;
+       nofault = (int *) 0;
+       gotparmem = 1;
+#ifdef DEBUG
+       printf("Parity detection enabled\n");
+#endif
+}
+
+/*
+ * Determine if level 7 interrupt was caused by a parity error
+ * and deal with it if it was.  Returns 1 if it was a parity error.
+ */
+parityerror(fp)
+       struct frame *fp;
+{
+       if (!gotparmem)
+               return(0);
+       *PARREG = 0;
+       DELAY(10);
+       *PARREG = 1;
+       if (panicstr) {
+               printf("parity error after panic ignored\n");
+               return(1);
+       }
+       if (!findparerror())
+               printf("WARNING: transient parity error ignored\n");
+       else if (USERMODE(fp->f_sr)) {
+               printf("pid %d: parity error\n", u.u_procp->p_pid);
+               uprintf("sorry, pid %d killed due to memory parity error\n",
+                       u.u_procp->p_pid);
+               psignal(u.u_procp, SIGKILL);
+#ifdef DEBUG
+       } else if (ignorekperr) {
+               printf("WARNING: kernel parity error ignored\n");
+#endif
+       } else {
+               regdump(fp->f_regs, 128);
+               panic("kernel parity error");
+       }
+       return(1);
+}
+
+/*
+ * Yuk!  There has got to be a better way to do this!
+ * Searching all of memory with interrupts blocked can lead to disaster.
+ */
+findparerror()
+{
+       static label_t parcatch;
+       static int looking = 0;
+       volatile struct pte opte;
+       volatile int pg, o, s;
+       register volatile int *ip;
+       register int i;
+       int found;
+
+#ifdef lint
+       ip = &found;
+       i = o = pg = 0; if (i) return(0);
+#endif
+       /*
+        * If looking is true we are searching for a known parity error
+        * and it has just occured.  All we do is return to the higher
+        * level invocation.
+        */
+       if (looking)
+               longjmp(&parcatch);
+       s = splhigh();
+       /*
+        * If setjmp returns true, the parity error we were searching
+        * for has just occured (longjmp above) at the current pg+o
+        */
+       if (setjmp(&parcatch)) {
+               printf("Parity error at 0x%x\n", ctob(pg)|o);
+               found = 1;
+               goto done;
+       }
+       /*
+        * If we get here, a parity error has occured for the first time
+        * and we need to find it.  We turn off any external caches and
+        * loop thru memory, testing every longword til a fault occurs and
+        * we regain control at setjmp above.  Note that because of the
+        * setjmp, pg and o need to be volatile or their values will be lost.
+        */
+       looking = 1;
+       ecacheoff();
+       opte = mmap[0];
+       for (pg = btoc(lowram); pg < btoc(lowram)+physmem; pg++) {
+               *(u_int *)mmap = PG_RO|PG_CI|PG_V;
+               mmap[0].pg_pfnum = pg;
+               TBIS(vmmap);
+               ip = (int *)vmmap;
+               for (o = 0; o < NBPG; o += sizeof(int))
+                       i = *ip++;
+       }
+       /*
+        * Getting here implies no fault was found.  Should never happen.
+        */
+       printf("Couldn't locate parity error\n");
+       found = 0;
+done:
+       looking = 0;
+       mmap[0] = opte;
+       TBIS(vmmap);
+       ecacheon();
+       splx(s);
+       return(found);
+}
+
+regdump(rp, sbytes)
+  int *rp; /* must not be register */
+  int sbytes;
+{
+       static int doingdump = 0;
+       register int i;
+       int s;
+       extern char *hexstr();
+
+       if (doingdump)
+               return;
+       s = splhigh();
+       doingdump = 1;
+       printf("pid = %d, pc = %s, ", u.u_procp->p_pid, hexstr(rp[PC], 8));
+       printf("ps = %s, ", hexstr(rp[PS], 4));
+       printf("sfc = %s, ", hexstr(getsfc(), 4));
+       printf("dfc = %s\n", hexstr(getdfc(), 4));
+       printf("p0 = %x@%s, ",
+              u.u_pcb.pcb_p0lr, hexstr((int)u.u_pcb.pcb_p0br, 8));
+       printf("p1 = %x@%s\n\n",
+              u.u_pcb.pcb_p1lr, hexstr((int)u.u_pcb.pcb_p1br, 8));
+       printf("Registers:\n     ");
+       for (i = 0; i < 8; i++)
+               printf("        %d", i);
+       printf("\ndreg:");
+       for (i = 0; i < 8; i++)
+               printf(" %s", hexstr(rp[i], 8));
+       printf("\nareg:");
+       for (i = 0; i < 8; i++)
+               printf(" %s", hexstr(rp[i+8], 8));
+       if (sbytes > 0) {
+               if (rp[PS] & PSL_S) {
+                       printf("\n\nKernel stack (%s):",
+                              hexstr((int)(((int *)&rp)-1), 8));
+                       dumpmem(((int *)&rp)-1, sbytes, 0);
+               } else {
+                       printf("\n\nUser stack (%s):", hexstr(rp[SP], 8));
+                       dumpmem((int *)rp[SP], sbytes, 1);
+               }
+       }
+       doingdump = 0;
+       splx(s);
+}
+
+#define KSADDR ((int *)&(((char *)&u)[(UPAGES-1)*NBPG]))
+
+dumpmem(ptr, sz, ustack)
+ register int *ptr;
+ int sz;
+{
+       register int i, val;
+       extern char *hexstr();
+
+       for (i = 0; i < sz; i++) {
+               if ((i & 7) == 0)
+                       printf("\n%s: ", hexstr((int)ptr, 6));
+               else
+                       printf(" ");
+               if (ustack == 1) {
+                       if ((val = fuword(ptr++)) == -1)
+                               break;
+               } else {
+                       if (ustack == 0 && (ptr < KSADDR || ptr > KSADDR+(NBPG/4-1)))
+                               break;
+                       val = *ptr++;
+               }
+               printf("%s", hexstr(val, 8));
+       }
+       printf("\n");
+}
+
+char *
+hexstr(val, len)
+ register int val;
+{
+       static char nbuf[9];
+       register int x, i;
+
+       if (len > 8)
+               return("");
+       nbuf[len] = '\0';
+       for (i = len-1; i >= 0; --i) {
+               x = val & 0xF;
+               if (x > 9)
+                       nbuf[i] = x - 10 + 'A';
+               else
+                       nbuf[i] = x + '0';
+               val >>= 4;
+       }
+       return(nbuf);
+}
diff --git a/usr/src/sys/hp300/hp300/mem.c b/usr/src/sys/hp300/hp300/mem.c
new file mode 100644 (file)
index 0000000..63fd7cd
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: mem.c 1.13 89/10/08$
+ *
+ *     @(#)mem.c       7.1 (Berkeley) %G%
+ */
+
+/*
+ * Memory special file
+ */
+
+#include "pte.h"
+
+#include "param.h"
+#include "user.h"
+#include "conf.h"
+#include "buf.h"
+#include "systm.h"
+#include "vm.h"
+#include "cmap.h"
+#include "uio.h"
+#include "malloc.h"
+
+#include "cpu.h"
+
+/*ARGSUSED*/
+mmrw(dev, uio, flags)
+       dev_t dev;
+       struct uio *uio;
+       int flags;
+{
+       register int o;
+       register u_int c, v;
+       register struct iovec *iov;
+       int error = 0;
+       caddr_t zbuf = NULL;
+       extern u_int lowram;
+
+       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;
+#ifndef DEBUG
+                       /* allow reads only in RAM (except for DEBUG) */
+                       if (v >= 0xFFFFFFFC || v < lowram)
+                               goto fault;
+#endif
+                       *(int *)mmap = (v & PG_FRAME) | PG_CI | PG_V |
+                               (uio->uio_rw == UIO_READ ? PG_RO : PG_RW);
+                       TBIS(vmmap);
+                       o = (int)uio->uio_offset & PGOFSET;
+                       c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET));
+                       c = MIN(c, (u_int)(NBPG - o));
+                       c = MIN(c, (u_int)iov->iov_len);
+                       error = uiomove((caddr_t)&vmmap[o], (int)c, uio);
+                       continue;
+
+/* minor device 1 is kernel memory */
+               case 1:
+                       c = iov->iov_len;
+                       if (!kernacc((caddr_t)uio->uio_offset, c,
+                           uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
+                               goto fault;
+                       error = uiomove((caddr_t)uio->uio_offset, (int)c, uio);
+                       continue;
+
+/* minor device 2 is EOF/RATHOLE */
+               case 2:
+                       if (uio->uio_rw == UIO_READ)
+                               return (0);
+                       c = iov->iov_len;
+                       break;
+
+/* 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 (zbuf == NULL) {
+                               zbuf = (caddr_t)
+                                   malloc(CLBYTES, M_TEMP, M_WAITOK);
+                               bzero(zbuf, CLBYTES);
+                       }
+                       c = MIN(iov->iov_len, CLBYTES);
+                       error = uiomove(zbuf, (int)c, uio);
+                       continue;
+
+               default:
+                       return (ENXIO);
+               }
+               if (error)
+                       break;
+               iov->iov_base += c;
+               iov->iov_len -= c;
+               uio->uio_offset += c;
+               uio->uio_resid -= c;
+       }
+       if (zbuf)
+               free(zbuf, M_TEMP);
+       return (error);
+fault:
+       return (EFAULT);
+}
diff --git a/usr/src/sys/hp300/hp300/ns_cksum.c b/usr/src/sys/hp300/hp300/ns_cksum.c
new file mode 100644 (file)
index 0000000..44891f1
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 1985, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)ns_cksum.c  7.1 (Berkeley) %G%
+ */
+
+#include "types.h"
+#include "mbuf.h"
+
+
+/*
+ * Checksum routine for Network Systems Protocol Packets (SUN Version).
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ */
+
+u_short
+ns_cksum(m, len)
+       register struct mbuf *m;
+       register int len;
+{
+       register u_short *w;            /* on sun, known to be a4 */
+       register int sum = 0;           /* on sun, known to be d6 */
+       register int low = 0;           /* on sun, known to be d5 */
+       register int mlen = low;        /* want 0, shuts lint up about low */
+       register int zero = mlen;       /* handy for fold */
+       register int sumH = mlen;       /* handy for fold2 */
+#undef ADD
+#define ADD asm("addw a4@+,d6; addxw d3,d6; rolw #1,d6")
+#define FOLD asm("movw d6,d5; swap d6; addw d6,d5; addxw d3,d5;  movl d5,d6");
+#define ADDH asm("movb a4@+,d5; addl d5,d2; addl d2,d2")
+#define ADDL asm("movb a4@+,d5; addl d5,d6; addl d6,d6")
+#define FOLDH asm("movw d2,d5; swap d2; addw d2,d5; addxw d3,d5; movl d5,d2");
+
+       for (;;) {
+               /*
+                * Each trip around loop adds in
+                * word from one mbuf segment.
+                */
+               w = mtod(m, u_short *);
+               if (mlen == -1) {
+                       /*
+                        * There is a byte left from the last segment;
+                        * ones-complement add it into the checksum.
+                        */
+                       low = *(u_char *)w;
+                       asm("addw d5,d6; addxw d3,d6; rolw #1,d6");
+                       w = (u_short *)((char *)w + 1);
+                       mlen = m->m_len - 1;
+                       len--;
+               } else
+                       mlen = m->m_len;
+               m = m->m_next;
+               if (len < mlen)
+                       mlen = len;
+               len -= mlen;
+               /*
+                *
+                * We can do a 16 bit ones complement sum using
+                * 32 bit arithmetic registers for adding,
+                * with carries from the low added
+                * into the high (by normal carry-chaining)
+                * so long as we fold back before 16 carries have occured.
+                *
+                */
+#ifndef OKTOODDWORD
+               if (((int) w & 1)==0) goto easycase;
+               while ((mlen -= 32) >= 0) {
+                       ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
+                       ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
+                       FOLD;
+                       FOLDH;
+                       ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
+                       ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
+                       FOLD;
+                       FOLDH;
+               }
+               mlen += 32;
+               while ((mlen -= 8) >= 0) {
+                       ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
+                       FOLD;
+                       FOLDH;
+               }
+               mlen += 8;
+               while ((mlen -= 2) >= 0) {
+                       ADDH; ADDL;
+               }
+               FOLDH;
+               sum = (sumH << 8) + sum;
+               FOLD;
+               sumH = 0;
+               goto commoncase;
+easycase:
+#endif
+               /* In this sequence there will be no carries out of
+                * the lower 16 bits.
+                */
+               while ((mlen -= 32) >= 0) {
+                       ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
+                       ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
+               }
+               mlen += 32;
+               while ((mlen -= 8) >= 0) {
+                       ADD; ADD; ADD; ADD;
+               }
+               mlen += 8;
+               while ((mlen -= 2) >= 0) {
+                       ADD;
+               }
+commoncase:
+               if (mlen == -1) {
+                       /*sum += *(u_char *)w << 8; FOLD*/
+                       low = *(u_char *)w << 8;
+                       asm("addw d5,d6; addxw d3,d6");
+               }
+               if (len == 0) 
+                       break;
+               /*
+                * Locate the next block with some data.
+                * If there is a word split across a boundary we
+                * will wrap to the top with mlen == -1 and
+                * then add it in shifted appropriately.
+                */
+               for (;;) {
+                       if (m == 0) {
+                               printf("idpcksum: out of data\n");
+                               goto done;
+                       }
+                       if (m->m_len)
+                               break;
+                       m = m->m_next;
+               }
+       }
+done:
+       /*
+        * sum has already been kept to low sixteen bits.
+        * just examine result and exit.
+        */
+       
+       if(sum==0xffff) sum = 0;
+       return (sum);
+}
diff --git a/usr/src/sys/hp300/hp300/oc_cksum.s b/usr/src/sys/hp300/hp300/oc_cksum.s
new file mode 100644 (file)
index 0000000..df1d15d
--- /dev/null
@@ -0,0 +1,161 @@
+| Copyright (c) 1988 Regents of the University of California.
+| All rights reserved.
+|
+| %sccs.include.redist.gas%
+|
+|      @(#)oc_cksum.s  7.1 (Berkeley) %G%
+|
+|
+| oc_cksum: ones complement 16 bit checksum for MC68020.
+|
+| oc_cksum (buffer, count, strtval)
+|
+| Do a 16 bit one's complement sum of 'count' bytes from 'buffer'.
+| 'strtval' is the starting value of the sum (usually zero).
+|
+| It simplifies life in in_cksum if strtval can be >= 2^16.
+| This routine will work as long as strtval is < 2^31.
+|
+| Performance
+| -----------
+| This routine is intended for MC 68020s but should also work
+| for 68030s.  It (deliberately) doesn't worry about the alignment
+| of the buffer so will only work on a 68010 if the buffer is
+| aligned on an even address.  (Also, a routine written to use
+| 68010 "loop mode" would almost certainly be faster than this
+| code on a 68010).
+|
+| We don't worry about alignment because this routine is frequently
+| called with small counts: 20 bytes for IP header checksums and 40
+| bytes for TCP ack checksums.  For these small counts, testing for
+| bad alignment adds ~10% to the per-call cost.  Since, by the nature
+| of the kernel's allocator, the data we're called with is almost
+| always longword aligned, there is no benefit to this added cost
+| and we're better off letting the loop take a big performance hit
+| in the rare cases where we're handed an unaligned buffer.
+|
+| Loop unrolling constants of 2, 4, 8, 16, 32 and 64 times were
+| tested on random data on four different types of processors (see
+| list below -- 64 was the largest unrolling because anything more
+| overflows the 68020 Icache).  On all the processors, the
+| throughput asymptote was located between 8 and 16 (closer to 8).
+| However, 16 was substantially better than 8 for small counts.
+| (It's clear why this happens for a count of 40: unroll-8 pays a
+| loop branch cost and unroll-16 doesn't.  But the tests also showed
+| that 16 was better than 8 for a count of 20.  It's not obvious to
+| me why.)  So, since 16 was good for both large and small counts,
+| the loop below is unrolled 16 times.
+| 
+| The processors tested and their average time to checksum 1024 bytes
+| of random data were:
+|      Sun 3/50 (15MHz)        190 us/KB
+|      Sun 3/180 (16.6MHz)     175 us/KB
+|      Sun 3/60 (20MHz)        134 us/KB
+|      Sun 3/280 (25MHz)        95 us/KB
+| 
+| The cost of calling this routine was typically 10% of the per-
+| kilobyte cost.  E.g., checksumming zero bytes on a 3/60 cost 9us
+| and each additional byte cost 125ns.  With the high fixed cost,
+| it would clearly be a gain to "inline" this routine -- the
+| subroutine call adds 400% overhead to an IP header checksum.
+| However, in absolute terms, inlining would only gain 10us per
+| packet -- a 1% effect for a 1ms ethernet packet.  This is not
+| enough gain to be worth the effort.
+
+       .data
+       .asciz  "@(#)$Header: oc_cksum.s,v 1.1 89/08/23 12:53:20 mike Exp $"
+       .even
+       .text
+
+       .globl  _oc_cksum
+_oc_cksum:
+       movl    sp@(4),a0       | get buffer ptr
+       movl    sp@(8),d1       | get byte count
+       movl    sp@(12),d0      | get starting value
+       movl    d2,sp@-         | free a reg
+
+       | test for possible 1, 2 or 3 bytes of excess at end
+       | of buffer.  The usual case is no excess (the usual
+       | case is header checksums) so we give that the faster
+       | 'not taken' leg of the compare.  (We do the excess
+       | first because we're about the trash the low order
+       | bits of the count in d1.)
+
+       btst    #0,d1
+       jne     L5              | if one or three bytes excess
+       btst    #1,d1
+       jne     L7              | if two bytes excess
+L1:
+       movl    d1,d2
+       lsrl    #6,d1           | make cnt into # of 64 byte chunks
+       andl    #0x3c,d2        | then find fractions of a chunk
+       negl    d2
+       andb    #0xf,cc         | clear X
+       jmp     pc@(L3-.-2:b,d2)
+L2:
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+       movl    a0@+,d2
+       addxl   d2,d0
+L3:
+       dbra    d1,L2           | (NB- dbra doesn't affect X)
+
+       movl    d0,d1           | fold 32 bit sum to 16 bits
+       swap    d1              | (NB- swap doesn't affect X)
+       addxw   d1,d0
+       jcc     L4
+       addw    #1,d0
+L4:
+       andl    #0xffff,d0
+       movl    sp@+,d2
+       rts
+
+L5:    | deal with 1 or 3 excess bytes at the end of the buffer.
+       btst    #1,d1
+       jeq     L6              | if 1 excess
+
+       | 3 bytes excess
+       clrl    d2
+       movw    a0@(-3,d1:l),d2 | add in last full word then drop
+       addl    d2,d0           |  through to pick up last byte
+
+L6:    | 1 byte excess
+       clrl    d2
+       movb    a0@(-1,d1:l),d2
+       lsll    #8,d2
+       addl    d2,d0
+       jra     L1
+
+L7:    | 2 bytes excess
+       clrl    d2
+       movw    a0@(-2,d1:l),d2
+       addl    d2,d0
+       jra     L1
diff --git a/usr/src/sys/hp300/hp300/pte.h b/usr/src/sys/hp300/hp300/pte.h
new file mode 100644 (file)
index 0000000..ef9d8a1
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: pte.h 1.11 89/09/03$
+ *
+ *     @(#)pte.h       7.1 (Berkeley) %G%
+ */
+
+/*
+ * HP300 page table entry
+ *
+ * There are two major kinds of pte's: those which have ever existed (and are
+ * thus either now in core or on the swap device), and those which have
+ * never existed, but which will be filled on demand at first reference.
+ * There is a structure describing each.  There is also an ancillary
+ * structure used in page clustering.
+ */
+
+#ifndef LOCORE
+struct ste
+{
+unsigned int   sg_pfnum:20,            /* page table frame number */
+               :8,                     /* reserved at 0 */
+               :1,                     /* reserved at 1 */
+               sg_prot:1,              /* write protect bit */
+               sg_v:2;                 /* valid bits */
+};
+
+struct pte
+{
+unsigned int   pg_pfnum:20,            /* page frame number or 0 */
+               :3,
+               pg_fod:1,               /* is fill on demand (=0) */
+               :1,                     /* reserved at zero */
+               pg_ci:1,                /* cache inhibit bit */
+               :1,                     /* reserved at zero */
+               pg_m:1,                 /* hardware modified (dirty) bit */
+               pg_u:1,                 /* hardware used (reference) bit */
+               pg_prot:1,              /* write protect bit */
+               pg_v:2;                 /* valid bit */
+};
+
+/* not used */
+struct hpte
+{
+unsigned int   pg_pfnum:20,
+               pg_high:12;             /* special for clustering */
+};
+
+struct fpte
+{
+unsigned int   pg_blkno:22,            /* file system block number */
+               pg_fileno:1,            /* file mapped from or TEXT or ZERO */
+               pg_fod:1,               /* is fill on demand (=1) */
+               :6,
+               pg_v:2;
+};
+#endif
+
+#define        SG_V            0x00000002
+#define        SG_NV           0x00000000
+#define        SG_PROT         0x00000004
+#define        SG_RO           0x00000004
+#define        SG_RW           0x00000000
+#define        SG_FRAME        0xfffff000
+#define        SG_IMASK        0xffc00000
+#define        SG_PMASK        0x003ff000
+#define        SG_ISHIFT       22
+#define        SG_PSHIFT       12
+
+#define        PG_V            0x00000001
+#define        PG_NV           0x00000000
+#define        PG_PROT         0x00000004
+#define        PG_U            0x00000008
+#define        PG_M            0x00000010
+#define        PG_FOD          0x00000100
+#define        PG_RO           0x00000004
+#define        PG_RW           0x00000000
+#define        PG_FRAME        0xfffff000
+#define        PG_CI           0x00000040
+#define        PG_PFNUM(x)     (((x) & PG_FRAME) >> PGSHIFT)
+
+/*
+ * Pseudo protections.
+ * Note that PG_URKW is not defined intuitively, but it is currently only
+ * used in vgetu() to initialize the u-area PTEs in the process address
+ * space.  Since the kernel never accesses the u-area thru these we are ok.
+ */
+#define        PG_KW           PG_RW
+#define        PG_URKR         PG_RO
+#define        PG_URKW         PG_RO
+#define        PG_UW           PG_RW
+
+#define        PG_FZERO        0
+#define        PG_FTEXT        1
+#define        PG_FMAX         (PG_FTEXT)
+
+/*
+ * Pte related macros
+ */
+#define        dirty(pte)      ((pte)->pg_m)
+
+/*
+ * Kernel virtual address to page table entry and to physical address.
+ */
+#define        kvtopte(va) (&Sysmap[((unsigned)(va) &~ KERNBASE) >> PGSHIFT])
+#define        ptetokv(pt) ((((struct pte *)(pt) - Sysmap) << PGSHIFT) | KERNBASE)
+#define        kvtophys(x) ((kvtopte(x)->pg_pfnum << PGSHIFT) | ((int)(x) & PGOFSET))
+
+#if defined(KERNEL) && !defined(LOCORE)
+/* utilities defined in locore.s */
+extern struct pte Sysmap[];
+extern struct pte Usrptmap[];
+extern struct pte usrpt[];
+extern struct pte Swapmap[];
+extern struct pte Forkmap[];
+extern struct pte Xswapmap[];
+extern struct pte Xswap2map[];
+extern struct pte Pushmap[];
+extern struct pte Vfmap[];
+extern struct pte mmap[];
+extern struct pte msgbufmap[];
+extern struct pte kmempt[], ekmempt[];
+extern struct ste Sysseg[];
+#endif /* defined(KERNEL) && !defined(LOCORE) */
diff --git a/usr/src/sys/hp300/hp300/swapgeneric.c b/usr/src/sys/hp300/hp300/swapgeneric.c
new file mode 100644 (file)
index 0000000..277ea3e
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)swapgeneric.c       7.1 (Berkeley) %G%
+ */
+
+#include "pte.h"
+
+#include "param.h"
+#include "conf.h"
+#include "buf.h"
+#include "vm.h"
+#include "systm.h"
+#include "reboot.h"
+
+#include "../hpdev/device.h"
+
+/*
+ * Generic configuration;  all in one
+ */
+dev_t  rootdev = NODEV;
+dev_t  argdev = NODEV;
+dev_t  dumpdev = NODEV;
+int    nswap;
+struct swdevt swdevt[] = {
+       { -1,   1,      0 },
+       { 0,    0,      0 },
+};
+long   dumplo;
+int    dmmin, dmmax, dmtext;
+
+extern struct driver rddriver;
+extern struct driver sddriver;
+extern struct hp_ctlr hp_cinit[];
+extern struct hp_device hp_dinit[];
+
+struct genericconf {
+       caddr_t gc_driver;
+       char    *gc_name;
+       dev_t   gc_root;
+} genericconf[] = {
+       { (caddr_t)&rddriver,   "rd",   makedev(2, 0),  },
+       { (caddr_t)&sddriver,   "sd",   makedev(4, 0),  },
+       { 0 },
+};
+
+setconf()
+{
+       register struct hp_ctlr *hc;
+       register struct hp_device *hd;
+       register struct genericconf *gc;
+       register char *cp;
+       int unit, swaponroot = 0;
+
+       if (rootdev != NODEV)
+               goto doswap;
+       unit = 0;
+       if (boothowto & RB_ASKNAME) {
+               char name[128];
+retry:
+               printf("root device? ");
+               gets(name);
+               for (gc = genericconf; gc->gc_driver; gc++)
+                       if (gc->gc_name[0] == name[0] &&
+                           gc->gc_name[1] == name[1])
+                               goto gotit;
+               printf("use one of:");
+               for (gc = genericconf; gc->gc_driver; gc++)
+                       printf(" %s%%d", gc->gc_name);
+               printf("\n");
+               goto retry;
+gotit:
+               if (*++cp < '0' || *cp > '9') {
+                       printf("bad/missing unit number\n");
+                       goto retry;
+               }
+               while (*cp >= '0' && *cp <= '9')
+                       unit = 10 * unit + *cp++ - '0';
+               if (*cp == '*')
+                       swaponroot++;
+               goto found;
+       }
+       for (gc = genericconf; gc->gc_driver; gc++) {
+               for (hd = hp_dinit; hd->hp_driver; hd++) {
+                       if (hd->hp_alive == 0)
+                               continue;
+                       if (hd->hp_unit == 0 && hd->hp_driver ==
+                           (struct driver *)gc->gc_driver) {
+                               printf("root on %s0\n", hd->hp_driver->d_name);
+                               goto found;
+                       }
+               }
+       }
+       printf("no suitable root\n");
+       asm("stop #0x2700");
+found:
+       gc->gc_root = makedev(major(gc->gc_root), unit*8);
+       rootdev = gc->gc_root;
+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 (;;) {
+               cnputc(c = cngetc());
+               switch (c) {
+               case '\n':
+               case '\r':
+                       *lp++ = '\0';
+                       return;
+               case '\b':
+               case '\177':
+                       if (lp > cp) {
+                               lp--;
+                               cnputc(' ');
+                               cnputc('\b');
+                       }
+                       continue;
+               case '#':
+                       lp--;
+                       if (lp < cp)
+                               lp = cp;
+                       continue;
+               case '@':
+               case 'u'&037:
+                       lp = cp;
+                       cnputc('\n');
+                       continue;
+               default:
+                       *lp++ = c;
+               }
+       }
+}
diff --git a/usr/src/sys/hp300/hp300/sys_machdep.c b/usr/src/sys/hp300/hp300/sys_machdep.c
new file mode 100644 (file)
index 0000000..7c9f78b
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)sys_machdep.c       7.1 (Berkeley) %G%
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "user.h"
+#include "ioctl.h"
+#include "file.h"
+#include "proc.h"
+#include "uio.h"
+#include "kernel.h"
+#include "mtio.h"
+#include "buf.h"
+#include "trace.h"
+
+#include "pte.h"
+
+#ifdef TRACE
+int    nvualarm;
+
+vtrace()
+{
+       register struct a {
+               int     request;
+               int     value;
+       } *uap;
+       int vdoualarm();
+
+       uap = (struct a *)u.u_ap;
+       switch (uap->request) {
+
+       case VTR_DISABLE:               /* disable a trace point */
+       case VTR_ENABLE:                /* enable a trace point */
+               if (uap->value < 0 || uap->value >= TR_NFLAGS)
+                       u.u_error = EINVAL;
+               else {
+                       u.u_r.r_val1 = traceflags[uap->value];
+                       traceflags[uap->value] = uap->request;
+               }
+               break;
+
+       case VTR_VALUE:         /* return a trace point setting */
+               if (uap->value < 0 || uap->value >= TR_NFLAGS)
+                       u.u_error = EINVAL;
+               else
+                       u.u_r.r_val1 = traceflags[uap->value];
+               break;
+
+       case VTR_UALARM:        /* set a real-time ualarm, less than 1 min */
+               if (uap->value <= 0 || uap->value > 60 * hz ||
+                   nvualarm > 5)
+                       u.u_error = EINVAL;
+               else {
+                       nvualarm++;
+                       timeout(vdoualarm, (caddr_t)u.u_procp->p_pid,
+                           uap->value);
+               }
+               break;
+
+       case VTR_STAMP:
+               trace(TR_STAMP, uap->value, u.u_procp->p_pid);
+               break;
+       }
+}
+
+vdoualarm(arg)
+       int arg;
+{
+       register struct proc *p;
+
+       p = pfind(arg);
+       if (p)
+               psignal(p, 16);
+       nvualarm--;
+}
+#endif
diff --git a/usr/src/sys/hp300/hp300/trap.c b/usr/src/sys/hp300/hp300/trap.c
new file mode 100644 (file)
index 0000000..dbc939f
--- /dev/null
@@ -0,0 +1,702 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: trap.c 1.28 89/09/25$
+ *
+ *     @(#)trap.c      7.1 (Berkeley) %G%
+ */
+
+#include "cpu.h"
+#include "psl.h"
+#include "reg.h"
+#include "pte.h"
+#include "mtpr.h"
+
+#include "param.h"
+#include "systm.h"
+#include "user.h"
+#include "proc.h"
+#include "seg.h"
+#include "trap.h"
+#include "acct.h"
+#include "kernel.h"
+#include "vm.h"
+#include "cmap.h"
+#include "syslog.h"
+#ifdef KTRACE
+#include "ktrace.h"
+#endif
+
+#ifdef HPUXCOMPAT
+#include "../hpux/hpux.h"
+#endif
+
+#define        USER    040             /* user-mode flag added to type */
+
+struct sysent  sysent[];
+int    nsysent;
+
+char   *trap_type[] = {
+       "Bus error",
+       "Address error",
+       "Illegal instruction",
+       "Zero divide",
+       "CHK instruction",
+       "TRAPV instruction",
+       "Privilege violation",
+       "Trace trap",
+       "MMU fault",
+       "SSIR trap",
+       "Format error",
+       "68881 exception",
+       "Coprocessor violation",
+       "Async system trap"
+};
+#define        TRAP_TYPES      (sizeof trap_type / sizeof trap_type[0])
+
+#ifdef DEBUG
+int mmudebug = 0;
+#endif
+
+/*
+ * Called from the trap handler when a processor trap occurs.
+ */
+/*ARGSUSED*/
+trap(type, code, v, frame)
+       int type;
+       unsigned code;
+       register unsigned v;
+       struct frame frame;
+{
+       register int i;
+       unsigned ucode = 0;
+       register struct proc *p = u.u_procp;
+       struct timeval syst;
+       unsigned ncode;
+
+       cnt.v_trap++;
+       syst = u.u_ru.ru_stime;
+       if (USERMODE(frame.f_sr)) {
+               type |= USER;
+               u.u_ar0 = frame.f_regs;
+       }
+       switch (type) {
+
+       default:
+dopanic:
+#ifdef KGDB
+               if (!panicstr && kgdb_trap(type, code, v, &frame))
+                       return;
+#endif
+               printf("trap type %d, code = %x, v = %x\n", type, code, v);
+               regdump(frame.f_regs, 128);
+               type &= ~USER;
+               if ((unsigned)type < TRAP_TYPES)
+                       panic(trap_type[type]);
+               panic("trap");
+
+       case T_BUSERR:          /* kernel bus error */
+               if (!u.u_pcb.pcb_onfault)
+                       goto dopanic;
+               /*
+                * If we have arranged to catch this fault in any of the
+                * copy to/from user space routines, set PC to return to
+                * indicated location and set flag informing buserror code
+                * that it may need to clean up stack frame.
+                */
+copyfault:
+               frame.f_pc = (int) u.u_pcb.pcb_onfault;
+               frame.f_stackadj = -1;
+               return;
+
+       case T_BUSERR+USER:     /* bus error */
+       case T_ADDRERR+USER:    /* address error */
+               i = SIGBUS;
+               break;
+
+#ifdef FPCOPROC
+       case T_COPERR:          /* kernel coprocessor violation */
+#endif
+       case T_FMTERR:          /* kernel format error */
+       /*
+        * The user has most likely trashed the RTE or FP state info
+        * in the stack frame of a signal handler.
+        */
+               printf("pid %d: kernel %s exception\n", u.u_procp->p_pid,
+                      type==T_COPERR ? "coprocessor" : "format");
+               u.u_signal[SIGILL] = SIG_DFL;
+               i = sigmask(SIGILL);
+               p->p_sigignore &= ~i;
+               p->p_sigcatch &= ~i;
+               p->p_sigmask &= ~i;
+               ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */
+               psignal(u.u_procp, SIGILL);
+               goto out;
+
+#ifdef FPCOPROC
+       case T_COPERR+USER:     /* user coprocessor violation */
+       /* What is a proper response here? */
+               ucode = 0;
+               i = SIGFPE;
+               break;
+
+       case T_FPERR+USER:              /* 68881 exceptions */
+       /*
+        * We pass along the 68881 status register which locore stashed
+        * in code for us.  Note that there is a possibility that the
+        * bit pattern of this register will conflict with one of the
+        * FPE_* codes defined in signal.h.  Fortunately for us, the
+        * only such codes we use are all in the range 1-7 and the low
+        * 3 bits of the status register are defined as 0 so there is
+        * no clash.
+        */
+               ucode = code;
+               i = SIGFPE;
+               break;
+#endif
+
+       case T_ILLINST+USER:    /* illegal instruction fault */
+#ifdef HPUXCOMPAT
+               if (u.u_procp->p_flag & SHPUX) {
+                       ucode = HPUX_ILL_ILLINST_TRAP;
+                       i = SIGILL;
+                       break;
+               }
+               /* fall through */
+#endif
+       case T_PRIVINST+USER:   /* privileged instruction fault */
+#ifdef HPUXCOMPAT
+               if (u.u_procp->p_flag & SHPUX)
+                       ucode = HPUX_ILL_PRIV_TRAP;
+               else
+#endif
+               ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */
+               i = SIGILL;
+               break;
+
+       case T_ZERODIV+USER:    /* Divide by zero */
+#ifdef HPUXCOMPAT
+               if (u.u_procp->p_flag & SHPUX)
+                       ucode = HPUX_FPE_INTDIV_TRAP;
+               else
+#endif
+               ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */
+               i = SIGFPE;
+               break;
+
+       case T_CHKINST+USER:    /* CHK instruction trap */
+#ifdef HPUXCOMPAT
+               if (u.u_procp->p_flag & SHPUX) {
+                       /* handled differently under hp-ux */
+                       i = SIGILL;
+                       ucode = HPUX_ILL_CHK_TRAP;
+                       break;
+               }
+#endif
+               ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */
+               i = SIGFPE;
+               break;
+
+       case T_TRAPVINST+USER:  /* TRAPV instruction trap */
+#ifdef HPUXCOMPAT
+               if (u.u_procp->p_flag & SHPUX) {
+                       /* handled differently under hp-ux */
+                       i = SIGILL;
+                       ucode = HPUX_ILL_TRAPV_TRAP;
+                       break;
+               }
+#endif
+               ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */
+               i = SIGFPE;
+               break;
+
+       /*
+        * XXX: Trace traps are a nightmare.
+        *
+        *      HP-UX uses trap #1 for breakpoints,
+        *      HPBSD uses trap #2,
+        *      SUN 3.x uses trap #15,
+        *      KGDB uses trap #15 (for kernel breakpoints).
+        *
+        * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
+        * SUN 3.x traps get passed through as T_TRAP15 and are not really
+        * supported yet.  KGDB traps are also passed through as T_TRAP15
+        * and are not used yet.
+        */
+       case T_TRACE:           /* kernel trace trap */
+       case T_TRAP15:          /* SUN (or KGDB) kernel trace trap */
+#ifdef KGDB
+               if (kgdb_trap(type, code, v, &frame))
+                       return;
+#endif
+               frame.f_sr &= ~PSL_T;
+               i = SIGTRAP;
+               break;
+
+       case T_TRACE+USER:      /* user trace trap */
+       case T_TRAP15+USER:     /* SUN user trace trap */
+#ifdef SUNCOMPAT
+               /*
+                * Trap #2 is used to signal a cache flush.
+                * Should we also flush data cache?
+                */
+               if (type == T_TRACE+USER && (p->p_flag & SSUN)) {
+                       ICIA();
+                       goto out;
+               }
+#endif
+               frame.f_sr &= ~PSL_T;
+               i = SIGTRAP;
+               break;
+
+       case T_AST:             /* system async trap, cannot happen */
+               goto dopanic;
+
+       case T_AST+USER:        /* user async trap */
+               astoff();
+               /*
+                * We check for software interrupts first.  This is because
+                * they are at a higher level than ASTs, and on a VAX would
+                * interrupt the AST.  We assume that if we are processing
+                * an AST that we must be at IPL0 so we don't bother to
+                * check.  Note that we ensure that we are at least at SIR
+                * IPL while processing the SIR.
+                */
+               spl1();
+               /* fall into... */
+
+       case T_SSIR:            /* software interrupt */
+       case T_SSIR+USER:
+               if (ssir & SIR_NET) {
+                       siroff(SIR_NET);
+                       cnt.v_soft++;
+                       netintr();
+               }
+               if (ssir & SIR_CLOCK) {
+                       siroff(SIR_CLOCK);
+                       cnt.v_soft++;
+                       softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
+               }
+               /*
+                * If this was not an AST trap, we are all done.
+                */
+               if (type != T_AST+USER) {
+                       cnt.v_trap--;
+                       return;
+               }
+               spl0();
+#ifndef PROFTIMER
+               if ((u.u_procp->p_flag&SOWEUPC) && u.u_prof.pr_scale) {
+                       addupc(frame.f_pc, &u.u_prof, 1);
+                       u.u_procp->p_flag &= ~SOWEUPC;
+               }
+#endif
+               goto out;
+
+       case T_MMUFLT:          /* kernel mode page fault */
+               /*
+                * Could be caused by a page fault in one of the copy to/from
+                * user space routines.  If so, we will have a catch address.
+                */
+               if (!u.u_pcb.pcb_onfault)
+                       goto dopanic;
+               /* fall into ... */
+
+       case T_MMUFLT+USER:     /* page fault */
+/*
+               printf("trap: T_MMUFLT pid %d, code %x, v %x, pc %x, ps %x\n",
+                      p->p_pid, code, v, frame.f_pc, frame.f_sr);
+*/
+               if (v >= USRSTACK) {
+                       if (type == T_MMUFLT)
+                               goto copyfault;
+                       i = SIGSEGV;
+                       break;
+               }
+               ncode = code >> 16;
+#if defined(HP330) || defined(HP360) || defined(HP370)
+               /*
+                * Crudely map PMMU faults into HP MMU faults.
+                */
+               if (mmutype != MMU_HP) {
+                       int ocode = ncode;
+                       ncode = 0;
+                       if (ocode & PMMU_WP)
+                               ncode |= MMU_WPF;
+                       else if (ocode & PMMU_INV) {
+                               if ((ocode & PMMU_LVLMASK) == 2)
+                                       ncode |= MMU_PF;
+                               else 
+                                       ncode |= MMU_PTF;
+                       }
+                       /*
+                        * RMW cycle, must load ATC by hand
+                        */
+                       else if ((code & (SSW_DF|SSW_RM)) == (SSW_DF|SSW_RM)) {
+#ifdef DEBUG
+                               log(LOG_WARNING,
+                                   "RMW fault at %x: MMUSR %x SSW %x\n",
+                                   v, ocode, code & 0xFFFF);
+#endif
+                               ploadw((caddr_t)v);
+                               return;
+                       }
+                       /*
+                        * Fault with no fault bits, should indicate bad
+                        * hardware but we see this on 340s using starbase
+                        * sometimes (faults accessing catseye registers)
+                        */
+                       else {
+                               log(LOG_WARNING,
+                                   "Bad PMMU fault at %x: MMUSR %x SSW %x\n",
+                                   v, ocode, code & 0xFFFF);
+                               return;
+                       }
+#ifdef DEBUG
+                       if (mmudebug && mmudebug == p->p_pid)
+                               printf("MMU %d: v%x, os%x, ns%x\n",
+                                      p->p_pid, v, ocode, ncode);
+#endif
+               }
+#endif
+#ifdef DEBUG
+               if ((ncode & (MMU_PTF|MMU_PF|MMU_WPF|MMU_FPE)) == 0) {
+                       printf("T_MMUFLT with no fault bits\n");
+                       goto dopanic;
+               }
+#endif
+               if (ncode & MMU_PTF) {
+#ifdef DEBUG
+                       /*
+                        * NOTE: we use a u_int instead of an ste since the
+                        * current compiler generates bogus code for some
+                        * bitfield operations (i.e. attempts to access last
+                        * word of a page as a longword causing fault).
+                        */
+                       extern struct ste *vtoste();
+                       u_int *ste = (u_int *)vtoste(p, v);
+
+                       if (*ste & SG_V) {
+                               if (ncode & MMU_WPF) {
+                                       printf("PTF|WPF...\n");
+                                       if (type == T_MMUFLT)
+                                               goto copyfault;
+                                       i = SIGBUS;
+                                       break;
+                               }
+                               printf("MMU_PTF with sg_v, ste@%x = %x\n",
+                                      ste, *ste);
+                               goto dopanic;
+                       }
+#endif
+#ifdef HPUXCOMPAT
+                       if (ISHPMMADDR(v)) {
+                               extern struct ste *vtoste();
+                               u_int *bste, *nste;
+
+                               bste = (u_int *)vtoste(p, HPMMBASEADDR(v));
+                               nste = (u_int *)vtoste(p, v);
+                               if ((*bste & SG_V) && *nste == SG_NV) {
+                                       *nste = *bste;
+                                       TBIAU();
+                                       return;
+                               }
+                       }
+#endif
+               growit:
+                       if (type == T_MMUFLT)
+                               goto copyfault;
+                       if (grow((unsigned)frame.f_regs[SP]) || grow(v))
+                               goto out;
+                       i = SIGSEGV;
+                       break;
+               }
+#ifdef HPUXCOMPAT
+               if (ISHPMMADDR(v)) {
+                       TBIS(v);
+                       v = HPMMBASEADDR(v);
+               }
+#endif
+               /*
+                * NOTE: WPF without PG_V is possible
+                * (e.g. attempt to write shared text which is paged out)
+                */
+               if (ncode & MMU_WPF) {
+#ifdef DEBUG
+                       extern struct ste *vtoste();
+                       u_int *ste = (u_int *)vtoste(p, v);
+
+                       if (!(*ste & SG_V)) {
+                               printf("MMU_WPF without sg_v, ste@%x = %x\n",
+                                      ste, *ste);
+                               goto dopanic;
+                       }
+#endif
+                       if (type == T_MMUFLT)
+                               goto copyfault;
+                       i = SIGBUS;
+                       break;
+               }
+               if (ncode & MMU_PF) {
+                       register u_int vp;
+#ifdef DEBUG
+                       extern struct ste *vtoste();
+                       u_int *ste = (u_int *)vtoste(p, v);
+                       struct pte *pte;
+
+                       if (!(*ste & SG_V)) {
+                               printf("MMU_PF without sg_v, ste@%x = %x\n",
+                                      ste, *ste);
+                               goto dopanic;
+                       }
+#endif
+                       vp = btop(v);
+                       if (vp >= dptov(p, p->p_dsize) &&
+                           vp < sptov(p, p->p_ssize-1))
+                               goto growit;
+#ifdef DEBUG
+                       pte = vtopte(p, vp);
+                       if (*(u_int *)pte & PG_V) {
+                               printf("MMU_PF with pg_v, pte = %x\n",
+                                      *(u_int *)pte);
+                               goto dopanic;
+                       }
+#endif
+                       i = u.u_error;
+                       pagein(v, 0);
+                       u.u_error = i;
+                       if (type == T_MMUFLT)
+                               return;
+                       goto out;
+               }
+#ifdef DEBUG
+               printf("T_MMUFLT: unrecognized scenerio\n");
+               goto dopanic;
+#endif
+       }
+       trapsignal(i, ucode);
+       if ((type & USER) == 0)
+               return;
+out:
+       p = u.u_procp;
+       if (p->p_cursig || ISSIG(p))
+               psig();
+       p->p_pri = p->p_usrpri;
+       if (runrun) {
+               /*
+                * Since we are u.u_procp, 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 setrq ourselves but before we
+                * swtch()'ed, we might not be on the queue indicated by
+                * our priority.
+                */
+               (void) splclock();
+               setrq(p);
+               u.u_ru.ru_nivcsw++;
+               swtch();
+               if (ISSIG(p))
+                       psig();
+       }
+       if (u.u_prof.pr_scale) {
+               int ticks;
+               struct timeval *tv = &u.u_ru.ru_stime;
+
+               ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
+                       (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
+               if (ticks) {
+#ifdef PROFTIMER
+                       extern int profscale;
+                       addupc(frame.f_pc, &u.u_prof, ticks * profscale);
+#else
+                       addupc(frame.f_pc, &u.u_prof, ticks);
+#endif
+               }
+       }
+       curpri = p->p_pri;
+}
+
+/*
+ * Called from the trap handler when a system call occurs
+ */
+/*ARGSUSED*/
+syscall(code, frame)
+       volatile int code;
+       struct frame frame;
+{
+       register caddr_t params;
+       register int i;
+       register struct sysent *callp;
+       register struct proc *p;
+       register struct user *up;
+       int opc, numsys;
+       struct timeval syst;
+       struct sysent *systab;
+#ifdef HPUXCOMPAT
+       extern struct sysent hpuxsysent[];
+       extern int hpuxnsysent, notimp();
+#endif
+
+       /*
+        * We assign &u to a local variable for GCC.  This ensures that
+        * we can explicitly reload it after the call to qsetjmp below.
+        * If we don't do this, GCC may itself have assigned &u to a
+        * register variable which will not be properly reloaded, since
+        * GCC knows nothing of the funky semantics of qsetjmp.
+        */
+       up = &u;
+
+       cnt.v_syscall++;
+       syst = up->u_ru.ru_stime;
+       if (!USERMODE(frame.f_sr))
+               panic("syscall");
+       up->u_ar0 = frame.f_regs;
+       up->u_error = 0;
+       opc = frame.f_pc - 2;
+       systab = sysent;
+       numsys = nsysent;
+#ifdef HPUXCOMPAT
+       if (up->u_procp->p_flag & SHPUX) {
+               systab = hpuxsysent;
+               numsys = hpuxnsysent;
+       }
+#endif
+       params = (caddr_t)frame.f_regs[SP] + NBPW;
+       /*
+        * We use entry 0 instead of 63 to signify an invalid syscall because
+        * HPUX uses 63 and 0 works just as well for our purposes.
+        */
+       if (code == 0) {
+               i = fuword(params);
+               params += NBPW;
+               callp = ((unsigned)i >= numsys) ? &systab[0] : &systab[i];
+       } else
+               callp = (code >= numsys) ? &systab[0] : &systab[code];
+       p = up->u_procp;
+       if ((i = callp->sy_narg * sizeof (int)) &&
+           (up->u_error = copyin(params, (caddr_t)up->u_arg, (u_int)i))) {
+#ifdef HPUXCOMPAT
+               if (p->p_flag & SHPUX)
+                       up->u_error = bsdtohpuxerrno(up->u_error);
+#endif
+               frame.f_regs[D0] = (u_char) up->u_error;
+               frame.f_sr |= PSL_C;    /* carry bit */
+#ifdef KTRACE
+                if (KTRPOINT(p, KTR_SYSCALL))
+                        ktrsyscall(p->p_tracep, code, callp->sy_narg);
+#endif
+               goto done;
+       }
+#ifdef KTRACE
+        if (KTRPOINT(p, KTR_SYSCALL))
+                ktrsyscall(p->p_tracep, code, callp->sy_narg);
+#endif
+       up->u_r.r_val1 = 0;
+       up->u_r.r_val2 = frame.f_regs[D0];
+       /*
+        * qsetjmp only saves a6/a7.  This speeds things up in the common
+        * case (where saved values are never used).  There is a side effect
+        * however.  Namely, if we do return via longjmp() we must restore
+        * our own register variables.
+        */
+       if (qsetjmp(&up->u_qsave)) {
+               up = &u;
+               if (up->u_error == 0 && up->u_eosys != RESTARTSYS)
+                       up->u_error = EINTR;
+#ifdef HPUXCOMPAT
+               /* there are some HPUX calls where we change u_ap */
+               if (up->u_ap != up->u_arg) {
+                       up->u_ap = up->u_arg;
+                       printf("syscall(%d): u_ap changed\n", code);
+               }
+#endif
+       } else {
+               up->u_eosys = NORMALRETURN;
+#ifdef HPUXCOMPAT
+               /* debug kludge */
+               if (callp->sy_call == notimp)
+                       notimp(code, callp->sy_narg);
+               else
+#endif
+               (*(callp->sy_call))(up);
+       }
+       /*
+        * Need to reinit p for two reason.  One, it is a register var
+        * and is not saved in the qsetjmp so a EINTR return will leave
+        * it with garbage.  Two, even on a normal return, it will be
+        * wrong for the child process of a fork (it will point to the
+        * parent).
+        */
+       p = up->u_procp;
+       if (up->u_eosys == NORMALRETURN) {
+               if (up->u_error) {
+#ifdef HPUXCOMPAT
+                       if (p->p_flag & SHPUX)
+                               up->u_error = bsdtohpuxerrno(up->u_error);
+#endif
+                       frame.f_regs[D0] = (u_char) up->u_error;
+                       frame.f_sr |= PSL_C;    /* carry bit */
+               } else {
+                       frame.f_regs[D0] = up->u_r.r_val1;
+                       frame.f_regs[D1] = up->u_r.r_val2;
+                       frame.f_sr &= ~PSL_C;
+               }
+       } else if (up->u_eosys == RESTARTSYS)
+               frame.f_pc = opc;
+       /* else if (up->u_eosys == JUSTRETURN) */
+               /* nothing to do */
+done:
+       /*
+        * The check for sigreturn (code 103) ensures that we don't
+        * attempt to set up a call to a signal handler (sendsig) before
+        * we have cleaned up the stack from the last call (sigreturn).
+        * Allowing this seems to lock up the machine in certain scenarios.
+        * What should really be done is to clean up the signal handling
+        * so that this is not a problem.
+        */
+       if (code != 103 && (p->p_cursig || ISSIG(p)))
+               psig();
+       p->p_pri = p->p_usrpri;
+       if (runrun) {
+               /*
+                * Since we are u.u_procp, 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 setrq ourselves but before we
+                * swtch()'ed, we might not be on the queue indicated by
+                * our priority.
+                */
+               (void) splclock();
+               setrq(p);
+               up->u_ru.ru_nivcsw++;
+               swtch();
+       }
+       if (up->u_prof.pr_scale) {
+               int ticks;
+               struct timeval *tv = &up->u_ru.ru_stime;
+
+               ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
+                       (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
+               if (ticks) {
+#ifdef PROFTIMER
+                       extern int profscale;
+                       addupc(frame.f_pc, &up->u_prof, ticks * profscale);
+#else
+                       addupc(frame.f_pc, &up->u_prof, ticks);
+#endif
+               }
+       }
+       curpri = p->p_pri;
+#ifdef KTRACE
+        if (KTRPOINT(p, KTR_SYSRET))
+                ktrsysret(p->p_tracep, code);
+#endif
+}
diff --git a/usr/src/sys/hp300/hp300/vectors.s b/usr/src/sys/hp300/hp300/vectors.s
new file mode 100644 (file)
index 0000000..790d9a9
--- /dev/null
@@ -0,0 +1,97 @@
+| Copyright (c) 1988 University of Utah
+| Copyright (c) 1990 Regents of the University of California.
+| All rights reserved.
+|
+| %sccs.include.redist.gas%
+|
+|      @(#)vectors.s   7.1 (Berkeley) %G%
+|
+       .text
+       .globl  _buserr,_addrerr
+       .globl  _illinst,_zerodiv,_chkinst,_trapvinst,_privinst,_trace
+       .globl  _badtrap
+       .globl  _spurintr,_lev1intr,_lev2intr,_lev3intr
+       .globl  _lev4intr,_lev5intr,_lev6intr,_lev7intr
+       .globl  _trap0,_trap1,_trap2,_trap15
+
+       .long   0x4ef80400      /* 0: jmp 0x400:w (unused reset SSP) */
+       .long   0               /* 1: NOT USED (reset PC) */
+       .long   _buserr         /* 2: bus error */
+       .long   _addrerr        /* 3: address error */
+       .long   _illinst        /* 4: illegal instruction */
+       .long   _zerodiv        /* 5: zero divide */
+       .long   _chkinst        /* 6: CHK instruction */
+       .long   _trapvinst      /* 7: TRAPV instruction */
+       .long   _privinst       /* 8: privilege violation */
+       .long   _trace          /* 9: trace */
+       .long   _illinst        /* 10: line 1010 emulator */
+       .long   _illinst        /* 11: line 1111 emulator */
+       .long   _badtrap        /* 12: unassigned, reserved */
+       .long   _coperr         /* 13: coprocessor protocol violation */
+       .long   _fmterr         /* 14: format error */
+       .long   _badtrap        /* 15: uninitialized interrupt vector */
+       .long   _badtrap        /* 16: unassigned, reserved */
+       .long   _badtrap        /* 17: unassigned, reserved */
+       .long   _badtrap        /* 18: unassigned, reserved */
+       .long   _badtrap        /* 19: unassigned, reserved */
+       .long   _badtrap        /* 20: unassigned, reserved */
+       .long   _badtrap        /* 21: unassigned, reserved */
+       .long   _badtrap        /* 22: unassigned, reserved */
+       .long   _badtrap        /* 23: unassigned, reserved */
+       .long   _spurintr       /* 24: spurious interrupt */
+       .long   _lev1intr       /* 25: level 1 interrupt autovector */
+       .long   _lev2intr       /* 26: level 2 interrupt autovector */
+       .long   _lev3intr       /* 27: level 3 interrupt autovector */
+       .long   _lev4intr       /* 28: level 4 interrupt autovector */
+       .long   _lev5intr       /* 29: level 5 interrupt autovector */
+       .long   _lev6intr       /* 30: level 6 interrupt autovector */
+       .long   _lev7intr       /* 31: level 7 interrupt autovector */
+       .long   _trap0          /* 32: syscalls */
+       .long   _trap1          /* 33: sigreturn syscall or breakpoint */
+       .long   _trap2          /* 34: breakpoint or sigreturn syscall */
+       .long   _illinst        /* 35: TRAP instruction vector */
+       .long   _illinst        /* 36: TRAP instruction vector */
+       .long   _illinst        /* 37: TRAP instruction vector */
+       .long   _illinst        /* 38: TRAP instruction vector */
+       .long   _illinst        /* 39: TRAP instruction vector */
+       .long   _illinst        /* 40: TRAP instruction vector */
+       .long   _illinst        /* 41: TRAP instruction vector */
+       .long   _illinst        /* 42: TRAP instruction vector */
+       .long   _illinst        /* 43: TRAP instruction vector */
+       .long   _illinst        /* 44: TRAP instruction vector */
+       .long   _illinst        /* 45: TRAP instruction vector */
+       .long   _illinst        /* 46: TRAP instruction vector */
+       .long   _trap15         /* 47: TRAP instruction vector */
+       .long   _fptrap         /* 48: FPCP branch/set on unordered cond */
+       .long   _fptrap         /* 49: FPCP inexact result */
+       .long   _fptrap         /* 50: FPCP divide by zero */
+       .long   _fptrap         /* 51: FPCP underflow */
+       .long   _fptrap         /* 52: FPCP operand error */
+       .long   _fptrap         /* 53: FPCP overflow */
+       .long   _fptrap         /* 54: FPCP signalling NAN */
+
+       .long   _badtrap        /* 55: unassigned, reserved */
+       .long   _badtrap        /* 56: unassigned, reserved */
+       .long   _badtrap        /* 57: unassigned, reserved */
+       .long   _badtrap        /* 58: unassigned, reserved */
+       .long   _badtrap        /* 59: unassigned, reserved */
+       .long   _badtrap        /* 60: unassigned, reserved */
+       .long   _badtrap        /* 61: unassigned, reserved */
+       .long   _badtrap        /* 62: unassigned, reserved */
+       .long   _badtrap        /* 63: unassigned, reserved */
+#define BADTRAP16      .long   _badtrap,_badtrap,_badtrap,_badtrap,\
+                               _badtrap,_badtrap,_badtrap,_badtrap,\
+                               _badtrap,_badtrap,_badtrap,_badtrap,\
+                               _badtrap,_badtrap,_badtrap,_badtrap
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
+       BADTRAP16               /* 64-255: user interrupt vectors */
diff --git a/usr/src/sys/hp300/hp300/vm_machdep.c b/usr/src/sys/hp300/hp300/vm_machdep.c
new file mode 100644 (file)
index 0000000..4e0d06f
--- /dev/null
@@ -0,0 +1,569 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: vm_machdep.c 1.18 89/08/23$
+ *
+ *     @(#)vm_machdep.c        7.1 (Berkeley) %G%
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "user.h"
+#include "proc.h"
+#include "cmap.h"
+#include "mount.h"
+#include "../ufs/ufsmount.h"
+#include "vm.h"
+#include "text.h"
+#include "malloc.h"
+#include "buf.h"
+
+#include "cpu.h"
+#include "pte.h"
+
+/*
+ * Set a red zone in the kernel stack after the u. area.
+ * We don't support a redzone right now.  It really isn't clear
+ * that it is a good idea since, if the kernel stack were to roll
+ * into a write protected page, the processor would lock up (since
+ * it cannot create an exception frame) and we would get no useful
+ * post-mortem info.  Currently, under the DEBUG option, we just
+ * check at every clock interrupt to see if the current k-stack has
+ * gone too far (i.e. into the "redzone" page) and if so, panic.
+ * Look at _lev6intr in locore.s for more details.
+ */
+/*ARGSUSED*/
+setredzone(pte, vaddr)
+       struct pte *pte;
+       caddr_t vaddr;
+{
+}
+
+/*
+ * Check for valid program size
+ * NB - Check data and data growth separately as they may overflow 
+ * when summed together.
+ */
+chksize(ts, ids, uds, ss)
+       unsigned ts, ids, uds, ss;
+{
+       extern unsigned maxtsize;
+
+       if (ctob(ts) > maxtsize ||
+           ctob(ids) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
+           ctob(uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
+           ctob(ids + uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
+           ctob(ss) > u.u_rlimit[RLIMIT_STACK].rlim_cur) {
+               u.u_error = ENOMEM;
+               return (1);
+       }
+       return (0);
+}
+
+/*ARGSUSED*/
+newptes(pte, v, size)
+       struct pte *pte;
+       u_int v;
+       register int size;
+{
+       register caddr_t a;
+
+#ifdef lint
+       pte = pte;
+#endif
+       if (size >= 8)
+               TBIAU();
+       else {
+               a = ptob(v);
+               while (size > 0) {
+                       TBIS(a);
+                       a += NBPG;
+                       size--;
+               }
+       }
+       DCIU();
+}
+
+/*
+ * Change protection codes of text segment.
+ * Have to flush translation buffer since this
+ * affect virtual memory mapping of current process.
+ */
+chgprot(addr, tprot)
+       caddr_t addr;
+       long tprot;
+{
+       unsigned v;
+       int tp;
+       register struct pte *pte;
+       register struct cmap *c;
+
+       v = clbase(btop(addr));
+       if (!isatsv(u.u_procp, v)) {
+               u.u_error = EFAULT;
+               return (0);
+       }
+       tp = vtotp(u.u_procp, v);
+       pte = tptopte(u.u_procp, tp);
+       if (pte->pg_fod == 0 && pte->pg_pfnum) {
+               c = &cmap[pgtocm(pte->pg_pfnum)];
+               if (c->c_blkno && c->c_mdev != MSWAPX)
+                       munhash(mounttab[c->c_mdev].um_devvp,
+                           (daddr_t)(u_long)c->c_blkno);
+       }
+       *(u_int *)pte &= ~PG_PROT;
+       *(u_int *)pte |= tprot;
+       TBIS(addr);
+       return (1);
+}
+
+settprot(tprot)
+       long tprot;
+{
+       register u_int *pte, i;
+
+       pte = (u_int *)u.u_procp->p_p0br;
+       for (i = 0; i < u.u_tsize; i++, pte++) {
+               *pte &= ~PG_PROT;
+               *pte |= tprot;
+       }
+       TBIAU();
+}
+
+/*
+ * Simulate effect of VAX region length registers.
+ * The one case where we must do anything is if a region has shrunk.
+ * In that case we must invalidate all the PTEs for the no longer valid VAs.
+ */
+setptlr(region, nlen)
+       int nlen;
+{
+       register struct pte *pte;
+       register int change;
+       int olen;
+
+       if (region == 0) {
+               olen = u.u_pcb.pcb_p0lr;
+               u.u_pcb.pcb_p0lr = nlen;
+       } else {
+               olen = P1PAGES - u.u_pcb.pcb_p1lr;
+               u.u_pcb.pcb_p1lr = nlen;
+               nlen = P1PAGES - nlen;
+       }
+       if ((change = olen - nlen) <= 0)
+               return;
+       if (region == 0)
+               pte = u.u_pcb.pcb_p0br + u.u_pcb.pcb_p0lr;
+       else
+               pte = u.u_pcb.pcb_p1br + u.u_pcb.pcb_p1lr - change;
+       do {
+               *(u_int *)pte++ = PG_NV;
+       } while (--change);
+       /* short cut newptes */
+       TBIAU();
+       DCIU();
+}
+
+/*
+ * Map `size' bytes of physical memory starting at `paddr' into
+ * kernel VA space using PTEs starting at `pte'.  Read/write and
+ * cache-inhibit status are specified by `prot'.
+ */ 
+physaccess(pte, paddr, size, prot)
+       register struct pte *pte;
+       caddr_t paddr;
+       register int size;
+{
+       register u_int page;
+
+       page = (u_int)paddr & PG_FRAME;
+       for (size = btoc(size); size; size--) {
+               *(int *)pte = PG_V | prot | page;
+               page += NBPG;
+               pte++;
+       }
+       TBIAS();
+}
+
+/*
+ * Move pages from one kernel virtual address to another.
+ * Both addresses are assumed to reside in the Sysmap,
+ * and size must be a multiple of CLSIZE.
+ */
+pagemove(from, to, size)
+       register caddr_t from, to;
+       int size;
+{
+       register struct pte *fpte, *tpte;
+
+       if (size % CLBYTES)
+               panic("pagemove");
+       fpte = kvtopte(from);
+       tpte = kvtopte(to);
+       while (size > 0) {
+               *tpte++ = *fpte;
+               *(int *)fpte++ = PG_NV;
+               TBIS(from);
+               TBIS(to);
+               from += NBPG;
+               to += NBPG;
+               size -= NBPG;
+       }
+}
+
+#ifdef KGDB
+/*
+ * Change protections on kernel pages from addr to addr+size
+ * (presumably so debugger can plant a breakpoint).
+ * All addresses are assumed to reside in the Sysmap,
+ */
+chgkprot(addr, size, rw)
+       register caddr_t addr;
+       int size, rw;
+{
+       register struct pte *pte;
+
+       pte = &Sysmap[btop(addr)];
+       while (size > 0) {
+               pte->pg_prot = rw == B_WRITE? 0 : 1;
+               TBIS(addr);
+               addr += NBPG;
+               size -= NBPG;
+               pte++;
+       }
+}
+#endif
+
+/*
+ * The probe[rw] routines should probably be redone in assembler
+ * for efficiency.
+ */
+prober(addr)
+       register u_int addr;
+{
+       register int page;
+       register struct proc *p;
+
+       if (addr >= USRSTACK)
+               return(0);
+#ifdef HPUXCOMPAT
+       if (ISHPMMADDR(addr))
+               addr = HPMMBASEADDR(addr);
+#endif
+       page = btop(addr);
+       p = u.u_procp;
+       if (page < dptov(p, p->p_dsize) || page > sptov(p, p->p_ssize))
+               return(1);
+#ifdef MAPMEM
+       if (page < dptov(p, p->p_dsize+p->p_mmsize) &&
+           (*(int *)vtopte(p, page) & (PG_FOD|PG_V)) == (PG_FOD|PG_V))
+               return(1);
+#endif
+       return(0);
+}
+
+probew(addr)
+       register u_int addr;
+{
+       register int page;
+       register struct proc *p;
+
+       if (addr >= USRSTACK)
+               return(0);
+#ifdef HPUXCOMPAT
+       if (ISHPMMADDR(addr))
+               addr = HPMMBASEADDR(addr);
+#endif
+       page = btop(addr);
+       p = u.u_procp;
+       if (page < dptov(p, p->p_dsize) || page > sptov(p, p->p_ssize))
+               return((*(int *)vtopte(p, page) & PG_PROT) == PG_RW);
+#ifdef MAPMEM
+       if (page < dptov(p, p->p_dsize+p->p_mmsize))
+               return((*(int *)vtopte(p, page) & (PG_FOD|PG_V|PG_PROT))
+                      == (PG_FOD|PG_V|PG_RW));
+#endif
+       return(0);
+}
+
+/*
+ * NB: assumes a physically contiguous kernel page table
+ *     (makes life a LOT simpler).
+ */
+kernacc(addr, count, rw)
+       register caddr_t addr;
+       int count, rw;
+{
+       register struct ste *ste;
+       register struct pte *pte;
+       register u_int ix, cnt;
+       extern long Syssize;
+
+       if (count <= 0)
+               return(0);
+       ix = ((int)addr & SG_IMASK) >> SG_ISHIFT;
+       cnt = (((int)addr + count + (1<<SG_ISHIFT)-1) & SG_IMASK) >> SG_ISHIFT;
+       cnt -= ix;
+       for (ste = &Sysseg[ix]; cnt; cnt--, ste++)
+               /* should check SG_PROT, but we have no RO segments now */
+               if (ste->sg_v == 0)
+                       return(0);
+       ix = btop(addr);
+       cnt = btop(addr+count+NBPG-1);
+       if (cnt > (u_int)&Syssize)
+               return(0);
+       cnt -= ix;
+       for (pte = &Sysmap[ix]; cnt; cnt--, pte++)
+               if (pte->pg_v == 0 || (rw == B_WRITE && pte->pg_prot == 1))
+                       return(0);
+       return(1);
+}
+
+useracc(addr, count, rw)
+       register caddr_t addr;
+       unsigned count;
+{
+       register int (*func)();
+       register u_int addr2;
+       extern int prober(), probew();
+
+       if (count <= 0)
+               return(0);
+       addr2 = (u_int) addr;
+       addr += count;
+       func = (rw == B_READ) ? prober : probew;
+       do {
+               if ((*func)(addr2) == 0)
+                       return(0);
+               addr2 = (addr2 + NBPG) & ~PGOFSET;
+       } while (addr2 < (u_int)addr);
+       return(1);
+}
+
+/*
+ * Convert kernel VA to physical address
+ */
+kvtop(addr)
+       register caddr_t addr;
+{
+       register int pf;
+
+       pf = Sysmap[btop(addr)].pg_pfnum;
+       if (pf == 0)
+               panic("kvtop: zero page frame");
+       return((u_int)ptob(pf) + ((int)addr & PGOFSET));
+}
+
+struct ste *
+vtoste(p, va)
+       register struct proc *p;
+       register u_int va;
+{
+       register struct ste *ste;
+
+       ste = (struct ste *)((u_int)p->p_p0br + p->p_szpt * NBPG);
+       return(ste + ((va & SG_IMASK) >> SG_ISHIFT));
+}
+
+initustp(p)
+       register struct proc *p;
+{
+       return((int)Usrptmap[btokmx(p->p_p0br) + p->p_szpt].pg_pfnum);
+}
+
+/*
+ * Initialize segment table to reflect PTEs in Usrptmap.
+ * Segment table address is given by Usrptmap index of p_szpt.
+ */
+initsegt(p)
+       register struct proc *p;
+{
+       register int i, k, sz;
+       register struct ste *ste;
+       extern struct ste *vtoste();
+
+       k = btokmx(p->p_p0br);
+       ste = vtoste(p, 0);
+       /* text and data */
+       sz = ctopt(p->p_tsize + p->p_dsize + p->p_mmsize);
+       for (i = 0; i < sz; i++, ste++) {
+               *(int *)ste = SG_RW | SG_V;
+               ste->sg_pfnum = Usrptmap[k++].pg_pfnum;
+       }
+       /*
+        * Bogus!  The kernelmap may map unused PT pages
+        * (since we don't shrink PTs) so we need to skip over
+        * those STEs.  We should really free the unused PT
+        * pages in expand().
+        */
+       sz += ctopt(p->p_ssize + HIGHPAGES);
+       if (sz < p->p_szpt)
+               k += p->p_szpt - sz;
+       /* hole */
+       sz = NPTEPG - ctopt(p->p_ssize + HIGHPAGES);
+       for ( ; i < sz; i++, ste++)
+               *(int *)ste = SG_NV;
+       /* stack and u-area */
+       sz = NPTEPG;
+       for ( ; i < sz; i++, ste++) {
+               *(int *)ste = SG_RW | SG_V;
+               ste->sg_pfnum = Usrptmap[k++].pg_pfnum;
+       }
+}
+
+/*
+ * Allocate/free cache-inhibited physical memory.
+ * Assumes that malloc returns page aligned memory for requests which are
+ * a multiple of the page size.  Hence, size must be such a multiple.
+ */
+caddr_t
+cialloc(sz)
+       int sz;
+{
+       caddr_t kva;
+       register int npg, *pte;
+
+       if (sz & CLOFSET)
+               return(NULL);
+       kva = (caddr_t)malloc(sz, M_DEVBUF, M_NOWAIT);
+       if (kva) {
+               if (!claligned(kva))
+                       panic("cialloc");
+               pte = (int *)kvtopte(kva);
+               npg = btoc(sz);
+               while (--npg >= 0)
+                       *pte++ |= PG_CI;
+               TBIAS();
+       }
+       return(kva);
+}
+
+cifree(kva, sz)
+       caddr_t kva;
+       int sz;
+{
+       register int npg, *pte;
+
+       if (sz & CLOFSET)
+               panic("cifree");
+       pte = (int *)kvtopte(kva);
+       npg = btoc(sz);
+       while (--npg >= 0)
+               *pte++ &= ~PG_CI;
+       TBIAS();
+       free(kva, M_DEVBUF);
+}
+
+extern char usrio[];
+extern struct pte Usriomap[];
+struct map *useriomap;
+int usriowanted;
+
+/*
+ * Map an IO request into kernel virtual address space.  Requests fall into
+ * one of five catagories:
+ *
+ *     B_PHYS|B_UAREA: User u-area swap.
+ *                     Address is relative to start of u-area (p_addr).
+ *     B_PHYS|B_PAGET: User page table swap.
+ *                     Address is a kernel VA in usrpt (Usrptmap).
+ *     B_PHYS|B_DIRTY: Dirty page push.
+ *                     Address is a VA in proc2's address space.
+ *     B_PHYS|B_PGIN:  Kernel pagein of user pages.
+ *                     Address is VA in user's address space.
+ *     B_PHYS:         User "raw" IO request.
+ *                     Address is VA in user's address space.
+ *
+ * All requests are (re)mapped into kernel VA space via the useriomap
+ * (a name with only slightly more meaning than "kernelmap")
+ */
+vmapbuf(bp)
+       register struct buf *bp;
+{
+       register int npf, a;
+       register caddr_t addr;
+       register struct pte *pte, *iopte;
+       register long flags = bp->b_flags;
+       struct proc *p;
+       int off, s;
+
+       if ((flags & B_PHYS) == 0)
+               panic("vmapbuf");
+       /*
+        * Find PTEs for the area to be mapped
+        */
+       p = flags&B_DIRTY ? &proc[2] : bp->b_proc;
+       addr = bp->b_un.b_addr;
+       if (flags & B_UAREA)
+               pte = &p->p_addr[btop(addr)];
+       else if (flags & B_PAGET)
+               pte = &Usrptmap[btokmx((struct pte *)addr)];
+       else
+               pte = vtopte(p, btop(addr));
+       /*
+        * Allocate some kernel PTEs and load them
+        */
+       off = (int)addr & PGOFSET;
+       npf = btoc(bp->b_bcount + off);
+       s = splbio();
+       while ((a = rmalloc(useriomap, npf)) == 0) {
+               usriowanted = 1;
+               sleep((caddr_t)useriomap, PSWP);
+       }
+       splx(s);
+       iopte = &Usriomap[a];
+       bp->b_saveaddr = bp->b_un.b_addr;
+       addr = bp->b_un.b_addr = (caddr_t)(usrio + (a << PGSHIFT)) + off;
+       while (npf--) {
+               mapin(iopte, (u_int)addr, pte->pg_pfnum, PG_CI|PG_RW|PG_V);
+               iopte++, pte++;
+               addr += NBPG;
+       }
+}
+
+/*
+ * Free the io map PTEs associated with this IO operation.
+ * We also invalidate the TLB entries and restore the original b_addr.
+ */
+vunmapbuf(bp)
+       register struct buf *bp;
+{
+       register int a, npf;
+       register caddr_t addr = bp->b_un.b_addr;
+       register struct pte *pte;
+       int s;
+
+       if ((bp->b_flags & B_PHYS) == 0)
+               panic("vunmapbuf");
+       a = (int)(addr - usrio) >> PGSHIFT;
+       npf = btoc(bp->b_bcount + ((int)addr & PGOFSET));
+       s = splbio();
+       rmfree(useriomap, npf, a);
+       if (usriowanted) {
+               usriowanted = 0;
+               wakeup((caddr_t)useriomap); 
+       }
+       splx(s);
+       pte = &Usriomap[a];
+       while (npf--) {
+               *(int *)pte = PG_NV;
+               TBIS((caddr_t)addr);
+               addr += NBPG;
+               pte++;
+       }
+#if 0
+       /* 0 is a valid (and common) user space addr */
+       if (bp->b_saveaddr == NULL)
+               panic("vunmapbuf: null saveaddr");
+#endif
+       bp->b_un.b_addr = bp->b_saveaddr;
+       bp->b_saveaddr = NULL;
+}
diff --git a/usr/src/sys/hp300/include/cpu.h b/usr/src/sys/hp300/include/cpu.h
new file mode 100644 (file)
index 0000000..0b4ad5f
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: cpu.h 1.13 89/06/23$
+ *
+ *     @(#)cpu.h       7.1 (Berkeley) %G%
+ */
+
+/* values for machineid */
+#define HP_320         0       /* 16Mhz 68020+HP MMU+16K external cache */
+#define HP_330         1       /* 16Mhz 68020+68851 MMU */
+#define HP_350         2       /* 25Mhz 68020+HP MMU+32K external cache */
+#define HP_360         3       /* 25Mhz 68030 */
+#define HP_370         4       /* 33Mhz 68030+64K external cache */
+#define HP_340         5       /* 16Mhz 68030 */
+
+/* values for mmutype (assigned for quick testing) */
+#define MMU_68030      -1      /* 68030 on-chip subset of 68851 */
+#define MMU_HP         0       /* HP proprietary */
+#define MMU_68851      1       /* Motorola 68851 */
+
+/* values for ectype */
+#define EC_PHYS                -1      /* external physical address cache */
+#define EC_NONE                0       /* no external cache */
+#define EC_VIRT                1       /* external virtual address cache */
+
+/* values for cpuspeed (not really related to clock speed due to caches) */
+#define MHZ_8          1
+#define MHZ_16         2
+#define MHZ_25         3
+#define MHZ_33         4
+
+#ifdef KERNEL
+extern int machineid, mmutype, ectype;
+extern int IObase;
+
+/* what is this supposed to do? i.e. how is it different than startrtclock? */
+#define        enablertclock()
+
+#endif
+
+/* physical memory sections */
+#define ROMBASE                (0x00000000)
+#define IOBASE         (0x00200000)
+#define IOTOP          (0x01000000)
+#define MAXADDR                (0xFFFFF000)
+
+/* IO space stuff */
+#define EXTIOBASE      (0x00600000)
+#define        IOCARDSIZE      (0x10000)
+#define        IOMAPSIZE       (btoc(IOTOP-IOBASE))
+#define        IOP(x)          ((x) - IOBASE)
+#define        IOV(x)          (((x) - IOBASE) + (int)&IObase)
+#define UNIOV(x)       ((x) - (int)&IObase + IOBASE)
+
+/* DIO II uncached address space */
+#define DIOIIBASE      (0x01000000)
+#define DIOIITOP       (0x20000000)
+#define DIOIICSIZE     (0x00400000)
+
+/* offsets for longword read/write */
+#define        MMUSSTP         IOP(0x5F4000)
+#define        MMUUSTP         IOP(0x5F4004)
+#define        MMUTBINVAL      IOP(0x5F4008)
+#define        MMUSTAT         IOP(0x5F400C)
+#define        MMUCMD          MMUSTAT
+
+#define MMU_UMEN       0x0001  /* enable user mapping */
+#define MMU_SMEN       0x0002  /* enable supervisor mapping */
+#define MMU_CEN                0x0004  /* enable data cache */
+#define MMU_BERR       0x0008  /* bus error */
+#define MMU_IEN                0x0020  /* enable instruction cache */
+#define MMU_FPE                0x0040  /* enable 68881 FP coprocessor */
+#define MMU_WPF                0x2000  /* write protect fault */
+#define MMU_PF         0x4000  /* page fault */
+#define MMU_PTF                0x8000  /* page table fault */
+
+#define MMU_FAULT      (MMU_PTF|MMU_PF|MMU_WPF|MMU_BERR)
+#define MMU_ENAB       (MMU_UMEN|MMU_SMEN|MMU_IEN|MMU_FPE)
+
+#define PMMU_LVLMASK   0x0007
+#define PMMU_INV       0x0400
+#define PMMU_WP                0x0800
+#define PMMU_ALV       0x1000
+#define PMMU_SO                0x2000
+#define PMMU_LV                0x4000
+#define PMMU_BE                0x8000
+
+#define PMMU_FAULT     (PMMU_WP|PMMU_INV)
+
+/* function code for user data space */
+#define        FC_USERD        1
+/* methinks the following is used to selectively clear TLB entries */
+#define FC_PURGE       3
+
+/* fields in the 68020 cache control register */
+#define IC_ENABLE      0x0001  /* enable instruction cache */
+#define IC_FREEZE      0x0002  /* freeze instruction cache */
+#define IC_CE          0x0004  /* clear instruction cache entry */
+#define IC_CLR         0x0008  /* clear entire instruction cache */
+
+/* additional fields in the 68030 cache control register */
+#define IC_BE          0x0010  /* instruction burst enable */
+#define DC_ENABLE      0x0100  /* data cache enable */
+#define DC_FREEZE      0x0200  /* data cache freeze */
+#define DC_CE          0x0400  /* clear data cache entry */
+#define DC_CLR         0x0800  /* clear entire data cache */
+#define DC_BE          0x1000  /* data burst enable */
+#define DC_WA          0x2000  /* write allocate */
+
+#define CACHE_ON       (DC_WA|DC_BE|DC_CLR|DC_ENABLE|IC_BE|IC_CLR|IC_ENABLE)
+#define CACHE_OFF      (DC_CLR|IC_CLR)
+#define CACHE_CLR      (CACHE_ON)
+#define IC_CLEAR       (DC_WA|DC_BE|DC_ENABLE|IC_BE|IC_CLR|IC_ENABLE)
+#define DC_CLEAR       (DC_WA|DC_BE|DC_CLR|DC_ENABLE|IC_BE|IC_ENABLE)
diff --git a/usr/src/sys/hp300/include/float.h b/usr/src/sys/hp300/include/float.h
new file mode 100644 (file)
index 0000000..63715f5
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)float.h     7.1 (Berkeley) %G%
+ */
+
+#define FLT_RADIX      2               /* b */
+#define FLT_ROUNDS     1               /* FP addition rounds to nearest */
+
+#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
diff --git a/usr/src/sys/hp300/include/frame.h b/usr/src/sys/hp300/include/frame.h
new file mode 100644 (file)
index 0000000..70f116a
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: frame.h 1.6 89/02/24$
+ *
+ *     @(#)frame.h     7.1 (Berkeley) %G%
+ */
+
+struct frame {
+       int     f_regs[16];
+       short   f_stackadj;
+       u_short f_sr;
+       u_int   f_pc;
+       u_short f_format:4,
+               f_vector:12;
+       union F_u {
+               struct fmt2 {
+                       u_int   f_iaddr;
+               } F_fmt2;
+
+               struct fmt9 {
+                       u_int   f_iaddr;
+                       u_short f_iregs[4];
+               } F_fmt9;
+
+               struct fmtA {
+                       u_short f_ir0;
+                       u_short f_ssw;
+                       u_short f_ipsc;
+                       u_short f_ipsb;
+                       u_int   f_dcfa;
+                       u_short f_ir1, f_ir2;
+                       u_int   f_dob;
+                       u_short f_ir3, f_ir4;
+               } F_fmtA;
+
+               struct fmtB {
+                       u_short f_ir0;
+                       u_short f_ssw;
+                       u_short f_ipsc;
+                       u_short f_ipsb;
+                       u_int   f_dcfa;
+                       u_short f_ir1, f_ir2;
+                       u_int   f_dob;
+                       u_short f_ir3, f_ir4;
+                       u_short f_ir5, f_ir6;
+                       u_int   f_sba;
+                       u_short f_ir7, f_ir8;
+                       u_int   f_dib;
+                       u_short f_iregs[22];
+               } F_fmtB;
+       } F_u;
+};
+
+#define        f_fmt2          F_u.F_fmt2
+#define        f_fmtA          F_u.F_fmtA
+#define        f_fmtB          F_u.F_fmtB
+
+/* common frame size */
+#define        CFSIZE          (sizeof(struct frame) - sizeof(union F_u))
+#define        NFMTSIZE        8
+
+#define        FMT0            0x0
+#define        FMT1            0x1
+#define        FMT2            0x2
+#define        FMT9            0x9
+#define        FMTA            0xA
+#define        FMTB            0xB
+
+/* frame specific info sizes */
+#define        FMT0SIZE        0
+#define        FMT1SIZE        0
+#define        FMT2SIZE        sizeof(struct fmt2)
+#define        FMT9SIZE        sizeof(struct fmt9)
+#define        FMTASIZE        sizeof(struct fmtA)
+#define        FMTBSIZE        sizeof(struct fmtB)
+
+#define        V_BUSERR        0x008
+#define        V_ADDRERR       0x00C
+#define        V_TRAP1         0x084
+
+#define        SSW_RC          0x2000
+#define        SSW_RB          0x1000
+#define        SSW_DF          0x0100
+#define        SSW_RM          0x0080
+#define        SSW_RW          0x0040
+#define        SSW_FCMASK      0x0007
+
+struct fpframe {
+       union FPF_u1 {
+               u_int   FPF_null;
+               struct {
+                       u_char  FPF_version;
+                       u_char  FPF_fsize;
+                       u_short FPF_res1;
+               } FPF_nonnull;
+       } FPF_u1;
+       union FPF_u2 {
+               struct fpidle {
+                       u_short fpf_ccr;
+                       u_short fpf_res2;
+                       u_int   fpf_iregs1[8];
+                       u_int   fpf_xops[3];
+                       u_int   fpf_opreg;
+                       u_int   fpf_biu;
+               } FPF_idle;
+
+               struct fpbusy {
+                       u_int   fpf_iregs[53];
+               } FPF_busy;
+       } FPF_u2;
+       u_int   fpf_regs[8*3];
+       u_int   fpf_fpcr;
+       u_int   fpf_fpsr;
+       u_int   fpf_fpiar;
+};
+
+#define fpf_null       FPF_u1.FPF_null
+#define fpf_version    FPF_u1.FPF_nonnull.FPF_version
+#define fpf_fsize      FPF_u1.FPF_nonnull.FPF_fsize
+#define fpf_res1       FPF_u1.FPF_nonnull.FPF_res1
+#define fpf_idle       FPF_u2.FPF_idle
+#define fpf_busy       FPF_u2.FPF_busy
diff --git a/usr/src/sys/hp300/include/mtpr.h b/usr/src/sys/hp300/include/mtpr.h
new file mode 100644 (file)
index 0000000..ac8cada
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: mtpr.h 1.5 89/04/11$
+ *
+ *     @(#)mtpr.h      7.1 (Berkeley) %G%
+ */
+
+/*
+ * simulated software interrupt register
+ */
+
+extern unsigned char ssir;
+
+#define SIR_NET                0x1
+#define SIR_CLOCK      0x2
+
+#define siroff(x)      ssir &= ~(x)
+#define setsoftnet()   ssir |= SIR_NET
+#define setsoftclock() ssir |= SIR_CLOCK
diff --git a/usr/src/sys/hp300/include/param.h b/usr/src/sys/hp300/include/param.h
new file mode 100644 (file)
index 0000000..78d1159
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: machparam.h 1.11 89/08/14$
+ *
+ *     @(#)param.h     7.1 (Berkeley) %G%
+ */
+
+/*
+ * Machine dependent constants for HP9000 series 300.
+ */
+#define        MACHINE "hp300"
+
+#ifndef BYTE_ORDER
+#include <machine/endian.h>
+#endif
+
+#include <machine/machlimits.h>
+
+#define        NBPG            4096            /* bytes/page */
+#define        PGOFSET         (NBPG-1)        /* byte offset into page */
+#define        PGSHIFT         12              /* LOG2(NBPG) */
+#define        NPTEPG          (NBPG/(sizeof (struct pte)))
+
+#define NBSEG          (1024*NBPG)     /* bytes/segment */
+#define        SEGOFSET        (NBSEG-1)       /* byte offset into segment */
+#define        SEGSHIFT        22              /* LOG2(NBSEG) */
+
+#define        KERNBASE        0x00000000      /* start of kernel virtual */
+#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
+
+#define        SSIZE           1               /* initial stack size/NBPG */
+#define        SINCR           1               /* increment of stack/NBPG */
+
+#define        UPAGES          3               /* pages of u-area */
+
+/*
+ * Constants related to network buffer management.
+ * MCLBYTES must be no larger than CLBYTES (the software page size), and,
+ * on machines that exchange pages of input or output buffers with mbuf
+ * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple
+ * of the hardware page size.
+ */
+#define        MSIZE           128             /* size of an mbuf */
+#define        MCLBYTES        1024
+#define        MCLSHIFT        10
+#define        MCLOFSET        (MCLBYTES - 1)
+#ifndef NMBCLUSTERS
+#ifdef GATEWAY
+#define        NMBCLUSTERS     512             /* map size, max cluster allocation */
+#else
+#define        NMBCLUSTERS     256             /* map size, max cluster allocation */
+#endif
+#endif
+
+/*
+ * Size of kernel malloc arena in CLBYTES-sized logical pages
+ */ 
+#ifndef NKMEMCLUSTERS
+#define        NKMEMCLUSTERS   (512*1024/CLBYTES)
+#endif
+
+/*
+ * Some macros for units conversion
+ */
+/* Core clicks (4096 bytes) to segments and vice versa */
+#define        ctos(x) (x)
+#define        stoc(x) (x)
+
+/* Core clicks (4096 bytes) to disk blocks */
+#define        ctod(x) ((x)<<(PGSHIFT-DEV_BSHIFT))
+#define        dtoc(x) ((x)>>(PGSHIFT-DEV_BSHIFT))
+#define        dtob(x) ((x)<<DEV_BSHIFT)
+
+/* clicks to bytes */
+#define        ctob(x) ((x)<<PGSHIFT)
+
+/* bytes to clicks */
+#define        btoc(x) (((unsigned)(x)+(NBPG-1))>>PGSHIFT)
+
+#define        btodb(bytes)                    /* calculates (bytes / DEV_BSIZE) */ \
+       ((unsigned)(bytes) >> DEV_BSHIFT)
+#define        dbtob(db)                       /* calculates (db * DEV_BSIZE) */ \
+       ((unsigned)(db) << DEV_BSHIFT)
+
+/*
+ * Map a ``block device block'' to a file system block.
+ * This should be device dependent, and will be if we
+ * add an entry to cdevsw/bdevsw for that purpose.
+ * For now though just use DEV_BSIZE.
+ */
+#define        bdbtofsb(bn)    ((bn) / (BLKDEV_IOSIZE/DEV_BSIZE))
+
+/*
+ * Macros to decode processor status word.
+ */
+#define        USERMODE(ps)    (((ps) & PSL_S) == 0)
+#define        BASEPRI(ps)     (((ps) & PSL_IPL7) == 0)
+
+#ifdef KERNEL
+#ifndef LOCORE
+int    cpuspeed;
+#define        DELAY(n)        { register int N = cpuspeed * (n); while (--N > 0); }
+#endif
+
+#else KERNEL
+#define        DELAY(n)        { register int N = (n); while (--N > 0); }
+#endif KERNEL
+
+#ifdef HPUXCOMPAT
+/*
+ * Constants/macros for HPUX multiple mapping of user address space.
+ * Pages in the first 256Mb are mapped in at every 256Mb segment.
+ */
+#define HPMMMASK       0xF0000000
+#define ISHPMMADDR(v)  \
+    ((u.u_pcb.pcb_flags&PCB_HPUXMMAP) && ((unsigned)(v)&HPMMMASK) != HPMMMASK)
+#define HPMMBASEADDR(v)        ((unsigned)(v) & ~HPMMMASK)
+#endif
diff --git a/usr/src/sys/hp300/include/pcb.h b/usr/src/sys/hp300/include/pcb.h
new file mode 100644 (file)
index 0000000..cced152
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: pcb.h 1.13 89/04/23$
+ *
+ *     @(#)pcb.h       7.1 (Berkeley) %G%
+ */
+
+#ifdef KERNEL
+#include "frame.h"
+#else
+#include <hp300/frame.h>
+#endif
+
+/*
+ * HP300 process control block
+ */
+struct pcb
+{
+       short   pcb_flags;      /* misc. process flags (+0) */
+       short   pcb_ps;         /* processor status word (+2) */
+       int     pcb_ustp;       /* user segment table pointer (+4) */
+       int     pcb_usp;        /* user stack pointer (+8) */
+       int     pcb_regs[12];   /* D0-D7, A0-A7 (+C) */
+       struct pte *pcb_p0br;   /* P0 base register (+3C) */
+       int     pcb_p0lr;       /* P0 length register (+40) */
+       struct pte *pcb_p1br;   /* P1 base register (+44) */
+       int     pcb_p1lr;       /* P1 length register (+48) */
+       int     pcb_szpt;       /* number of pages of user page table (+4C) */
+       int     pcb_cmap2;      /* temporary copy PTE (+50) */
+       int     *pcb_sswap;     /* saved context for swap return (+54) */
+       short   pcb_sigc[12];   /* signal trampoline code (+58) */
+       caddr_t pcb_onfault;    /* for copyin/out faults (+70) */
+       struct fpframe pcb_fpregs; /* 68881/2 context save area (+74) */
+       int     pcb_exec[16];   /* exec structure for core dumps (+1B8) */
+       int     pcb_res[2];     /* reserved for future expansion (+1F8) */
+};
+
+/* flags */
+
+#define        PCB_AST         0x0001  /* async trap pending */
+#define PCB_HPUXMMAP   0x0010  /* VA space is multiple mapped */
+#define PCB_HPUXTRACE  0x0020  /* being traced by an HPUX process */
+#define PCB_HPUXBIN    0x0040  /* loaded from an HPUX format binary */
+                               /* note: does NOT imply SHPUX */
+
+#define aston() \
+       { \
+               u.u_pcb.pcb_flags |= PCB_AST; \
+       }
+
+#define astoff() \
+       { \
+               u.u_pcb.pcb_flags &= ~PCB_AST; \
+       }
+
+#define astpend() \
+       (u.u_pcb.pcb_flags & PCB_AST)
diff --git a/usr/src/sys/hp300/include/psl.h b/usr/src/sys/hp300/include/psl.h
new file mode 100644 (file)
index 0000000..2195401
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)psl.h       7.1 (Berkeley) %G%
+ */
+
+/*
+ * MC68000 program status word
+ */
+
+#define        PSL_C           0x0001          /* carry bit */
+#define        PSL_V           0x0002          /* overflow bit */
+#define        PSL_Z           0x0004          /* zero bit */
+#define        PSL_N           0x0008          /* negative bit */
+#define        PSL_X           0x0010          /* extend bit */
+#define        PSL_ALLCC       0x001F          /* all cc bits - unlikely */
+#define        PSL_IPL0        0x0000          /* interrupt priority level 0 */
+#define        PSL_IPL1        0x0100          /* interrupt priority level 1 */
+#define        PSL_IPL2        0x0200          /* interrupt priority level 2 */
+#define        PSL_IPL3        0x0300          /* interrupt priority level 3 */
+#define        PSL_IPL4        0x0400          /* interrupt priority level 4 */
+#define        PSL_IPL5        0x0500          /* interrupt priority level 5 */
+#define        PSL_IPL6        0x0600          /* interrupt priority level 6 */
+#define        PSL_IPL7        0x0700          /* interrupt priority level 7 */
+#define        PSL_S           0x2000          /* supervisor enable bit */
+#define        PSL_T           0x8000          /* trace enable bit */
+
+#define        PSL_LOWIPL      (PSL_S)
+#define        PSL_HIGHIPL     (PSL_S | PSL_IPL7)
+#define PSL_IPL                (PSL_IPL7)
+#define        PSL_USER        (0)
+
+#define        PSL_MBZ         0x58E0          /* must be zero bits */
+
+#define        PSL_USERSET     (0)
+#define        PSL_USERCLR     (PSL_S | PSL_IPL7 | PSL_MBZ)
diff --git a/usr/src/sys/hp300/include/reg.h b/usr/src/sys/hp300/include/reg.h
new file mode 100644 (file)
index 0000000..5b167f5
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: reg.h 1.5 89/04/11$
+ *
+ *     @(#)reg.h       7.1 (Berkeley) %G%
+ */
+
+/*
+ * Location of the users' stored
+ * registers relative to D0.
+ * Usage is u.u_ar0[XX].
+ */
+#define        D0      (0)
+#define        D1      (1)
+#define        D2      (2)
+#define        D3      (3)
+#define        D4      (4)
+#define        D5      (5)
+#define        D6      (6)
+#define        D7      (7)
+#define        A0      (8)
+#define        A1      (9)
+#define        A2      (10)
+#define        A3      (11)
+#define        A4      (12)
+#define        A5      (13)
+#define        A6      (14)
+#define        A7      (15)
+
+#define        SP      A7
+#define        PC      (17)
+#define        PS      (16)
+
+#ifdef IPCREG
+#define        NIPCREG 17
+int ipcreg[NIPCREG] =
+       {D0,D1,D2,D3,D4,D5,D6,D7,A0,A1,A2,A3,A4,A5,A6,A7,PC};
+#endif
+
+#ifdef KERNEL
+/*
+ * Due to a mental lapse somewhere down the line, wait returns its values
+ * in strange registers.  Kludge it up here so we don't have to in the
+ * machine-independent code.
+ */
+#define        R0      D1
+#define        R1      A0
+#endif
diff --git a/usr/src/sys/hp300/include/trap.h b/usr/src/sys/hp300/include/trap.h
new file mode 100644 (file)
index 0000000..0ac3da4
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: trap.h 1.6 88/11/25$
+ *
+ *     @(#)trap.h      7.1 (Berkeley) %G%
+ */
+
+/*
+ * Trap type values
+ */
+
+#define        T_BUSERR        0
+#define        T_ADDRERR       1
+#define        T_ILLINST       2
+#define        T_ZERODIV       3
+#define        T_CHKINST       4
+#define        T_TRAPVINST     5
+#define        T_PRIVINST      6
+#define        T_TRACE         7
+#define        T_MMUFLT        8
+#define        T_SSIR          9
+#define        T_FMTERR        10
+#define T_FPERR                11
+#define T_COPERR       12
+#define T_AST          13
+#define T_TRAP15       15
diff --git a/usr/src/sys/hp300/include/vmparam.h b/usr/src/sys/hp300/include/vmparam.h
new file mode 100644 (file)
index 0000000..3a8852d
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * %sccs.include.redist.c%
+ *
+ * from: Utah $Hdr: vmparam.h 1.14 89/08/14$
+ *
+ *     @(#)vmparam.h   7.1 (Berkeley) %G%
+ */
+
+/*
+ * Machine dependent constants for HP300
+ */
+/*
+ * 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.
+ *
+ * NOTE: the ONLY reason that HIGHPAGES is 0x100 instead of UPAGES (3)
+ * is for HPUX compatibility.  Why??  Because HPUX's debuggers
+ * have the user's stack hard-wired at FFF00000 for post-mortems,
+ * and we must be compatible...
+ */
+#define        USRTEXT         0
+#define        USRSTACK        (-HIGHPAGES*NBPG)       /* Start of user stack */
+#define        BTOPUSRSTACK    (0x100000-HIGHPAGES)    /* btop(USRSTACK) */
+#define P1PAGES                0x100000
+#define        LOWPAGES        0
+#define HIGHPAGES      (0x100000/NBPG)
+
+/*
+ * Virtual memory related constants, all in bytes
+ */
+#ifndef MAXTSIZ
+#define        MAXTSIZ         (6*1024*1024)           /* max text size */
+#endif
+#ifndef DFLDSIZ
+#define        DFLDSIZ         (8*1024*1024)           /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define        MAXDSIZ         (16*1024*1024)          /* max data size */
+#endif
+#ifndef        DFLSSIZ
+#define        DFLSSIZ         (512*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 */
+#define        DMTEXT  1024                    /* swap allocation for text */
+
+/*
+ * Sizes of the system and user portions of the system page table.
+ */
+/* SYSPTSIZE IS SILLY; IT SHOULD BE COMPUTED AT BOOT TIME */
+#define        SYSPTSIZE       (2 * NPTEPG)
+#define        USRPTSIZE       (1 * NPTEPG)
+
+/*
+ * PTEs for mapping user space into kernel for phyio operations.
+ * One page is enough to handle 4Mb of simultaneous raw IO operations.
+ */
+#define USRIOSIZE      (1 * NPTEPG)
+
+/*
+ * PTEs for system V style shared memory.
+ * This is basically slop for kmempt which we actually allocate (malloc) from.
+ */
+#define SHMMAXPGS      1024
+
+/*
+ * 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.
+ */
+
+#define        KLMAX   (4/CLSIZE)
+#define        KLSEQL  (2/CLSIZE)              /* in klust if vadvise(VA_SEQL) */
+#define        KLIN    (4/CLSIZE)              /* default data/stack in klust */
+#define        KLTXT   (4/CLSIZE)              /* default text in klust */
+#define        KLOUT   (4/CLSIZE)
+
+/*
+ * KLSDIST is the advance or retard of the fifo reclaim for sequential
+ * processes data space.
+ */
+#define        KLSDIST 3               /* klusters advance/retard for seq. fifo */
+
+/*
+ * Paging thresholds (see vm_sched.c).
+ * Strategy of 1/19/85:
+ *     lotsfree is 512k bytes, but at most 1/4 of memory
+ *     desfree is 200k bytes, but at most 1/8 of memory
+ *     minfree is 64k bytes, but at most 1/2 of desfree
+ */
+#define        LOTSFREE        (512 * 1024)
+#define        LOTSFREEFRACT   4
+#define        DESFREE         (200 * 1024)
+#define        DESFREEFRACT    8
+#define        MINFREE         (64 * 1024)
+#define        MINFREEFRACT    2
+
+/*
+ * 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) \
+       (*(u_int *)(pte) = ((pfnum) << PGSHIFT) | (prot), TBIS((caddr_t)(v)))