summaryrefslogtreecommitdiff
path: root/sys/arch/pc532/stand
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/pc532/stand')
-rw-r--r--sys/arch/pc532/stand/Makefile98
-rw-r--r--sys/arch/pc532/stand/README26
-rw-r--r--sys/arch/pc532/stand/boot.c279
-rw-r--r--sys/arch/pc532/stand/conf.c59
-rw-r--r--sys/arch/pc532/stand/cons.c93
-rw-r--r--sys/arch/pc532/stand/devopen.c203
-rw-r--r--sys/arch/pc532/stand/filesystem.c40
-rw-r--r--sys/arch/pc532/stand/inflate.c1433
-rw-r--r--sys/arch/pc532/stand/machdep.c98
-rw-r--r--sys/arch/pc532/stand/prf.c79
-rw-r--r--sys/arch/pc532/stand/rd.c29
-rw-r--r--sys/arch/pc532/stand/samachdep.h42
-rw-r--r--sys/arch/pc532/stand/scn.c103
-rw-r--r--sys/arch/pc532/stand/scsi_hi.c303
-rw-r--r--sys/arch/pc532/stand/scsi_low.c426
-rw-r--r--sys/arch/pc532/stand/sd.c196
-rw-r--r--sys/arch/pc532/stand/so.h67
-rw-r--r--sys/arch/pc532/stand/srt0.s91
-rw-r--r--sys/arch/pc532/stand/test.c191
-rw-r--r--sys/arch/pc532/stand/tgets.c89
20 files changed, 3945 insertions, 0 deletions
diff --git a/sys/arch/pc532/stand/Makefile b/sys/arch/pc532/stand/Makefile
new file mode 100644
index 00000000000..0dd6ee9ecf3
--- /dev/null
+++ b/sys/arch/pc532/stand/Makefile
@@ -0,0 +1,98 @@
+# $NetBSD: Makefile,v 1.7.2.1 1995/10/17 00:19:13 phil Exp $
+
+# @(#)Makefile 8.1 (Berkeley) 6/10/93
+
+#DESTDIR=
+STANDDIR=${DESTDIR}/stand
+# load at 0x400000 - 18 * 1024 - 0x10000
+# that way the boot code will be at the correct
+# address if the floppy image is started from memory
+# NOTE: alloc() function takes memory after _end
+RELOC= 3EB800
+
+CONS= -DSCNCONSOLE
+DEFS= -DSTANDALONE ${CONS}
+CFLAGS= -O ${INCPATH} ${DEFS} -fwritable-strings
+
+SRCS= cons.c devopen.c scn.c scsi_low.c scsi_hi.c \
+ conf.c prf.c tgets.c machdep.c sd.c rd.c filesystem.c
+
+S= ${.CURDIR}/../../..
+SAREL=
+KERNREL=
+
+.PATH: ${S}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
+.PATH: ${S}/stand ${S}/lib/libsa
+
+INCPATH=-I${.CURDIR} -I${.CURDIR}/../.. -I${S} -I${S}/lib/libsa
+
+### find out what to use for libs
+.include "../../../lib/libkern/Makefile.inc"
+LIBKERN= ${KERNLIB}
+
+NO_NET=
+.include "../../../lib/libsa/Makefile.inc"
+LIBSA= ${SALIB}
+
+#LIBS= ${LIBSA} ${.OBJDIR}/libdrive.a \
+# ${LIBKERN} ${LIBSA} ${LIBKERN}
+LIBS= ${LIBSA} ${.OBJDIR}/libdrive.a \
+ ${LIBKERN} ${LIBSA}
+
+BOOTS= boot zboot.o
+ALL= ${BOOTS}
+
+all: ${ALL}
+
+${BOOTS}: ${LIBS}
+
+OBJS= ${SRCS:N*.h:R:S/$/.o/g}
+${.OBJDIR}/libdrive.a: ${OBJS}
+ ar crv $@ $?
+ ranlib $@
+
+# depend on DEFS
+
+devopen.o machdep.o srt0.o: Makefile
+cons.o: Makefile
+
+# startups
+
+srt0.o: ${.CURDIR}/srt0.s
+ cpp ${INCPATH} ${DEFS} ${.CURDIR}/srt0.s | as -o srt0.o
+
+# new boot
+boot: boot.o srt0.o ${LIBS}
+ ld -z -T ${RELOC} -e begin srt0.o boot.o ${LIBS} -o $@
+ @size boot
+
+zboot.o: inflate.o
+ ld -r srt0.o inflate.o $(LIBS) -o zboot.o
+
+# new boot user mode test
+TESTBOOT= boot.o test.o $(SC) ${LIBS}
+# objects from regular libc;
+SC= cerror.o syscall.o malloc.o sbrk.o getpagesize.o
+testboot: $(TESTBOOT)
+ ld -o testboot /usr/lib/crt0.o $(TESTBOOT) ${LIBS} -o $@
+
+$(SC): /usr/lib/libc.a
+ ar x /usr/lib/libc.a $(SC)
+
+# utilities
+
+install: ${ALL}
+ cp ${ALL} ${DESTDIR}/usr/mdec
+
+.include <bsd.dep.mk>
+.include <bsd.obj.mk>
+.include <bsd.subdir.mk>
+
+FRC:
+
+# clean ...
+
+clean::
+ rm -f ${ALL} ${.OBJDIR}/libdrive.a ${OBJS} boot.o srt0.o inflate.o
+
+cleandir: clean
diff --git a/sys/arch/pc532/stand/README b/sys/arch/pc532/stand/README
new file mode 100644
index 00000000000..a835dde57e6
--- /dev/null
+++ b/sys/arch/pc532/stand/README
@@ -0,0 +1,26 @@
+$NetBSD: README,v 1.2 1994/10/26 08:25:43 cgd Exp $
+
+pc532 stand/boot
+Phil Budne <phil@ultimate.com> 5/19/1994
+
+Based on hp300 stand/pboot.c, uses libso
+ (lacks the fun "spinner" that the i386 boot program displays)
+
+May be debugged under usermode (using "testboot" image)
+
+Passes howto, bootdev, & symbols to booted program;
+ r3/ magic value 0xc1e86394 (3253232532)
+ r4/ end of symbols
+ r5/ physical load address (typ 0x2000)
+ r6/ bootdev
+ r7/ howto (flags: RB_{ASKNAME,KDB,SINGLE,HALT})
+
+All files have Berzerkley style copyrights, except libso files from
+Jordan Hubbard's "libso" (which in turn come from Bruce Culbertson's
+ROM monitor); scsi_hi.c scsi_lo.c so.h
+
+TODO:
+
+check if kernel will overlap boot program!
+pick up initial how and boot dev
+
diff --git a/sys/arch/pc532/stand/boot.c b/sys/arch/pc532/stand/boot.c
new file mode 100644
index 00000000000..6301d6f1cd6
--- /dev/null
+++ b/sys/arch/pc532/stand/boot.c
@@ -0,0 +1,279 @@
+/* $NetBSD: boot.c,v 1.4.2.1 1995/10/17 00:19:15 phil Exp $ */
+
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)boot.c 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef lint
+static char rcsid[] = "$NetBSD: boot.c,v 1.4.2.1 1995/10/17 00:19:15 phil Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <a.out.h>
+#include "stand.h"
+#include "samachdep.h"
+
+/*
+ * Boot program... bits in `howto' determine whether boot stops to
+ * ask for system name. Boot device is derived from ROM provided
+ * information.
+ */
+
+extern unsigned opendev;
+extern int noconsole;
+extern int testing;
+
+char *ssym, *esym;
+
+char *name;
+char *names[] = {
+ "/netbsd", "/onetbsd", "/netbsd.old",
+};
+#define NUMNAMES (sizeof(names)/sizeof(char *))
+#define LOADADDR ((char *)0x2000)
+
+static int bdev, bctlr, bunit, bpart;
+
+main()
+{
+ int currname = 0;
+ int io;
+
+ cninit();
+ scsiinit();
+
+ printf("\n>> NetBSD BOOT pc532 [$Revision: 1.1 $]\n");
+
+ bdev = B_TYPE(bootdev);
+ bctlr = B_CONTROLLER(bootdev);
+ bunit = B_UNIT(bootdev);
+ bpart = B_PARTITION(bootdev);
+
+ for (;;) {
+ name = names[currname++];
+ if (currname == NUMNAMES)
+ currname = 0;
+
+ if (!noconsole) {
+ howto = 0;
+ getbootdev(&howto);
+ }
+ else
+ printf(": %s\n", name);
+
+ io = open(name, 0);
+
+ if (io >= 0) {
+ copyunix(howto, opendev, io);
+ close(io);
+ }
+ else
+ printf("boot: %s\n", strerror(errno));
+ }
+}
+
+/*ARGSUSED*/
+copyunix(howto, devtype, io)
+ register int howto; /* boot flags */
+ register u_int devtype; /* boot device */
+ register int io;
+{
+ struct exec x;
+ int i;
+ register char *load; /* load addr for unix */
+ register char *addr;
+ char *file;
+ int dev, ctlr, unit, part;
+
+ /* XXX use devtype? */
+ dev = B_TYPE(opendev);
+ ctlr = B_CONTROLLER(opendev);
+ unit = B_UNIT(opendev);
+ part = B_PARTITION(opendev);
+ /* get the file name part of name */
+ devparse(name, &i, &i, &i, &i, &i, &file);
+
+ i = read(io, (char *)&x, sizeof(x));
+ if (i != sizeof(x) || N_BADMAG(x)) {
+ printf("Bad format\n");
+ return;
+ }
+ addr = LOADADDR; /* Always load at LOADADDR */
+ load = (char *)(x.a_entry & 0x00ffff00); /* XXX make less magical? */
+ printf("Booting %s%d%c:%s @ 0x%x\n",
+ devsw[dev].dv_name, unit + (8*ctlr), 'a' + part, file, load);
+
+ if (testing) {
+ load = addr = alloc(2*1024*1024); /* XXX stat the file? */
+ if (!addr) {
+ printf("alloc failed\n");
+ exit(1);
+ }
+ }
+
+ /* Text */
+ printf("%d", x.a_text);
+ if (N_GETMAGIC(x) == ZMAGIC && lseek(io, 0, SEEK_SET) == -1)
+ goto shread;
+ if (read(io, addr, x.a_text) != x.a_text)
+ goto shread;
+ addr += x.a_text;
+ if (N_GETMAGIC(x) == NMAGIC)
+ while ((int)addr & CLOFSET)
+ *addr++ = 0;
+ /* Data */
+ printf("+%d", x.a_data);
+ if (read(io, addr, x.a_data) != x.a_data)
+ goto shread;
+ addr += x.a_data;
+
+ /* Bss */
+ printf("+%d", x.a_bss);
+ bzero( addr, x.a_bss );
+ addr += x.a_bss;
+
+ /* Symbols */
+ ssym = load + (addr - LOADADDR);
+ bcopy(&x.a_syms, addr, sizeof(x.a_syms));
+ addr += sizeof(x.a_syms);
+ printf(" [%d+", x.a_syms);
+ if (x.a_syms && read(io, addr, x.a_syms) != x.a_syms)
+ goto shread;
+ addr += x.a_syms;
+
+ /* read size of string table */
+ i = 0;
+ if (x.a_syms && read(io, &i, sizeof(int)) != sizeof(int))
+ goto shread;
+
+ /* read strings */
+ printf("%d]", i);
+ bcopy(&i, addr, sizeof(int));
+ if (i) {
+ i -= sizeof(int);
+ addr += sizeof(int);
+ if (read(io, addr, i) != i)
+ goto shread;
+ addr += i;
+ }
+
+ if (load != LOADADDR) {
+ bcopy(LOADADDR, load, addr - LOADADDR);
+ addr = load + (addr - LOADADDR);
+ }
+#define round_to_size(x,t) \
+ (((int)(x) + sizeof(t) - 1) & ~(sizeof(t) - 1))
+ esym = (char *)round_to_size(addr - load,int);
+#undef round_to_size
+
+ /* and note the end address of all this */
+ printf(" total=0x%x", addr);
+
+ x.a_entry &= 0xffffff;
+ printf(" start 0x%x\n", x.a_entry);
+
+#ifdef DEBUG
+ printf("ssym=0x%x esym=0x%x\n", ssym, esym);
+ printf("\n\nReturn to boot...\n");
+ getchar();
+#endif
+
+ if (!testing) {
+#ifdef __GNUC__
+ /* do NOT change order!!
+ * the following are passed as args, and are in registers
+ * clobbered by the last two movd's!!!
+ */
+ asm(" movd %0,r5" : : "g" (load));
+ asm(" movd %0,r6" : : "g" (devtype));
+ asm(" movd %0,r7" : : "g" (howto));
+
+ /* magic value for locore.s to look for (3253232532) */
+ asm(" movd %0,r3" : : "i" (0xc1e86394));
+ asm(" movd %0,r4" : : "g" (esym));
+#endif /* __GNUC__ */
+ (*((int (*)()) x.a_entry))();
+ }
+ return;
+shread:
+ printf("Short read\n");
+ return;
+}
+
+char line[100];
+
+getbootdev(howto)
+ int *howto;
+{
+ char c, *ptr = line;
+
+ printf("Boot: [[[%s%d%c:]%s][-abdrs]] :- ",
+ devsw[bdev].dv_name, bunit + (8 * bctlr), 'a'+bpart, name);
+
+ if (tgets(line)) {
+ while (c = *ptr) {
+ while (c == ' ')
+ c = *++ptr;
+ if (!c)
+ return;
+ if (c == '-')
+ while ((c = *++ptr) && c != ' ')
+ switch (c) {
+ case 'a':
+ *howto |= RB_ASKNAME;
+ continue;
+ case 'b':
+ *howto |= RB_HALT;
+ continue;
+ case 'd':
+ *howto |= RB_KDB;
+ continue;
+ case 'r':
+ *howto |= RB_DFLTROOT;
+ continue;
+ case 's':
+ *howto |= RB_SINGLE;
+ continue;
+ }
+ else {
+ name = ptr;
+ while ((c = *++ptr) && c != ' ');
+ if (c)
+ *ptr++ = 0;
+ }
+ }
+ } else
+ printf("\n");
+}
diff --git a/sys/arch/pc532/stand/conf.c b/sys/arch/pc532/stand/conf.c
new file mode 100644
index 00000000000..6f4a50da0a8
--- /dev/null
+++ b/sys/arch/pc532/stand/conf.c
@@ -0,0 +1,59 @@
+/* $NetBSD: conf.c,v 1.3 1995/08/29 21:55:42 phil Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)conf.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include "stand.h"
+
+int rdstrategy __P((void *devdata, int rw,
+ daddr_t blk, u_int size, char *buf, u_int *rsize));
+int rdopen __P((struct open_file *f, ...));
+
+int sdstrategy __P((void *devdata, int rw,
+ daddr_t blk, u_int size, char *buf, u_int *rsize));
+int sdopen __P((struct open_file *f, ...));
+
+#define sdioctl noioctl
+#define rdioctl noioctl
+
+struct devsw devsw[] = {
+ { "sd", sdstrategy, sdopen, nullsys, sdioctl }, /*0*/
+ { NULL, NULL, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL },
+ { "rd", rdstrategy, rdopen, nullsys, rdioctl }, /*3*/
+};
+
+int ndevs = (sizeof(devsw)/sizeof(devsw[0]));
diff --git a/sys/arch/pc532/stand/cons.c b/sys/arch/pc532/stand/cons.c
new file mode 100644
index 00000000000..307a58539c5
--- /dev/null
+++ b/sys/arch/pc532/stand/cons.c
@@ -0,0 +1,93 @@
+/* $NetBSD: cons.c,v 1.3 1995/08/29 21:55:43 phil Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah Hdr: cons.c 1.7 92/02/28
+ *
+ * @(#)cons.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <dev/cons.h>
+#include "samachdep.h"
+
+#ifdef SCNCONSOLE
+int scnprobe(), scninit(), scngetchar(), scnputchar();
+#endif
+
+struct consdev constab[] = {
+#ifdef SCNCONSOLE
+ { scnprobe, scninit, scngetchar, scnputchar },
+#endif
+ { 0 },
+};
+
+struct consdev *cn_tab;
+int noconsole;
+
+cninit()
+{
+ register struct consdev *cp;
+
+ cn_tab = NULL;
+ noconsole = 1;
+ 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;
+ }
+ if (cn_tab) {
+ (*cn_tab->cn_init)(cn_tab);
+ noconsole = 0;
+ }
+}
+
+cngetc()
+{
+ if (cn_tab)
+ return((*cn_tab->cn_getc)(cn_tab->cn_dev));
+ return(0);
+}
+
+cnputc(c)
+ int c;
+{
+ if (cn_tab)
+ (*cn_tab->cn_putc)(cn_tab->cn_dev, c);
+}
diff --git a/sys/arch/pc532/stand/devopen.c b/sys/arch/pc532/stand/devopen.c
new file mode 100644
index 00000000000..4ddac7c398a
--- /dev/null
+++ b/sys/arch/pc532/stand/devopen.c
@@ -0,0 +1,203 @@
+/* $NetBSD: devopen.c,v 1.4 1995/08/29 21:55:44 phil Exp $ */
+
+/*-
+ * Copyright (c) 1993 John Brezak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+
+#include "stand.h"
+#include "samachdep.h"
+
+u_int opendev;
+
+#define ispart(c) ((c) >= 'a' && (c) <= 'h')
+
+atoi(char *cp)
+{
+ int val = 0;
+ while(isdigit(*cp))
+ val = val * 10 + (*cp++ - '0');
+ return(val);
+}
+
+usage()
+{
+ printf("\
+Usage: device(adaptor, controller, drive, partition)file\n\
+ <device><unit><partitonletter>:file\n\
+");
+}
+
+devlookup(char *d, int len)
+{
+ struct devsw *dp = devsw;
+ int i;
+
+ for (i = 0; i < ndevs; i++, dp++)
+ if (dp->dv_name && strncmp(dp->dv_name, d, len) == 0)
+ return(i);
+
+ printf("No such device - Configured devices are:\n");
+ for (dp = devsw, i = 0; i < ndevs; i++, dp++)
+ if (dp->dv_name)
+ printf(" %s", dp->dv_name);
+ printf("\n");
+ errno = ENODEV;
+ return(-1);
+}
+
+/*
+ * Parse a device spec in one of two forms.
+ *
+ * dev(adapt, ctlr, unit, part)file
+ * [A-Za-z]*[0-9]*[A-Za-z]:file
+ * dev unit part
+ */
+devparse(char *fname, int *dev, int *adapt, int *ctlr, int *unit, int *part, char **file)
+{
+ int *argp, i;
+ char *s, *args[4];
+
+ /* get device name and make lower case */
+ for (s = fname; *s && *s != '/' && *s != ':' && *s != '('; s++)
+ if (isupper(*s)) *s = tolower(*s);
+
+ /* first form */
+ if (*s == '(') {
+ /* lookup device and get index */
+ if ((*dev = devlookup(fname, s - fname)) < 0)
+ goto baddev;
+
+ /* tokenize device ident */
+ args[0] = ++s;
+ for (i = 1; *s && *s != ')'; s++) {
+ if (i > 3)
+ goto baddev;
+ if (*s == ',')
+ args[i++] = ++s;
+ }
+ switch(i) {
+ case 4:
+ *adapt = atoi(args[0]);
+ *ctlr = atoi(args[1]);
+ *unit = atoi(args[2]);
+ *part = atoi(args[3]);
+ break;
+ case 3:
+ *ctlr = atoi(args[0]);
+ *unit = atoi(args[1]);
+ *part = atoi(args[2]);
+ break;
+ case 2:
+ *unit = atoi(args[0]);
+ *part = atoi(args[1]);
+ break;
+ case 1:
+ *part = atoi(args[0]);
+ break;
+ case 0:
+ break;
+ }
+ *file = ++s;
+ }
+
+ /* second form */
+ else if (*s == ':') {
+ /* isolate device */
+ for (s = fname; *s != ':' && !isdigit(*s); s++);
+
+ /* lookup device and get index */
+ if ((*dev = devlookup(fname, s - fname)) < 0)
+ goto baddev;
+
+ /* isolate unit */
+ if ((*unit = atoi(s)) > ((1 << (sizeof(char) * 8)) - 1))
+ goto bad;
+ for (; isdigit(*s); s++);
+
+ /* translate partition */
+ if (!ispart(*s))
+ goto bad;
+
+ *part = *s++ - 'a';
+ if (*s != ':')
+ goto bad;
+ *file = ++s;
+ }
+
+ /* no device present */
+ else
+ *file = fname;
+
+ /* return the remaining unparsed part as the file to boot */
+ return(0);
+
+ bad:
+ usage();
+
+ baddev:
+ return(-1);
+}
+
+
+devopen(f, fname, file)
+ struct open_file *f;
+ const char *fname;
+ char **file;
+{
+ int n, error;
+ int dev, ctlr, unit, part;
+ int adapt = 0; /* XXX not used on HP */
+ struct devsw *dp = &devsw[0];
+
+ dev = B_TYPE(bootdev);
+ ctlr = B_CONTROLLER(bootdev);
+ unit = B_UNIT(bootdev);
+ part = B_PARTITION(bootdev);
+
+ if (error = devparse(fname, &dev, &adapt, &ctlr, &unit, &part, file))
+ return(error);
+
+ dp = &devsw[dev];
+
+ if (!dp->dv_open)
+ return(ENODEV);
+
+ opendev = MAKEBOOTDEV(dev, adapt, ctlr, unit, part);
+
+ f->f_dev = dp;
+
+ if ((error = (*dp->dv_open)(f, ctlr, unit, part)) == 0)
+ return(0);
+
+ printf("%s(%d,%d,%d,%d): %s\n", devsw[dev].dv_name,
+ adapt, ctlr, unit, part, strerror(error));
+
+ return(error);
+}
diff --git a/sys/arch/pc532/stand/filesystem.c b/sys/arch/pc532/stand/filesystem.c
new file mode 100644
index 00000000000..3d0ff77b8d1
--- /dev/null
+++ b/sys/arch/pc532/stand/filesystem.c
@@ -0,0 +1,40 @@
+/* $NetBSD: filesystem.c,v 1.2 1994/10/26 08:25:48 cgd Exp $ */
+
+/*
+ * Copyright (c) 1993 Philip A. Nelson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Philip A. Nelson.
+ * 4. The name of Philip A. Nelson may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PHILIP NELSON BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stand.h>
+#include <ufs.h>
+
+struct fs_ops file_system[] =
+{ ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat };
+
+int nfsys = sizeof(file_system)/sizeof(struct fs_ops);
diff --git a/sys/arch/pc532/stand/inflate.c b/sys/arch/pc532/stand/inflate.c
new file mode 100644
index 00000000000..3ebe08c086a
--- /dev/null
+++ b/sys/arch/pc532/stand/inflate.c
@@ -0,0 +1,1433 @@
+/*
+ * Copyright (c) 1995 Matthias Pfaller.
+ *
+ * Most of this code is from the unzip512 distribution and was put
+ * in the public domain by Mark Adler 1994.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Matthias Pfaller.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: inflate.c,v 1.1 1995/10/18 08:51:23 deraadt Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <a.out.h>
+#include "stand.h"
+#include "samachdep.h"
+
+#ifndef EOF
+#define EOF -1
+#endif
+typedef unsigned char uch; /* code assumes unsigned bytes; these type- */
+typedef unsigned short ush; /* defs replace byte/UWORD/ULONG (which are */
+typedef unsigned long ulg; /* predefined on some systems) & match zip */
+
+extern int qflag;
+extern uch slide[];
+extern ulg crc_32_tab[];
+
+#define NEXTBYTE nextbyte()
+#define FLUSH(n) flush(n)
+#define WSIZE 0x8000
+#define memzero(dest, len) bzero(dest, len)
+
+/* Function prototypes */
+#ifndef OF
+# ifdef __STDC__
+# define OF(a) a
+# else /* !__STDC__ */
+# define OF(a) ()
+# endif /* ?__STDC__ */
+#endif
+
+/* From: funzip.c -- put in the public domain by Mark Adler */
+
+#define VERSION "3.83 of 28 August 1994"
+
+/*
+
+ All funzip does is take a zip file from stdin and decompress the
+ first entry to stdout. The entry has to be either deflated or
+ stored. If the entry is encrypted, then the decryption password
+ must be supplied on the command line as the first argument.
+
+ funzip needs to be linked with inflate.o and crypt.o compiled from
+ the unzip source. If decryption is desired, the full version of
+ crypt.c (and crypt.h) from zcrypt21.zip or later must be used.
+
+ */
+
+/* compression methods */
+#define STORED 0
+#define DEFLATED 8
+
+/* PKZIP header definitions */
+#define ZIPMAG 0x4b50 /* two-byte zip lead-in */
+#define LOCREM 0x0403 /* remaining two bytes in zip signature */
+#define LOCSIG 0x04034b50L /* full signature */
+#define LOCFLG 4 /* offset of bit flag */
+#define CRPFLG 1 /* bit for encrypted entry */
+#define EXTFLG 8 /* bit for extended local header */
+#define LOCHOW 6 /* offset of compression method */
+#define LOCTIM 8 /* file mod time (for decryption) */
+#define LOCCRC 12 /* offset of crc */
+#define LOCSIZ 16 /* offset of compressed size */
+#define LOCLEN 20 /* offset of uncompressed length */
+#define LOCFIL 24 /* offset of file name field length */
+#define LOCEXT 26 /* offset of extra field length */
+#define LOCHDR 28 /* size of local header, including LOCREM */
+#define EXTHDR 16 /* size of extended local header, inc sig */
+
+/* GZIP header definitions */
+#define GZPMAG 0x8b1f /* two-byte gzip lead-in */
+#define GZPHOW 0 /* offset of method number */
+#define GZPFLG 1 /* offset of gzip flags */
+#define GZPMUL 2 /* bit for multiple-part gzip file */
+#define GZPISX 4 /* bit for extra field present */
+#define GZPISF 8 /* bit for filename present */
+#define GZPISC 16 /* bit for comment present */
+#define GZPISE 32 /* bit for encryption */
+#define GZPTIM 2 /* offset of Unix file modification time */
+#define GZPEXF 6 /* offset of extra flags */
+#define GZPCOS 7 /* offset of operating system compressed on */
+#define GZPHDR 8 /* length of minimal gzip header */
+
+/* Macros for getting two-byte and four-byte header values */
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+/* Function prototypes */
+ulg updcrc OF((uch *, ulg));
+int inflate OF((void));
+void err OF((int, char *));
+
+/* Globals */
+uch *outptr; /* points to next byte in output buffer */
+ulg outcnt; /* bytes in output buffer */
+ulg outsiz; /* total bytes written to out */
+int encrypted; /* flag to turn on decryption */
+int qflag = 1; /* turn off messages in inflate.c */
+uch slide[WSIZE];
+uch *addr, *load, *esym;
+extern uch *r3, *r6, *r7;
+int bsize;
+
+/* Masks for inflate.c */
+ush mask_bits[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+extern uch input_data[];
+uch *datap = input_data;
+struct exec x;
+
+int nextbyte()
+{
+ extern int input_len;
+
+ if (!(input_len & 0x1fff))
+ twiddle();
+ if (input_len-- > 0)
+ return(*datap++);
+ else
+ return(EOF);
+}
+
+int nextblock(p, n)
+char *p;
+int n;
+{
+ extern int input_len;
+
+ twiddle();
+ if (input_len < n)
+ return(0);
+ memcpy(p, datap, n);
+ input_len -= n;
+ datap += n;
+ return(n);
+}
+
+ulg updcrc(s, n)
+uch *s; /* pointer to bytes to pump through */
+ulg n; /* number of bytes in s[] */
+/* Run a set of bytes through the crc shift register. If s is a NULL
+ pointer, then initialize the crc shift register contents instead.
+ Return the current crc in either case. */
+{
+ register ulg c; /* temporary variable */
+
+ static ulg crc = 0xffffffffL; /* shift register contents */
+
+ if (s == (uch *)NULL)
+ c = 0xffffffffL;
+ else
+ {
+ c = crc;
+ while (n--)
+ c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
+ }
+ crc = c;
+ return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
+}
+
+void nextstate()
+{
+ static int state = 0;
+
+ switch (state) {
+ case 0:
+ if (N_BADMAG(x))
+ panic("Bad exec format\n");
+ load = addr = (uch *)(x.a_entry & 0x00ffff00);
+ printf("Uncompressing @ 0x%x\n", addr);
+ bsize = x.a_text;
+ if (N_GETMAGIC(x) == ZMAGIC) {
+ bcopy(&x, addr, sizeof(x));
+ addr += sizeof(x);
+ bsize -= sizeof(x);
+ }
+ printf("%d", x.a_text);
+ state = 1;
+ break;
+
+ case 1:
+ if (N_GETMAGIC(x) == NMAGIC)
+ while ((int)addr & CLOFSET)
+ *addr++ = 0;
+ bsize = x.a_data;
+ printf("+%d", x.a_data);
+ state = 2;
+ break;
+
+ case 2:
+ printf("+%d", x.a_bss);
+ bzero(addr, x.a_bss );
+ addr += x.a_bss;
+ bcopy(&x.a_syms, addr, sizeof(x.a_syms));
+ addr += sizeof(x.a_syms);
+ printf(" [%d+", x.a_syms);
+ if (x.a_syms) {
+ bsize = x.a_syms + sizeof(int);
+ state = 3;
+ break;
+ }
+ printf("0]");
+
+ case 4:
+ printf(" total 0x%x", addr);
+ x.a_entry &= 0xffffff;
+ printf(" start 0x%x\n", x.a_entry);
+#define round_to_size(x,t) \
+ (((int)(x) + sizeof(t) - 1) & ~(sizeof(t) - 1))
+ esym = (char *)round_to_size(addr - load, int);
+#undef round_to_size
+ state = -1;
+ break;
+
+ case 3:
+ printf("%d]", ((int *)addr)[-1]);
+ bsize = ((int *)addr)[-1] - sizeof(int);
+ state = 4;
+ break;
+
+ case -1:
+ printf("Already at EOF\n");
+ break;
+ }
+}
+
+int flush(w) /* used by inflate.c (FLUSH macro) */
+ulg w; /* number of bytes to flush */
+{
+ uch *p = slide;
+
+ updcrc(slide, w);
+ outsiz += w;
+
+ while (bsize <= w) {
+ bcopy(p, addr, bsize);
+ p += bsize;
+ addr += bsize;
+ w -= bsize;
+ nextstate();
+ }
+ if (w) {
+ bcopy(p, addr, w);
+ addr += w;
+ bsize -= w;
+ }
+ return(0);
+}
+
+main()
+{
+ ush n;
+ uch h[LOCHDR]; /* first local header (GZPHDR < LOCHDR) */
+ int g = 0; /* true if gzip format */
+ char *s = "";
+
+ cninit();
+
+ addr = (uch *)&x;
+ bsize = sizeof(x);
+
+ /* read local header, check validity, and skip name and extra fields */
+ n = nextbyte(); n |= nextbyte() << 8;
+ if (n == ZIPMAG)
+ {
+ if (nextblock((char *)h, LOCHDR) != LOCHDR || SH(h) != LOCREM)
+ panic("invalid zip file");
+ if (SH(h + LOCHOW) != STORED && SH(h + LOCHOW) != DEFLATED)
+ panic("first entry not deflated or stored--can't funzip");
+ for (n = SH(h + LOCFIL); n--; ) g = nextbyte();
+ for (n = SH(h + LOCEXT); n--; ) g = nextbyte();
+ g = 0;
+ encrypted = h[LOCFLG] & CRPFLG;
+ }
+ else if (n == GZPMAG)
+ {
+ if (nextblock((char *)h, GZPHDR) != GZPHDR)
+ panic("invalid gzip file");
+ if (h[GZPHOW] != DEFLATED)
+ panic("gzip file not deflated");
+ if (h[GZPFLG] & GZPMUL)
+ panic("cannot handle multi-part gzip files");
+ if (h[GZPFLG] & GZPISX)
+ {
+ n = nextbyte(); n |= nextbyte() << 8;
+ while (n--) g = nextbyte();
+ }
+ if (h[GZPFLG] & GZPISF)
+ while ((g = nextbyte()) != 0 && g != EOF) ;
+ if (h[GZPFLG] & GZPISC)
+ while ((g = nextbyte()) != 0 && g != EOF) ;
+ g = 1;
+ encrypted = h[GZPFLG] & GZPISE;
+ }
+ else
+ panic("input not a zip or gzip file");
+
+ /* if entry encrypted, decrypt and validate encryption header */
+ if (encrypted)
+ panic("cannot decrypt entry (need to recompile with full crypt.c)");
+
+ /* prepare output buffer and crc */
+ outptr = slide;
+ outcnt = 0L;
+ outsiz = 0L;
+ updcrc(NULL, 0L);
+
+ /* decompress */
+ if (g || h[LOCHOW])
+ { /* deflated entry */
+ int r;
+
+ if ((r = inflate()) != 0)
+ if (r == 3)
+ panic("out of memory");
+ else
+ panic("invalid compressed data--format violated");
+ inflate_free();
+ }
+ else
+ { /* stored entry */
+ register ulg n;
+
+ n = LG(h + LOCLEN);
+ if (n != LG(h + LOCSIZ)) {
+ printf("len %ld, siz %ld\n", n, LG(h + LOCSIZ));
+ panic("invalid compressed data--length mismatch");
+ }
+ while (n--) {
+ ush c = nextbyte();
+ *outptr++ = (uch)c;
+ if (++outcnt == WSIZE) /* do FlushOutput() */
+ {
+ flush(outcnt);
+ outptr = slide;
+ outcnt = 0L;
+ }
+ }
+ if (outcnt) /* flush one last time; no need to reset outptr/outcnt */
+ flush(outcnt);
+ }
+
+ /* if extended header, get it */
+ if (g)
+ {
+ if (nextblock((char *)h + LOCCRC, 8) != 8)
+ panic("gzip file ended prematurely");
+ }
+ else
+ if ((h[LOCFLG] & EXTFLG) &&
+ nextblock((char *)h + LOCCRC - 4, EXTHDR) != EXTHDR)
+ panic("zip file ended prematurely");
+
+ /* validate decompression */
+ if (LG(h + LOCCRC) != updcrc(slide, 0L))
+ panic("invalid compressed data--crc error");
+ if (LG(h + (g ? LOCSIZ : LOCLEN)) != outsiz)
+ panic("invalid compressed data--length error");
+
+ /* check if there are more entries */
+ if (!g && nextblock((char *)h, 4) == 4 && LG(h) == LOCSIG)
+ printf("funzip warning: zip file has more than one entry--rest ignored\n");
+
+ asm(" movd %0,r3" : : "g" (r3)); /* magic */
+ asm(" movd %0,r4" : : "g" (esym));
+ asm(" movd %0,r5" : : "g" (load));
+ asm(" movd %0,r6" : : "g" (r6)); /* devtype */
+ asm(" movd %0,r7" : : "g" (r7)); /* howto */
+
+ (*((int (*)()) x.a_entry))();
+}
+
+/* Table of CRC-32's of all single-byte values (made by makecrc.c) */
+ulg crc_32_tab[] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+
+/* From: inflate.c -- put in the public domain by Mark Adler
+ version c14o, 23 August 1994 */
+
+/*
+ Inflate deflated (PKZIP's method 8 compressed) data. The compression
+ method searches for as much of the current string of bytes (up to a
+ length of 258) in the previous 32K bytes. If it doesn't find any
+ matches (of at least length 3), it codes the next byte. Otherwise, it
+ codes the length of the matched string and its distance backwards from
+ the current position. There is a single Huffman code that codes both
+ single bytes (called "literals") and match lengths. A second Huffman
+ code codes the distance information, which follows a length code. Each
+ length or distance code actually represents a base value and a number
+ of "extra" (sometimes zero) bits to get to add to the base value. At
+ the end of each deflated block is a special end-of-block (EOB) literal/
+ length code. The decoding process is basically: get a literal/length
+ code; if EOB then done; if a literal, emit the decoded byte; if a
+ length then get the distance and emit the referred-to bytes from the
+ sliding window of previously emitted data.
+
+ There are (currently) three kinds of inflate blocks: stored, fixed, and
+ dynamic. The compressor outputs a chunk of data at a time and decides
+ which method to use on a chunk-by-chunk basis. A chunk might typically
+ be 32K to 64K, uncompressed. If the chunk is uncompressible, then the
+ "stored" method is used. In this case, the bytes are simply stored as
+ is, eight bits per byte, with none of the above coding. The bytes are
+ preceded by a count, since there is no longer an EOB code.
+
+ If the data is compressible, then either the fixed or dynamic methods
+ are used. In the dynamic method, the compressed data is preceded by
+ an encoding of the literal/length and distance Huffman codes that are
+ to be used to decode this block. The representation is itself Huffman
+ coded, and so is preceded by a description of that code. These code
+ descriptions take up a little space, and so for small blocks, there is
+ a predefined set of codes, called the fixed codes. The fixed method is
+ used if the block ends up smaller that way (usually for quite small
+ chunks); otherwise the dynamic method is used. In the latter case, the
+ codes are customized to the probabilities in the current block and so
+ can code it much better than the pre-determined fixed codes can.
+
+ The Huffman codes themselves are decoded using a mutli-level table
+ lookup, in order to maximize the speed of decoding plus the speed of
+ building the decoding tables. See the comments below that precede the
+ lbits and dbits tuning parameters.
+ */
+
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+#define PKZIP_BUG_WORKAROUND /* PKZIP 1.93a problem--live with it */
+
+/*
+ inflate.h must supply the uch slide[WSIZE] array and the NEXTBYTE,
+ FLUSH() and memzero macros. If the window size is not 32K, it
+ should also define WSIZE. If INFMOD is defined, it can include
+ compiled functions to support the NEXTBYTE and/or FLUSH() macros.
+ There are defaults for NEXTBYTE and FLUSH() below for use as
+ examples of what those functions need to do. Normally, you would
+ also want FLUSH() to compute a crc on the data. inflate.h also
+ needs to provide these typedefs:
+
+ typedef unsigned char uch;
+ typedef unsigned short ush;
+ typedef unsigned long ulg;
+
+ This module uses the external functions malloc() and free() (and
+ probably memset() or bzero() in the memzero() macro). Their
+ prototypes are normally found in <string.h> and <stdlib.h>.
+ */
+
+/* Warning: the fwrite above might not work on 16-bit compilers, since
+ 0x8000 might be interpreted as -32,768 by the library function. */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model).
+ Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16
+ means that v is a literal, 16 < e < 32 means that v is a pointer to
+ the next table, which codes e - 16 bits, and lastly e == 99 indicates
+ an unused code. If a code with e == 99 is looked up, this implies an
+ error in the data. */
+struct huft {
+ uch e; /* number of extra bits or operation */
+ uch b; /* number of bits in this code or subcode */
+ union {
+ ush n; /* literal, length base, or distance base */
+ struct huft *t; /* pointer to next level of table */
+ } v;
+};
+
+int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
+ struct huft **, int *));
+int huft_free OF((struct huft *));
+int inflate_codes OF((struct huft *, struct huft *, int, int));
+int inflate_stored OF((void));
+int inflate_fixed OF((void));
+int inflate_dynamic OF((void));
+int inflate_block OF((int *));
+int inflate OF((void));
+int inflate_free OF((void));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+ stream to find repeated byte strings. This is implemented here as a
+ circular buffer. The index is updated simply by incrementing and then
+ and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area. It is assumed
+ to be usable as if it were declared "uch slide[32768];" or as just
+ "uch *slide;" and then malloc'ed in the latter case. The definition
+ must be in unzip.h, included above. */
+unsigned wp; /* current position in slide */
+
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
+static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+static ush cpdext[] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/* And'ing with mask[n] masks the lower n bits */
+ush mask[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* Macros for inflate() bit peeking and grabbing.
+ The usage is:
+
+ NEEDBITS(j)
+ x = b & mask[j];
+ DUMPBITS(j)
+
+ where NEEDBITS makes sure that b has at least j bits in it, and
+ DUMPBITS removes the bits from b. The macros use the variable k
+ for the number of bits in b. Normally, b and k are register
+ variables for speed, and are initialized at the begining of a
+ routine that uses these macros from a global bit buffer and count.
+
+ In order to not ask for more bits than there are in the compressed
+ stream, the Huffman tables are constructed to only ask for just
+ enough bits to make up the end-of-block code (value 256). Then no
+ bytes need to be "returned" to the buffer at the end of the last
+ block. See the huft_build() routine.
+ */
+
+ulg bb; /* bit buffer */
+unsigned bk; /* bits in bit buffer */
+
+#ifndef CHECK_EOF
+# define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
+#else
+# define NEEDBITS(n) {while(k<(n)){int c=NEXTBYTE;if(c==EOF)return 1;\
+ b|=((ulg)c)<<k;k+=8;}}
+#endif /* Piet Plomp: change "return 1" to "break" */
+
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+int lbits = 9; /* bits in base literal/length lookup table */
+int dbits = 6; /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16 /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+
+unsigned hufts; /* track memory usage */
+
+void *malloc(n)
+int n;
+{
+ void *p;
+ p = alloc(n + sizeof(n));
+ if (!p)
+ return(NULL);
+ *((int *)p) = n;
+ p += sizeof(n);
+ return(p);
+}
+
+int huft_build(b, n, s, d, e, t, m)
+unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
+unsigned n; /* number of codes (assumed <= N_MAX) */
+unsigned s; /* number of simple-valued codes (0..s-1) */
+ush *d; /* list of base values for non-simple codes */
+ush *e; /* list of extra bits for non-simple codes */
+struct huft **t; /* result: starting table */
+int *m; /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return zero on success, one if
+ the given code set is incomplete (the tables are still built in this
+ case), two if the input is invalid (all zero length codes or an
+ oversubscribed set of lengths), and three if not enough memory.
+ The code with value 256 is special, and the tables are constructed
+ so that no bits beyond that code are fetched when that code is
+ decoded. */
+{
+ unsigned a; /* counter for codes of length k */
+ unsigned c[BMAX+1]; /* bit length count table */
+ unsigned el; /* length of EOB code (value 256) */
+ unsigned f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register unsigned i; /* counter, current code */
+ register unsigned j; /* counter */
+ register int k; /* number of bits in current code */
+ int lx[BMAX+1]; /* memory for l[-1..BMAX-1] */
+ int *l = lx+1; /* stack of bits per table */
+ register unsigned *p; /* pointer into c[], b[], or v[] */
+ register struct huft *q; /* points to current table */
+ struct huft r; /* table entry for structure assignment */
+ struct huft *u[BMAX]; /* table stack */
+ static unsigned v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ unsigned x[BMAX+1]; /* bit offsets, then code stack */
+ unsigned *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ unsigned z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */
+ memzero((char *)c, sizeof(c));
+ p = b; i = n;
+ do {
+ c[*p]++; p++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (struct huft *)NULL;
+ *m = 0;
+ return 0;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((unsigned)*m < j)
+ *m = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((unsigned)*m > i)
+ *m = i;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return 2; /* bad input: more codes than bits */
+ if ((y -= c[i]) < 0)
+ return 2;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = l[-1] = 0; /* no bits decoded yet */
+ u[0] = (struct huft *)NULL; /* just to keep compilers happy */
+ q = (struct huft *)NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l[h])
+ {
+ w += l[h++]; /* add bits already decoded */
+
+ /* compute minimum size table less than or equal to *m bits */
+ z = (z = g - w) > (unsigned)*m ? *m : z; /* upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ if ((unsigned)w + j > el && (unsigned)w < el)
+ j = el - w; /* make EOB code end at table */
+ z = 1 << j; /* table entries for j-bit table */
+ l[h] = j; /* set table size in stack */
+
+ /* allocate and link in new table */
+ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+ (struct huft *)NULL)
+ {
+ if (h)
+ huft_free(u[0]);
+ return 3; /* not enough memory */
+ }
+ hufts += z + 1; /* track memory usage */
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->v.t)) = (struct huft *)NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.b = (uch)l[h-1]; /* bits to dump before this table */
+ r.e = (uch)(16 + j); /* bits in this table */
+ r.v.t = q; /* pointer to this table */
+ j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.b = (uch)(k - w);
+ if (p >= v + n)
+ r.e = 99; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
+ r.v.n = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
+ r.v.n = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ w -= l[--h]; /* don't need to update q */
+ }
+ }
+
+
+ /* return actual size of base table */
+ *m = l[0];
+
+
+ /* Return true (1) if we were given an incomplete table */
+ return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t; /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register struct huft *p, *q;
+
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ p = t;
+ while (p != (struct huft *)NULL)
+ {
+ q = (--p)->v.t;
+ free(((void *)p) - sizeof(int), ((int *)p)[-1]);
+ p = q;
+ }
+ return 0;
+}
+
+
+
+#ifdef ASM_INFLATECODES
+# define inflate_codes(tl,td,bl,bd) flate_codes(tl,td,bl,bd,(uch *)slide)
+ int flate_codes OF((struct huft *, struct huft *, int, int, uch *));
+
+#else
+
+int inflate_codes(tl, td, bl, bd)
+struct huft *tl, *td; /* literal/length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+ Return an error code or zero if it all goes ok. */
+{
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+
+ /* inflate the coded data */
+ ml = mask[bl]; /* precompute masks for speed */
+ md = mask[bd];
+ while (1) /* do until end of block */
+ {
+ NEEDBITS((unsigned)bl)
+ if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask[e]))->e) > 16);
+ DUMPBITS(t->b)
+ if (e == 16) /* then it's a literal */
+ {
+ slide[w++] = (uch)t->v.n;
+ if (w == WSIZE)
+ {
+ FLUSH(w);
+ w = 0;
+ }
+ }
+ else /* it's an EOB or a length */
+ {
+ /* exit if end of block */
+ if (e == 15)
+ break;
+
+ /* get length of block to copy */
+ NEEDBITS(e)
+ n = t->v.n + ((unsigned)b & mask[e]);
+ DUMPBITS(e);
+
+ /* decode distance of block to copy */
+ NEEDBITS((unsigned)bd)
+ if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask[e]))->e) > 16);
+ DUMPBITS(t->b)
+ NEEDBITS(e)
+ d = w - t->v.n - ((unsigned)b & mask[e]);
+ DUMPBITS(e)
+
+ /* do the copy */
+ do {
+ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ slide[w++] = slide[d++];
+ } while (--e);
+ if (w == WSIZE)
+ {
+ FLUSH(w);
+ w = 0;
+ }
+ } while (n);
+ }
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+
+
+ /* done */
+ return 0;
+}
+
+#endif /* ASM_INFLATECODES */
+
+
+
+int inflate_stored()
+/* "decompress" an inflated type 0 (stored) block. */
+{
+ unsigned n; /* number of bytes in block */
+ unsigned w; /* current window position */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+
+ /* go to byte boundary */
+ n = k & 7;
+ DUMPBITS(n);
+
+
+ /* get the length and its complement */
+ NEEDBITS(16)
+ n = ((unsigned)b & 0xffff);
+ DUMPBITS(16)
+ NEEDBITS(16)
+ if (n != (unsigned)((~b) & 0xffff))
+ return 1; /* error in compressed data */
+ DUMPBITS(16)
+
+
+ /* read and output the compressed data */
+ while (n--)
+ {
+ NEEDBITS(8)
+ slide[w++] = (uch)b;
+ if (w == WSIZE)
+ {
+ FLUSH(w);
+ w = 0;
+ }
+ DUMPBITS(8)
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+ return 0;
+}
+
+
+/* Globals for literal tables (built once) */
+struct huft *fixed_tl = (struct huft *)NULL;
+struct huft *fixed_td;
+int fixed_bl, fixed_bd;
+
+int inflate_fixed()
+/* decompress an inflated type 1 (fixed Huffman codes) block. We should
+ either replace this with a custom decoder, or at least precompute the
+ Huffman tables. */
+{
+ /* if first time, set up tables for fixed blocks */
+ if (fixed_tl == (struct huft *)NULL)
+ {
+ int i; /* temporary variable */
+ static unsigned l[288]; /* length list for huft_build */
+
+ /* literal table */
+ for (i = 0; i < 144; i++)
+ l[i] = 8;
+ for (; i < 256; i++)
+ l[i] = 9;
+ for (; i < 280; i++)
+ l[i] = 7;
+ for (; i < 288; i++) /* make a complete, but wrong code set */
+ l[i] = 8;
+ fixed_bl = 7;
+ if ((i = huft_build(l, 288, 257, cplens, cplext,
+ &fixed_tl, &fixed_bl)) != 0)
+ {
+ fixed_tl = (struct huft *)NULL;
+ return i;
+ }
+
+ /* distance table */
+ for (i = 0; i < 30; i++) /* make an incomplete code set */
+ l[i] = 5;
+ fixed_bd = 5;
+ if ((i = huft_build(l, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd)) > 1)
+ {
+ huft_free(fixed_tl);
+ fixed_tl = (struct huft *)NULL;
+ return i;
+ }
+ }
+
+
+ /* decompress until an end-of-block code */
+ return inflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd) != 0;
+}
+
+
+
+int inflate_dynamic()
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+ int i; /* temporary variables */
+ unsigned j;
+ unsigned l; /* last length */
+ unsigned m; /* mask for bit lengths table */
+ unsigned n; /* number of lengths to get */
+ struct huft *tl; /* literal/length code table */
+ struct huft *td; /* distance code table */
+ int bl; /* lookup bits for tl */
+ int bd; /* lookup bits for td */
+ unsigned nb; /* number of bit length codes */
+ unsigned nl; /* number of literal/length codes */
+ unsigned nd; /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+ static unsigned ll[288+32]; /* literal/length and distance code lengths */
+#else
+ static unsigned ll[286+30]; /* literal/length and distance code lengths */
+#endif
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in table lengths */
+ NEEDBITS(5)
+ nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
+ DUMPBITS(5)
+ NEEDBITS(5)
+ nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
+ DUMPBITS(5)
+ NEEDBITS(4)
+ nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
+ DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+ if (nl > 288 || nd > 32)
+#else
+ if (nl > 286 || nd > 30)
+#endif
+ return 1; /* bad lengths */
+
+
+ /* read in bit-length-code lengths */
+ for (j = 0; j < nb; j++)
+ {
+ NEEDBITS(3)
+ ll[border[j]] = (unsigned)b & 7;
+ DUMPBITS(3)
+ }
+ for (; j < 19; j++)
+ ll[border[j]] = 0;
+
+
+ /* build decoding table for trees--single level, 7 bit lookup */
+ bl = 7;
+ if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
+ {
+ if (i == 1)
+ huft_free(tl);
+ return i; /* incomplete code set */
+ }
+
+
+ /* read in literal and distance code lengths */
+ n = nl + nd;
+ m = mask[bl];
+ i = l = 0;
+ while ((unsigned)i < n)
+ {
+ NEEDBITS((unsigned)bl)
+ j = (td = tl + ((unsigned)b & m))->b;
+ DUMPBITS(j)
+ j = td->v.n;
+ if (j < 16) /* length of code in bits (0..15) */
+ ll[i++] = l = j; /* save last length in l */
+ else if (j == 16) /* repeat last length 3 to 6 times */
+ {
+ NEEDBITS(2)
+ j = 3 + ((unsigned)b & 3);
+ DUMPBITS(2)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = l;
+ }
+ else if (j == 17) /* 3 to 10 zero length codes */
+ {
+ NEEDBITS(3)
+ j = 3 + ((unsigned)b & 7);
+ DUMPBITS(3)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ else /* j == 18: 11 to 138 zero length codes */
+ {
+ NEEDBITS(7)
+ j = 11 + ((unsigned)b & 0x7f);
+ DUMPBITS(7)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ }
+
+
+ /* free decoding table for trees */
+ huft_free(tl);
+
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+
+ /* build the decoding tables for literal/length and distance codes */
+ bl = lbits;
+ if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+ {
+ return i; /* incomplete code set */
+ }
+ bd = dbits;
+ if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+ {
+ if (i == 1 && !qflag) {
+#ifdef PKZIP_BUG_WORKAROUND
+ i = 0;
+ }
+#else
+ huft_free(td);
+ }
+ huft_free(tl);
+ return i; /* incomplete code set */
+#endif
+ }
+
+
+ /* decompress until an end-of-block code */
+ if (inflate_codes(tl, td, bl, bd))
+ return 1;
+
+
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+ return 0;
+}
+
+
+
+int inflate_block(e)
+int *e; /* last block flag */
+/* decompress an inflated block */
+{
+ unsigned t; /* block type */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in last block bit */
+ NEEDBITS(1)
+ *e = (int)b & 1;
+ DUMPBITS(1)
+
+
+ /* read in block type */
+ NEEDBITS(2)
+ t = (unsigned)b & 3;
+ DUMPBITS(2)
+
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+
+ /* inflate that block type */
+ if (t == 2)
+ return inflate_dynamic();
+ if (t == 0)
+ return inflate_stored();
+ if (t == 1)
+ return inflate_fixed();
+
+
+ /* bad block type */
+ return 2;
+}
+
+
+
+int inflate()
+/* decompress an inflated entry */
+{
+ int e; /* last block flag */
+ int r; /* result code */
+ unsigned h; /* maximum struct huft's malloc'ed */
+
+
+ /* initialize window, bit buffer */
+ wp = 0;
+ bk = 0;
+ bb = 0;
+
+
+ /* decompress until the last block */
+ h = 0;
+ do {
+ hufts = 0;
+ if ((r = inflate_block(&e)) != 0)
+ return r;
+ if (hufts > h)
+ h = hufts;
+ } while (!e);
+
+
+ /* flush out slide */
+ FLUSH(wp);
+
+
+ /* return success */
+ return 0;
+}
+
+
+
+int inflate_free()
+{
+ if (fixed_tl != (struct huft *)NULL)
+ {
+ huft_free(fixed_td);
+ huft_free(fixed_tl);
+ fixed_td = fixed_tl = (struct huft *)NULL;
+ }
+ return 0;
+}
diff --git a/sys/arch/pc532/stand/machdep.c b/sys/arch/pc532/stand/machdep.c
new file mode 100644
index 00000000000..ec044477f0b
--- /dev/null
+++ b/sys/arch/pc532/stand/machdep.c
@@ -0,0 +1,98 @@
+/* $NetBSD: machdep.c,v 1.2 1994/10/26 08:25:49 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994 Philip L. Budne.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Philip L. Budne.
+ * 4. The name of Philip L. Budne may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PHILIP NELSON BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * pc532 standalone machdep code
+ * Phil Budne, May 10, 1994
+ *
+ */
+
+#include <sys/types.h>
+#include "samachdep.h"
+
+int testing = 0;
+
+void
+bzero( char *addr, int len )
+{
+ while (len-- > 0)
+ *addr++ = '\0';
+}
+
+/* XXX TEMP; would like to use code more like hp300 scsi.c */
+
+void
+scsiinit(void)
+{
+}
+
+int
+scsialive(int ctlr)
+{
+ return 1; /* controller always alive! */
+}
+
+/* call functions in scsi_hi.c */
+#include "so.h"
+
+int
+scsi_tt_read(ctlr, slave, buf, len, blk, nblk)
+ int ctlr, slave;
+ u_char *buf;
+ u_int len;
+ daddr_t blk;
+ u_int nblk;
+{
+#if 0
+printf("scsi_tt_read ctlr %d, slave %d, len %d, blk %d, nblk %d\n",
+ ctlr, slave, len, blk, nblk );
+#endif
+ if (sc_rdwt(DISK_READ, blk, buf, nblk, 1<<slave, 0) == 0)
+ return 0;
+ return -2;
+}
+
+int
+scsi_tt_write(ctlr, slave, buf, len, blk, nblk)
+ int ctlr, slave;
+ u_char *buf;
+ u_int len;
+ daddr_t blk;
+ u_int nblk;
+{
+#if 0
+ if (sc_rdwt(DISK_WRITE, blk, buf, nblk, 1<<slave, 0) == 0)
+ return 0;
+#endif
+ return -2;
+}
diff --git a/sys/arch/pc532/stand/prf.c b/sys/arch/pc532/stand/prf.c
new file mode 100644
index 00000000000..e9db7e63e57
--- /dev/null
+++ b/sys/arch/pc532/stand/prf.c
@@ -0,0 +1,79 @@
+/* $NetBSD: prf.c,v 1.2 1994/10/26 08:25:50 cgd Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)prf.c 8.1 (Berkeley) 6/10/93
+ */
+
+getchar()
+{
+ register int c;
+
+ while((c = cngetc()) == 0)
+ ;
+ if (c == '\r')
+ c = '\n';
+ else if (c == ('c'&037)) {
+ panic("^C");
+ /* NOTREACHED */
+ }
+ if (c != '\b' && c != '\177')
+ putchar(c);
+ return(c);
+}
+
+tgetchar()
+{
+ register int c;
+
+ if ((c = cngetc()) == 0)
+ return(0);
+
+ if (c == '\r')
+ c = '\n';
+ else if (c == ('c'&037)) {
+ panic("^C");
+ /* NOTREACHED */
+ }
+ if (c != '\b' && c != '\177')
+ putchar(c);
+ return(c);
+}
+
+putchar(c)
+ register int c;
+{
+ cnputc(c);
+ if (c == '\n')
+ cnputc('\r');
+}
diff --git a/sys/arch/pc532/stand/rd.c b/sys/arch/pc532/stand/rd.c
new file mode 100644
index 00000000000..4f3c3620a68
--- /dev/null
+++ b/sys/arch/pc532/stand/rd.c
@@ -0,0 +1,29 @@
+#include <sys/param.h>
+#include "stand.h"
+#include "samachdep.h"
+
+#ifndef RD_START
+#define RD_START 0x288000
+#endif
+
+rdopen(f, ctlr, unit, part)
+ struct open_file *f;
+ int ctlr, unit, part;
+{
+ f->f_devdata = (void *) RD_START;
+ return(0);
+}
+
+int
+rdstrategy(ss, func, dblk, size, buf, rsize)
+ void *ss;
+ int func;
+ daddr_t dblk; /* block number */
+ u_int size; /* request size in bytes */
+ void *buf;
+ u_int *rsize; /* out: bytes transferred */
+{
+ memcpy(buf, ss + (dblk << DEV_BSHIFT), size);
+ *rsize = size;
+ return(0);
+}
diff --git a/sys/arch/pc532/stand/samachdep.h b/sys/arch/pc532/stand/samachdep.h
new file mode 100644
index 00000000000..a48383f54d5
--- /dev/null
+++ b/sys/arch/pc532/stand/samachdep.h
@@ -0,0 +1,42 @@
+/* $NetBSD: samachdep.h,v 1.2 1994/10/26 08:25:51 cgd Exp $ */
+
+/*
+ * Copyright (c) 1982, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)samachdep.h 8.1 (Berkeley) 6/10/93
+ */
+
+#define NSCSI 1
+#define NSD 8
+
+extern int howto;
+extern unsigned int bootdev;
diff --git a/sys/arch/pc532/stand/scn.c b/sys/arch/pc532/stand/scn.c
new file mode 100644
index 00000000000..b8637d16c38
--- /dev/null
+++ b/sys/arch/pc532/stand/scn.c
@@ -0,0 +1,103 @@
+/* $NetBSD: scn.c,v 1.3 1995/08/29 21:55:49 phil Exp $ */
+
+/*-
+ * Copyright (c) 1994 Philip L. Budne.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Philip L. Budne.
+ * 4. The name of Philip L. Budne may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP BUDNE ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PHILIP BUDNE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * scn.c -- scn2681/2692/68881 standalone console driver
+ * Phil Budne, May 10, 1994
+ *
+ */
+
+#ifdef SCNCONSOLE
+#include <sys/types.h>
+#include <dev/cons.h>
+
+#define DUART 0x28000000
+
+/* registers */
+#define SCN_STAT 1
+#define SCN_DATA 3
+
+/* status bits */
+#define STAT_RXRDY 0x01
+#define STAT_TXRDY 0x04
+
+#ifndef SCNCNUNIT
+#define SCNCNUNIT 0
+#endif
+
+unsigned char * volatile scncnaddr = (unsigned char *) DUART + 8 * SCNCNUNIT;
+
+scnprobe(cp)
+ struct consdev *cp;
+{
+ /* the only game in town */
+ cp->cn_pri = CN_NORMAL; /* XXX remote? */
+}
+
+scninit(cp)
+ struct consdev *cp;
+{
+ /* leave things they way the PROM set them */
+}
+
+scngetchar(cp)
+ struct consdev *cp;
+{
+ register unsigned char * volatile scn = scncnaddr;
+
+ if ((scn[SCN_STAT] & STAT_RXRDY) == 0)
+ return(0);
+ return scn[SCN_DATA];
+}
+
+scnputchar(cp, c)
+ struct consdev *cp;
+ register int c;
+{
+ register unsigned char * volatile scn = scncnaddr;
+ register int timo;
+ short stat;
+
+ /* wait a reasonable time for the transmitter to come ready */
+ timo = 50000;
+ while (((stat = scn[SCN_STAT]) & STAT_TXRDY) == 0 && --timo)
+ ;
+ scn[SCN_DATA] = c;
+#if 0
+ /* wait for this transmission to complete */
+ timo = 1000000;
+ while (((stat = scn[SCN_STAT]) & STAT_TXRDY) == 0 && --timo)
+ ;
+#endif
+}
+#endif
diff --git a/sys/arch/pc532/stand/scsi_hi.c b/sys/arch/pc532/stand/scsi_hi.c
new file mode 100644
index 00000000000..866273596d5
--- /dev/null
+++ b/sys/arch/pc532/stand/scsi_hi.c
@@ -0,0 +1,303 @@
+/* $NetBSD: scsi_hi.c,v 1.3 1994/10/26 08:25:53 cgd Exp $ */
+
+/****************************************************************************
+ * NS32K Monitor SCSI high-level driver
+ * Bruce Culbertson
+ * 8 March 1990
+ * (This source is public domain source)
+ *
+ * There are three monitor SCSI commands. "Read" and "write" I think are
+ * fairly self explanatory once you read the help messages. They, in fact,
+ * execute the "extended read", "extended write", and "request sense"
+ * commands from the SCSI standard.
+ *
+ * "Raw" lets you execute any SCSI command but you need a SCSI reference to
+ * know what the commands are and what their formats are. The SCSI
+ * standard specifies that there are six buffers which, for example, hold a
+ * SCSI command or are the source or destination for data. You provide
+ * "raw" with an array of pointers to the six buffers. Using "edit", you
+ * can enter a SCSI command somewhere in memory and you can create the
+ * array of pointers. The array must actually be eight entries long; two
+ * entries are not used. By typing "raw <array address>", the SCSI command
+ * is executed.
+ *
+ * By the way, "read", "write", and "raw" talk only to the DP8490 SCSI
+ * controller. I have not had time to read the Adaptec data sheet and
+ * write a driver for it.
+ ****************************************************************************/
+#include "so.h"
+
+#define OK 0
+#define NOT_OK OK+1
+#define PRIVATE
+#define PUBLIC
+#define U8 unsigned char
+
+long scsiAdr = DEFAULT_SCSI_ADR, /* default SCSI address */
+ scsiLun = DEFAULT_SCSI_LUN;
+
+struct cmd_desc { /* SCSI command description */
+ const U8 *cmd; /* command string */
+ const U8 *odata; /* data to output, if any */
+ const struct cmd_desc *chain; /* next command */
+};
+
+struct drive { /* SCSI drive description */
+ U8 adr, lun; /* SCSI address and LUN */
+ U8 flags; /* drive characteristics */
+ U8 stat; /* drive state */
+ const struct cmd_desc *init; /* list of initialize commands */
+};
+/* for drive.flags */
+#define EXTENDED_RDWR 1 /* device does extended read, write */
+#define EXTENDED_SENSE 2 /* device does extended sense */
+/* for drive.stat */
+#define INITIALIZED 1 /* device is initialized */
+
+#ifdef OMTI
+/* These SCSI commands initialize a OMTI 5200 SCSI controller with a 360K
+ * floppy at LUN=1 and an ST-225 at LUN=0.
+ */
+const U8 floppy_parms_cmd[] = {0xc2, 0x20, 0, 0, 0, 0};
+const U8 floppy_parms_data[] = {0, 3, 0x27, 0xa, 0, 0, 0, 0x80, 1, 0};
+const U8 floppy_format_cmd[] = {0xc0, 0x20, 0, 0, 9, 0x8b};
+const U8 floppy_recal_cmd[] = {1, 0x20, 0, 0, 0, 0};
+const U8 wini_parms_cmd[] = {0xc2, 0, 0, 0, 0, 0};
+const U8 wini_parms_data[] = {0, 0, 0, 3, 2, 0x63, 0, 1, 0x10, 0};
+const U8 wini_recal_cmd[] = {1, 0, 0, 0, 0, 0};
+const struct cmd_desc floppy_init2 =
+ {floppy_recal_cmd, 0, 0};
+const struct cmd_desc floppy_init1 =
+ {floppy_format_cmd, 0, &floppy_init2};
+const struct cmd_desc floppy_init0 =
+ {floppy_parms_cmd, floppy_parms_data, &floppy_init1};
+const struct cmd_desc wini_init1 =
+ {wini_recal_cmd, 0, 0};
+const struct cmd_desc wini_init0 =
+ {wini_parms_cmd, wini_parms_data, &wini_init1};
+#endif
+
+PRIVATE struct drive drive_tbl[] = {
+#ifdef OMTI
+ {1, 0, 0, 0, &wini_init0},
+ {1, 1, 0, 0, &floppy_init0},
+#endif
+ {0, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
+};
+#define DRV_TBL_SZ (sizeof (drive_tbl) / sizeof (struct drive))
+
+/* Round up to multiple of four since SCSI transfers are always multiples
+ * of four bytes.
+ */
+#define CMD_LEN 12 /* longest SCSI command */
+#define SENSE_LEN 24 /* extended sense length */
+#define MSG_LEN 4
+#define STAT_LEN 4
+
+#define MAX_SCSI_RETRIES 6
+#define CMD_IX 2
+#define CMD_SENSE 0x03
+#define CMD_READ 0x08
+#define CMD_WRITE 0x0a
+#define CMD_XREAD 0x28
+#define CMD_XWRITE 0x2a
+PRIVATE U8 cmd_buf[CMD_LEN];
+
+#define SENSE_KEY 2
+#define NO_SENSE 0
+#define RECOVERY_ERR 1
+#define UNIT_ATTN 6
+#define ADD_SENSE_CODE 12
+#define SENSE_RST 0x29
+PRIVATE U8 sense_buf[SENSE_LEN];
+
+#define CHECK_CONDITION 2
+#define STAT_IX 3
+#define STAT_MASK 0x1f
+PRIVATE U8 stat_buf[STAT_LEN];
+#define IMSG_IX 7
+PRIVATE U8 msg_buf[MSG_LEN];
+
+#define ODATA_IX 0
+#define IDATA_IX 1
+PRIVATE struct scsi_args scsi_args;
+
+/*===========================================================================*
+ * sc_rdwt *
+ *===========================================================================*/
+/* Carry out a read or write request for the SCSI disk. */
+PRIVATE int
+sc_rdwt(op, block, ram_adr, len, sc_adr, lun)
+long block, ram_adr, len, sc_adr, lun;
+{
+ int retries, ret;
+ U8 *p;
+ struct drive *dp;
+
+ /* get drive characteristics */
+ for (dp = drive_tbl; dp < drive_tbl + DRV_TBL_SZ - 1; ++dp)
+ if (dp->adr == sc_adr && dp->lun == lun) break;
+ if (dp == drive_tbl + DRV_TBL_SZ - 1) {
+ dp->adr = sc_adr; /* have default, set adr, lun */
+ dp->lun = lun;
+ }
+ for (retries = 0; retries < MAX_SCSI_RETRIES; ++retries) {
+ if (dp->init && !(dp->stat & INITIALIZED))
+ if (OK != sc_initialize (dp)) {
+ printf("SCSI cannot initialize device\n");
+ return NOT_OK;
+ }
+ p = cmd_buf; /* build SCSI command */
+ if (dp->flags & EXTENDED_RDWR) { /* use extended commands */
+ *p++ = (op == DISK_READ)? CMD_XREAD: CMD_XWRITE;
+ *p++ = lun << 5;
+ *p++ = (block >> 24) & 0xff;
+ *p++ = (block >> 16) & 0xff;
+ *p++ = (block >> 8) & 0xff;
+ *p++ = (block >> 0) & 0xff;
+ *p++ = 0;
+ *p++ = (len >> 8) & 0xff;
+ *p++ = (len >> 0) & 0xff;
+ *p = 0;
+ } else { /* use short (SASI) commands */
+ *p++ = (op == DISK_READ)? CMD_READ: CMD_WRITE;
+ *p++ = (lun << 5) | ((block >> 16) & 0x1f);
+ *p++ = (block >> 8) & 0xff;
+ *p++ = (block >> 0) & 0xff;
+ *p++ = len;
+ *p = 0;
+ }
+ if (op == DISK_READ)
+ ret = exec_scsi_hi (cmd_buf, (U8 *)ram_adr, (U8 *)0, dp);
+ else
+ ret = exec_scsi_hi (cmd_buf, (U8 *)0, (U8 *)ram_adr, dp);
+ if (OK == ret) return OK;
+ dp->stat &= ~INITIALIZED;
+ }
+ printf("SCSI %s, block %d failed even after retries\n",
+ op == DISK_READ? "READ": "WRITE", block);
+ return NOT_OK;
+}
+
+/*===========================================================================*
+ * sc_initialize *
+ *===========================================================================*/
+/* Execute the list of initialization commands for the given drive.
+ */
+int
+sc_initialize (dp)
+struct drive *dp;
+{
+ const struct cmd_desc *cp;
+
+ for (cp = dp->init; cp != 0; cp = cp->chain)
+ if (OK != exec_scsi_hi (cp->cmd, 0, cp->odata, dp)) {
+ dp->stat &= ~INITIALIZED;
+ return NOT_OK;
+ }
+ dp->stat |= INITIALIZED;
+ return OK;
+}
+
+/*===========================================================================*
+ * exec_scsi_hi *
+ *===========================================================================*/
+/* Execute a "high-level" SCSI command. This means execute a low level
+ * command and, if it fails, execute a request sense to find out why.
+ */
+PRIVATE int
+exec_scsi_hi(cmd, data_in, data_out, dp)
+U8 *cmd, *data_out, *data_in;
+struct drive *dp;
+{
+ scsi_args.ptr[CMD_IX] = (long)cmd;
+ scsi_args.ptr[STAT_IX] = (long)stat_buf;
+ scsi_args.ptr[IMSG_IX] = (long)msg_buf;
+ scsi_args.ptr[IDATA_IX] = (long)data_in;
+ scsi_args.ptr[ODATA_IX] = (long)data_out;
+ if (OK != exec_scsi_low (&scsi_args, dp->adr))
+ return NOT_OK;
+ *stat_buf &= STAT_MASK; /* strip off lun */
+ if (*stat_buf == 0)
+ /* Success -- this should be the usual case */
+ return OK;
+ if (*stat_buf != CHECK_CONDITION) {
+ /* do not know how to handle this so return error */
+ printf("SCSI device returned unknown status: %d\n", *stat_buf);
+ return NOT_OK;
+ }
+ /* Something funny happened, need to execute request-sense command
+ * to learn more.
+ */
+ if (OK == get_sense(dp))
+ /* Something funny happened, but the device recovered from it and
+ * the command succeeded.
+ */
+ return OK;
+ return NOT_OK;
+}
+
+/*===========================================================================*
+ * get_sense *
+ *===========================================================================*/
+/* Execute a "request sense" SCSI command and check results. When a SCSI
+ * command returns CHECK_CONDITION, a request-sense command must be executed.
+ * A request-sense command provides information about the original command.
+ * The original command might have succeeded, in which case it does not
+ * need to be retried and OK is returned. Examples: read error corrected
+ * with error correction code, or error corrected by retries performed by
+ * the SCSI device. The original command also could have failed, in
+ * which case NOT_OK is returned.
+ */
+#define XLOGICAL_ADR \
+ (sense_buf[3]<<24 | sense_buf[4]<<16 | sense_buf[5]<<8 | sense_buf[6])
+#define LOGICAL_ADR \
+ (sense_buf[1]<<16 | sense_buf[2]<<8 | sense_buf[3])
+
+PRIVATE int
+get_sense (dp)
+struct drive *dp;
+{
+ U8 *p;
+
+ p = cmd_buf; /* build SCSI command */
+ *p++ = CMD_SENSE;
+ *p++ = dp->lun << 5;
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = (dp->flags & EXTENDED_SENSE)? SENSE_LEN: 0;
+ *p = 0;
+ scsi_args.ptr[IDATA_IX] = (long)sense_buf;
+ scsi_args.ptr[ODATA_IX] = 0;
+ scsi_args.ptr[CMD_IX] = (long)cmd_buf;
+ scsi_args.ptr[STAT_IX] = (long)stat_buf;
+ scsi_args.ptr[IMSG_IX] = (long)msg_buf;
+ if (OK != exec_scsi_low (&scsi_args, dp->adr)) {
+ printf("SCSI SENSE command failed\n");
+ return NOT_OK;
+ }
+ if ((*stat_buf & STAT_MASK) != 0) {
+ printf("SCSI SENSE returned wrong status %d\n", *stat_buf);
+ return NOT_OK;
+ }
+ if (0 == (dp->flags & EXTENDED_SENSE)) {
+ printf("SCSI request sense, code 0x%x, log_adr 0x%x\n",
+ sense_buf[0], LOGICAL_ADR);
+ return NOT_OK;
+ }
+ switch (sense_buf[SENSE_KEY] & 0xf) {
+ case NO_SENSE:
+ case UNIT_ATTN: /* reset */
+ return NOT_OK; /* must retry command */
+ case RECOVERY_ERR:
+ /* eventually, we probably do not want to hear about these. */
+ printf("SCSI ok with recovery, code 0x%x, logical address 0x%x\n",
+ sense_buf[ADD_SENSE_CODE], XLOGICAL_ADR);
+ return OK; /* orig command was ok with recovery */
+ default:
+ printf("SCSI failure: key 0x%x code 0x%x log adr 0x%x sense buf 0x%x\n",
+ sense_buf[SENSE_KEY], sense_buf[ADD_SENSE_CODE],
+ XLOGICAL_ADR, sense_buf);
+ return NOT_OK; /* orig command failed */
+ }
+}
diff --git a/sys/arch/pc532/stand/scsi_low.c b/sys/arch/pc532/stand/scsi_low.c
new file mode 100644
index 00000000000..6fd2bc643f8
--- /dev/null
+++ b/sys/arch/pc532/stand/scsi_low.c
@@ -0,0 +1,426 @@
+/* $NetBSD: scsi_low.c,v 1.4 1994/12/09 21:04:42 phil Exp $ */
+
+/****************************************************************************
+ * NS32K Monitor SCSI low-level driver
+ * Bruce Culbertson
+ * 8 March 1990
+ * (This source is public domain source.)
+ *
+ * Originally written by Bruce Culbertson for a ns32016 port of Minix.
+ * Adapted from that for the pc532 (ns32632) monitor.
+ * Adapted from that for NetBSD/pc532 by Philip L. Bunde.
+ *
+ * Do not use DMA -- makes 32016 and pc532 versions compatible.
+ * Do not use interrupts -- makes it harder for the user code to bomb
+ * this code.
+ ****************************************************************************/
+
+#include "so.h"
+
+#define OK 0
+#define NOT_OK OK+1
+#define PRIVATE
+#define PUBLIC
+#define WR_ADR(adr,val) (*((volatile unsigned char *)(adr))=(val))
+#define RD_ADR(adr) (*((volatile unsigned char *)(adr)))
+#define AIC6250 0
+#define DP8490 1
+#define MAX_CACHE 0x10000
+
+/* SCSI bus phases
+ */
+#define PH_ODATA 0
+#define PH_IDATA 1
+#define PH_CMD 2
+#define PH_STAT 3
+#define PH_IMSG 7
+#define PH_NONE 8
+#define PH_IN(phase) ((phase) & 1)
+
+/* NCR5380 SCSI controller registers
+ */
+#define SC_CTL 0x30000000 /* base for control registers */
+#define SC_DMA 0x38000000 /* base for data registers */
+#define SC_CURDATA SC_CTL+0
+#define SC_OUTDATA SC_CTL+0
+#define SC_ICMD SC_CTL+1
+#define SC_MODE SC_CTL+2
+#define SC_TCMD SC_CTL+3
+#define SC_STAT1 SC_CTL+4
+#define SC_STAT2 SC_CTL+5
+#define SC_START_SEND SC_CTL+5
+#define SC_INDATA SC_CTL+6
+#define SC_RESETIP SC_CTL+7
+#define SC_START_RCV SC_CTL+7
+
+/* Bits in NCR5380 registers
+ */
+#define SC_A_RST 0x80
+#define SC_A_SEL 0x04
+#define SC_S_SEL 0x02
+#define SC_S_REQ 0x20
+#define SC_S_BSY 0x40
+#define SC_S_BSYERR 0x04
+#define SC_S_PHASE 0x08
+#define SC_S_IRQ 0x10
+#define SC_S_DRQ 0x40
+#define SC_M_DMA 0x02
+#define SC_M_BSY 0x04
+#define SC_ENABLE_DB 0x01
+
+/* Status of interrupt routine, returned in m1_i1 field of message.
+ */
+#define ISR_NOTDONE 0
+#define ISR_OK 1
+#define ISR_BSYERR 2
+#define ISR_RSTERR 3
+#define ISR_BADPHASE 4
+#define ISR_TIMEOUT 5
+
+#define ICU_ADR 0xfffffe00
+#define ICU_IO (ICU_ADR+20)
+#define ICU_DIR (ICU_ADR+21)
+#define ICU_DATA (ICU_ADR+19)
+#define ICU_SCSI_BIT 0x80
+
+/* Miscellaneous
+ */
+#define MAX_WAIT 2000000
+#define SC_LOG_LEN 32
+
+PRIVATE struct scsi_args *sc_ptrs;
+PRIVATE char sc_cur_phase,
+ sc_reset_done = 1,
+ sc_have_msg,
+ sc_accept_int,
+ sc_dma_dir;
+
+long sc_dma_port = SC_DMA,
+ sc_dma_adr;
+
+#ifdef DEBUG
+struct sc_log {
+ unsigned char stat1, stat2;
+} sc_log [SC_LOG_LEN],
+ *sc_log_head = sc_log;
+int sc_spurious_int;
+#endif
+unsigned char
+ sc_watchdog_error; /* watch dog error */
+
+/* error messages */
+char *scsi_errors[] = {
+ 0, /* ISR_NOTDONE */
+ 0, /* ISR_OK */
+ "busy error", /* ISR_BSYERR */
+ "reset error", /* ISR_RSTERR */
+ "NULL pointer for current phase", /* ISR_BADPHASE */
+ "timeout", /* ISR_TIMEOUT */
+};
+
+/*===========================================================================*
+ * exec_scsi_low *
+ *===========================================================================*/
+/* Execute a generic SCSI command. Passed pointers to eight buffers:
+ * data-out, data-in, command, status, dummy, dummy, message-out, message-in.
+ */
+PUBLIC
+int
+exec_scsi_low (args, scsi_adr)
+struct scsi_args *args;
+long scsi_adr;
+{
+ int ret;
+
+ sc_ptrs = args; /* make pointers globally accessible */
+ scCtlrSelect (DP8490);
+ if (!sc_reset_done) sc_reset();
+ /* TCMD has some undocumented behavior in initiator mode. I think the
+ * data bus cannot be enabled if i/o is asserted.
+ */
+ WR_ADR (SC_TCMD, 0);
+ if (OK != sc_wait_bus_free ()) { /* bus-free phase */
+ printf("SCSI: bus not free\n");
+ return NOT_OK;
+ }
+ sc_cur_phase = PH_NONE;
+ sc_have_msg = 0;
+ if (OK != sc_select (scsi_adr)) /* select phase */
+ return NOT_OK;
+ sc_watchdog_error = 0;
+ ret = sc_receive (); /* isr does the rest */
+ if (ret == ISR_OK) return OK;
+ else {
+ sc_reset();
+ printf("SCSI: %s\n", scsi_errors[ret]);
+ return NOT_OK;
+ }
+}
+
+/*===========================================================================*
+ * sc_reset *
+ *===========================================================================*/
+/*
+ * Reset SCSI bus.
+ */
+PRIVATE
+sc_reset()
+{
+ volatile int i;
+
+ WR_ADR (SC_MODE, 0); /* get into harmless state */
+ WR_ADR (SC_OUTDATA, 0);
+ WR_ADR (SC_ICMD, SC_A_RST); /* assert RST on SCSI bus */
+ i = 200; /* wait 25 usec */
+ while (i--);
+ WR_ADR (SC_ICMD, 0); /* deassert RST, get off bus */
+ sc_reset_done = 1;
+}
+
+/*===========================================================================*
+ * sc_wait_bus_free *
+ *===========================================================================*/
+PRIVATE int
+sc_wait_bus_free()
+{
+ int i = MAX_WAIT;
+ volatile int j;
+
+ while (i--) {
+ /* Must be clear for 2 usec, so read twice */
+ if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
+ for (j = 0; j < 25; ++j);
+ if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
+ return OK;
+ }
+ sc_reset_done = 0;
+ return NOT_OK;
+}
+
+/*===========================================================================*
+ * sc_select *
+ *===========================================================================*/
+/* This duplicates much of the work that the interrupt routine would do on a
+ * phase mismatch and, in fact, the original plan was to just do the select,
+ * let a phase mismatch occur, and let the interrupt routine do the rest.
+ * That didn't work because the 5380 did not reliably generate the phase
+ * mismatch interrupt after selection.
+ */
+PRIVATE int
+sc_select(adr)
+long adr;
+{
+ int i, stat1;
+ long new_ptr;
+
+ WR_ADR (SC_OUTDATA, adr); /* SCSI bus address */
+ WR_ADR (SC_ICMD, SC_A_SEL | SC_ENABLE_DB);
+ for (i = 0;; ++i) { /* wait for target to assert SEL */
+ stat1 = RD_ADR (SC_STAT1);
+ if (stat1 & SC_S_BSY) break; /* select successful */
+ if (i > MAX_WAIT) { /* timeout */
+ printf("SCSI: SELECT timeout\n");
+ sc_reset();
+ return NOT_OK;
+ }
+ }
+ WR_ADR (SC_ICMD, 0); /* clear SEL, disable data out */
+ WR_ADR (SC_OUTDATA, 0);
+ for (i = 0;; ++i) { /* wait for target to assert REQ */
+ if (stat1 & SC_S_REQ) break; /* target requesting transfer */
+ if (i > MAX_WAIT) { /* timeout */
+ printf("SCSI: REQ timeout\n");
+ sc_reset();
+ return NOT_OK;
+ }
+ stat1 = RD_ADR (SC_STAT1);
+ }
+ sc_cur_phase = (stat1 >> 2) & 7; /* get new phase from controller */
+ if (sc_cur_phase != PH_CMD) {
+ printf("SCSI: bad phase = %d\n", sc_cur_phase);
+ sc_reset();
+ return NOT_OK;
+ }
+ new_ptr = sc_ptrs->ptr[PH_CMD];
+ if (new_ptr == 0) {
+ printf("SCSI: NULL command pointer\n");
+ sc_reset();
+ return NOT_OK;
+ }
+ sc_accept_int = 1;
+ sc_dma_setup (DISK_WRITE, new_ptr);
+ WR_ADR (SC_TCMD, PH_CMD);
+ WR_ADR (SC_ICMD, SC_ENABLE_DB);
+ WR_ADR (SC_MODE, SC_M_BSY | SC_M_DMA);
+ WR_ADR (SC_START_SEND, 0);
+ return OK;
+}
+
+/*===========================================================================*
+ * scsi_interrupt *
+ *===========================================================================*/
+/* SCSI interrupt handler.
+ */
+PUBLIC
+int
+scsi_interrupt()
+{
+ unsigned char stat2, dummy;
+ long new_ptr;
+ int ret = ISR_NOTDONE;
+
+ stat2 = RD_ADR (SC_STAT2); /* get status before clearing request */
+
+# ifdef DEBUG /* debugging log of interrupts */
+ sc_log_head->stat1 = RD_ADR (SC_STAT1);
+ sc_log_head->stat2 = stat2;
+ if (++sc_log_head >= sc_log + SC_LOG_LEN) sc_log_head = sc_log;
+ sc_log_head->stat1 = sc_log_head->stat2 = 0xff;
+# endif
+
+ for (;;) {
+ dummy = RD_ADR (SC_RESETIP); /* clear interrupt request */
+ if (!sc_accept_int || /* return if spurious interrupt */
+ (!sc_watchdog_error &&
+ (stat2 & SC_S_BSYERR) == 0 && (stat2 & SC_S_PHASE) == 1))
+ {
+# ifdef DEBUG
+ ++sc_spurious_int;
+# endif
+ return ret;
+ }
+ RD_ADR (SC_MODE) &= ~SC_M_DMA; /* clear DMA mode */
+ WR_ADR (SC_ICMD, 0); /* disable data bus */
+ if (sc_cur_phase != PH_NONE) { /* if did DMA, save the new pointer */
+ new_ptr = sc_dma_adr; /* fetch new pointer from DMA cntlr */
+ if (sc_cur_phase == PH_IMSG && /* have message? */
+ new_ptr != sc_ptrs->ptr[PH_IMSG]) sc_have_msg = 1;
+ sc_ptrs->ptr[sc_cur_phase] = /* save pointer */
+ new_ptr;
+ }
+ if (sc_watchdog_error) ret = ISR_TIMEOUT;
+ else if (stat2 & SC_S_BSYERR) { /* target deasserted BSY? */
+ if (sc_have_msg) ret = ISR_OK;
+ else ret = ISR_BSYERR;
+ } else if (!(stat2 & SC_S_PHASE)) { /* if phase mismatch, setup new phase */
+ sc_cur_phase = /* get new phase from controller */
+ (RD_ADR (SC_STAT1) >> 2) & 7;
+ new_ptr = sc_ptrs->ptr[sc_cur_phase];
+ if (new_ptr == 0) ret = ISR_BADPHASE;
+ else {
+ WR_ADR (SC_TCMD, sc_cur_phase); /* write new phase into TCMD */
+ if (PH_IN (sc_cur_phase)) { /* set DMA controller */
+ sc_dma_setup (DISK_READ, new_ptr);
+ RD_ADR (SC_MODE) |= SC_M_DMA;
+ WR_ADR (SC_START_RCV, 0); /* tell SCSI to start DMA */
+ } else {
+ sc_dma_setup (DISK_WRITE, new_ptr);
+ RD_ADR (SC_MODE) |= SC_M_DMA;
+ WR_ADR (SC_ICMD, SC_ENABLE_DB);
+ WR_ADR (SC_START_SEND, 0);
+ }
+ }
+ } else ret = ISR_RSTERR;
+ if (ret != ISR_NOTDONE) { /* if done, send message to task */
+ sc_watchdog_error = 0;
+ sc_accept_int = 0;
+ WR_ADR (SC_MODE, 0); /* clear monbsy, dma */
+ break; /* reti re-enables ints */
+ }
+ if (0 == ((stat2 = /* check for another interrupt */
+ RD_ADR (SC_STAT2)) & SC_S_IRQ))
+ {
+ break;
+ }
+ }
+ return ret;
+}
+
+/*===========================================================================*
+ * sc_dma_setup *
+ *===========================================================================*/
+/* Fake DMA setup. Just store pointers and direction in global variables.
+ *
+ * The pseudo-DMA is subtler than it looks because of the cache.
+ *
+ * 1) When accessing I/O devices through a cache, some mechanism is
+ * necessary to ensure you access the device rather than the cache.
+ * On the 32532, the IODEC signal is supposed to be asserted for I/O
+ * addresses to accomplish this. However, a bug makes this much
+ * slower than necessary and severely hurts pseudo-DMA performance.
+ * Hence, IODEC is not asserted for the SCSI DMA port.
+ *
+ * 2) Because of (1), we must devise our own method of forcing the
+ * SCSI DMA port to be read. 0x8000000 addresses have been decoded
+ * to all access this port. By always using new addresses to access
+ * the DMA port (wrapping only after reading MAX_CACHE bytes), we
+ * force cache misses and, hence, device reads. Since the cache
+ * is write-through, we do not need to worry about writes.
+ *
+ * 3) It is possible to miss the last few bytes of a transfer if
+ * bus transfer size is not considered. The loop in sc_receive()
+ * transfers data until the interrupt signal is asserted. If
+ * bytes are transferred, the attempt to move the first byte of a
+ * double word causes the whole word to be read into the cache.
+ * Then the byte is transferred. If reading the double word
+ * completed the SCSI transfer, then the loop exits since
+ * interrupt is asserted. However, the last few bytes have only
+ * been moved into the cache -- they have not been moved to the
+ * DMA destination.
+ *
+ * 4) It is also possible to miss the first few bytes of a transfer.
+ * If the address used to access pseudo-dma port is not double word
+ * aligned, the whole double word is read into the cache, and then
+ * data is moved from the middle of the word (i.e. something other
+ * than the first bytes read from the SCSI controller) by the
+ * pseudo-dma loop in sc_receive().
+ */
+sc_dma_setup (dir, adr)
+int dir;
+long adr;
+{
+ if (sc_dma_port > SC_DMA + MAX_CACHE) sc_dma_port = SC_DMA;
+ sc_dma_dir = dir;
+ sc_dma_adr = adr;
+}
+
+/*===========================================================================*
+ * sc_receive *
+ *===========================================================================*/
+/* Replacement for Minix receive(), which waits for a message. This code
+ * spins, waiting for data to transfer or interrupt requests to handle.
+ * See sc_dma_setup for details.
+ */
+int
+sc_receive()
+{
+ int stat2, isr_ret;
+
+ for (;;) {
+ stat2 = RD_ADR (SC_STAT2);
+ if (stat2 & SC_S_IRQ) {
+ if (ISR_NOTDONE != (isr_ret = scsi_interrupt())) break;
+ } else if (stat2 & SC_S_DRQ) { /* test really not necessary on pc532 */
+ if (sc_dma_dir == DISK_READ)
+ *((long *)sc_dma_adr)++ = *((volatile long *)sc_dma_port)++;
+ else *((volatile long *)sc_dma_port)++ = *((long *)sc_dma_adr)++;
+ }
+ }
+ return isr_ret;
+}
+
+/*===========================================================================*
+ * scCtlrSelect
+ *===========================================================================*/
+/* Select a SCSI device.
+ */
+scCtlrSelect (ctlr)
+int ctlr;
+{
+ RD_ADR (ICU_IO) &= ~ICU_SCSI_BIT; /* i/o, not port */
+ RD_ADR (ICU_DIR) &= ~ICU_SCSI_BIT; /* output */
+ if (ctlr == DP8490)
+ RD_ADR (ICU_DATA) &= ~ICU_SCSI_BIT; /* select = 0 for 8490 */
+ else
+ RD_ADR (ICU_DATA) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */
+}
diff --git a/sys/arch/pc532/stand/sd.c b/sys/arch/pc532/stand/sd.c
new file mode 100644
index 00000000000..ff6ea431607
--- /dev/null
+++ b/sys/arch/pc532/stand/sd.c
@@ -0,0 +1,196 @@
+/* $NetBSD: sd.c,v 1.4 1995/08/29 21:55:50 phil Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Van Jacobson of Lawrence Berkeley Laboratory and the Systems
+ * Programming Group of the University of Utah Computer Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: sd.c 1.9 92/12/21$
+ *
+ * @(#)sd.c 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * SCSI CCS disk driver
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include "stand.h"
+#include "samachdep.h"
+
+struct sd_softc {
+ int sc_ctlr;
+ int sc_unit;
+ int sc_part;
+ char sc_retry;
+ char sc_alive;
+ struct disklabel sc_label;
+} sd_softc[NSCSI][NSD];
+
+#ifdef SD_DEBUG
+int debug = SD_DEBUG;
+#endif
+
+#define SDRETRY 2
+
+sdinit(ctlr, unit)
+ int ctlr, unit;
+{
+ register struct sd_softc *ss = &sd_softc[ctlr][unit];
+
+ /* HP version does test_unit_ready
+ * followed by read_capacity to get blocksize
+ */
+ ss->sc_alive = 1;
+ return (1);
+}
+
+sdreset(ctlr, unit)
+ int ctlr, unit;
+{
+}
+
+char io_buf[MAXBSIZE];
+
+sdgetinfo(ss)
+ register struct sd_softc *ss;
+{
+ register struct disklabel *lp;
+ char *msg, *getdisklabel();
+ int sdstrategy(), i, err;
+
+ lp = &sd_softc[ss->sc_ctlr][ss->sc_unit].sc_label;
+ bzero((caddr_t)lp, sizeof *lp);
+ lp->d_secsize = DEV_BSIZE;
+ lp->d_secpercyl = 1;
+ lp->d_npartitions = MAXPARTITIONS;
+ lp->d_partitions[ss->sc_part].p_offset = 0;
+ lp->d_partitions[ss->sc_part].p_size = 0x7fffffff;
+
+ if (err = sdstrategy(ss, F_READ,
+ LABELSECTOR, DEV_BSIZE, io_buf, &i) < 0) {
+ printf("sdgetinfo: sdstrategy error %d\n", err);
+ return 0;
+ }
+
+ msg = getdisklabel(io_buf, lp);
+ if (msg) {
+ printf("sd(%d,%d,%d): %s\n",
+ ss->sc_ctlr, ss->sc_unit, ss->sc_part, msg);
+ return 0;
+ }
+ return(1);
+}
+
+sdopen(f, ctlr, unit, part)
+ struct open_file *f;
+ int ctlr, unit, part;
+{
+ register struct sd_softc *ss;
+ register struct disklabel *lp;
+
+#ifdef SD_DEBUG
+ if (debug)
+ printf("sdopen: ctlr=%d unit=%d part=%d\n",
+ ctlr, unit, part);
+#endif
+
+ if (ctlr >= NSCSI || !scsialive(ctlr))
+ return (EADAPT);
+ if (unit >= NSD)
+ return (ECTLR);
+ ss = &sd_softc[ctlr][unit]; /* XXX alloc()? keep pointers? */
+ ss->sc_part = part;
+ ss->sc_unit = unit;
+ ss->sc_ctlr = ctlr;
+ if (!ss->sc_alive) {
+ if (!sdinit(ctlr, unit))
+ return (ENXIO);
+ if (!sdgetinfo(ss))
+ return (ERDLAB);
+ }
+ lp = &sd_softc[ctlr][unit].sc_label;
+ if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0)
+ return (EPART);
+
+ f->f_devdata = (void *)ss;
+ return (0);
+}
+
+int
+sdstrategy(ss, func, dblk, size, buf, rsize)
+ register struct sd_softc *ss;
+ int func;
+ daddr_t dblk; /* block number */
+ u_int size; /* request size in bytes */
+ char *buf;
+ u_int *rsize; /* out: bytes transferred */
+{
+ register int ctlr = ss->sc_ctlr;
+ register int unit = ss->sc_unit;
+ register int part = ss->sc_part;
+ register struct partition *pp = &ss->sc_label.d_partitions[part];
+ u_int nblk = size >> DEV_BSHIFT;
+ u_int blk = dblk + pp->p_offset;
+ char stat;
+
+ if (size == 0)
+ return(0);
+
+ ss->sc_retry = 0;
+
+#ifdef SD_DEBUG
+ if (debug)
+ printf("sdstrategy(%d,%d): size=%d blk=%d nblk=%d\n",
+ ctlr, unit, size, blk, nblk);
+#endif
+
+retry:
+ if (func == F_READ)
+ stat = scsi_tt_read(ctlr, unit, buf, size, blk, nblk);
+ else
+ stat = scsi_tt_write(ctlr, unit, buf, size, blk, nblk);
+ if (stat) {
+ printf("sd(%d,%d,%d): block=%x, error=0x%x\n",
+ ctlr, unit, ss->sc_part, blk, stat);
+ if (++ss->sc_retry > SDRETRY)
+ return(EIO);
+ goto retry;
+ }
+ *rsize = size;
+
+ return(0);
+}
diff --git a/sys/arch/pc532/stand/so.h b/sys/arch/pc532/stand/so.h
new file mode 100644
index 00000000000..63c85ef9d5a
--- /dev/null
+++ b/sys/arch/pc532/stand/so.h
@@ -0,0 +1,67 @@
+/* $NetBSD: so.h,v 1.2 1994/10/26 08:25:57 cgd Exp $ */
+
+#ifndef _SO_H_INCLUDE
+#define _SO_H_INCLUDE
+
+/* Definitions for standalone I/O lib */
+
+#define DUART0 0x28000000
+#define DUART1 0x28000020
+#define DUART2 0x28000040
+#define DUART3 0x28000060
+#define PARRDU 0x28000080
+#define PARCLU 0x280000A0
+#define SCSI_POLLED 0x30000000
+#define SCSI_DMA 0x38000000
+#define ICU_ADDR 0xFFFFFE00
+
+/* Which UART to use by default */
+#define DEFAULT_UART 0
+
+/* Which SCSI device to use by default */
+#define DEFAULT_SCSI_ADR 1
+#define DEFAULT_SCSI_LUN 0
+
+/* Low level scsi operation codes */
+#define DISK_READ 3
+#define DISK_WRITE 4
+
+/* The size of a disk block */
+#define DBLKSIZE 512
+
+/* Some disk address that will never be used */
+#define INSANE_BADDR 0x800000
+
+struct scsi_args {
+ long ptr [8];
+};
+
+#ifndef NULL
+#define NULL 0L
+#endif
+
+/*
+ * The next macro defines where the "break" area in memory ends for
+ * malloc() and friends. The area between edata and this address will
+ * then be reserved and should not be used for anything else (or you will
+ * no doubt have big problems). Depending on where your program's end-of-data
+ * is, you may wish to locate this in such a way as to usurp a minimum
+ * amount of memory.
+ */
+#define BREAK_END_ADDR ((char *)0x400000) /* to 4MB */
+
+/* Selectivly enable inline functions */
+#ifndef NO_INLINE
+#define Inline inline
+#else
+#define Inline
+#endif
+
+extern void fatal(), warn();
+extern long ulimit(int, long);
+extern int brk(char *);
+extern char *sbrk(int);
+
+extern int sc_rdwt();
+
+#endif /* _SO_H_INCLUDE */
diff --git a/sys/arch/pc532/stand/srt0.s b/sys/arch/pc532/stand/srt0.s
new file mode 100644
index 00000000000..fe7eaa8c127
--- /dev/null
+++ b/sys/arch/pc532/stand/srt0.s
@@ -0,0 +1,91 @@
+/* $NetBSD: srt0.s,v 1.3 1995/08/29 21:55:51 phil Exp $ */
+
+/*-
+ * Copyright (c) 1994 Philip L. Budne.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Philip L. Budne.
+ * 4. The name of Philip L. Budne may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PHILIP NELSON BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * srt0.s -- standalone C startup
+ * Phil Budne, May 10, 1994
+ *
+ * from: pc532 kernel locore.s
+ * Phil Nelson, Dec 6, 1992
+ *
+ */
+
+#define PSR_S 0x200
+#define PSR_I 0x800
+
+.data
+.globl _howto, _bootdev, _r3, _r6, _r7
+__save_sp: .long 0
+__save_fp: .long 0
+_bootdev: .long 0
+_howto: .long 0
+_r3: .long 0
+_r6: .long 0
+_r7: .long 0
+
+.text
+.globl begin
+begin:
+ bicpsrw PSR_I /* make sure interrupts are off. */
+ bicpsrw PSR_S /* make sure we are using sp0. */
+
+ /* In case we are zboot: */
+ movd r3,_r3(pc) /* magic */
+ movd r6,_r6(pc) /* devtype */
+ movd r7,_r7(pc) /* howto */
+
+ lprd sb, 0 /* gcc expects this. */
+ sprd sp, __save_sp(pc) /* save monitor's sp. */
+ sprd fp, __save_fp(pc) /* save monitor's fp. */
+/* sprd intbase, __old_intbase(pc) /* save monitor's intbase. */
+ movqd 0, _howto(pc)
+
+restart:
+ /* Zero the bss segment. */
+ addr _end(pc),r0 # setup to zero the bss segment.
+ addr _edata(pc),r1
+ subd r1,r0 # compute _end - _edata
+ movd r0,tos # push length
+ addr _edata(pc),tos # push address
+
+ movqd 0,_bootdev(pc) # XXX trash bootdev
+ bsr _bzero # zero the bss segment
+ bsr _main
+ /* fall */
+
+.globl __rtt
+__rtt: lprd sp, __save_sp(pc) /* restore monitor's sp. */
+ lprd fp, __save_fp(pc) /* restore monitor's fp. */
+/* XXX just return to monitor??? */
+ movqd 3, _howto /* RB_SINGLE|RB_ASKNAME */
+ br restart
diff --git a/sys/arch/pc532/stand/test.c b/sys/arch/pc532/stand/test.c
new file mode 100644
index 00000000000..9d41480cb19
--- /dev/null
+++ b/sys/arch/pc532/stand/test.c
@@ -0,0 +1,191 @@
+/* $NetBSD: test.c,v 1.2 1994/10/26 08:25:59 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1994 Philip L. Budne.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Philip L. Budne.
+ * 4. The name of Philip L. Budne may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PHILIP BUDNE ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PHILIP BUDNE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Allow test of "boot" (and presumably other "stand" utils)
+ * under user mode.
+ *
+ * Phil Budne <phil@ultimate.com> May 10, 1994
+ */
+
+/* my /sys/sys/syscall.h is out of sync w.r.t. lseek?? */
+#include "/usr/include/sys/syscall.h"
+#include <sys/types.h>
+
+extern int errno;
+
+int testing = 1;
+int bootdev;
+int howto;
+
+_open( char *fname, int mode )
+{
+ return syscall( SYS_open, fname, mode );
+}
+
+_read( int fd, char *buf, int len )
+{
+ return syscall( SYS_read, fd, buf, len );
+}
+
+_write( int fd, char *buf, int len )
+{
+ return syscall( SYS_write, fd, buf, len );
+}
+
+/*
+ * I'd like to strangle the jerk who thought it
+ * was a cool idea to change lseek, rather than creating
+ * a new "qseek" to handle long long offsets
+ */
+_lseek( int fd, off_t pos, int whence )
+{
+ return syscall( SYS_lseek, fd, 0, pos, whence );
+}
+
+int fd = -1;
+
+opendisk(int unit)
+{
+ char fname[32];
+ static int _unit = -1;
+
+ if (unit == _unit)
+ return;
+
+ if (fd >= 0) {
+ close(fd);
+ fd = -1;
+ }
+ _unit = unit;
+
+#if 0
+ sprintf( fname, "/dev/r%s%dc", "sd", unit );
+#else
+ strcpy( fname, "/dev/rsd0c" );
+#endif
+ fd = _open( fname, 0 );
+ if (fd < 0) {
+ printf("open %s failed\n", fname );
+ return;
+ }
+ printf("opened %s (fd %d)\n", fname, fd );
+}
+
+void
+bzero( char *addr, int len )
+{
+ while (len-- > 0)
+ *addr++ = '\0';
+}
+
+/* XXX TEMP; would like to use code more like hp300 scsi.c */
+
+void
+scsiinit(void)
+{
+}
+
+int
+scsialive(int ctlr)
+{
+ return 1; /* controller always alive! */
+}
+
+#define BPS 512
+scsi_tt_read(ctlr, slave, buf, len, blk, nblk)
+ char *buf;
+{
+ int pos;
+#if 0
+printf("scsi_tt_read(ctlr %d, slave %d, buf 0x%x, len %d, blk %d, nblk %d)\n",
+ ctlr, slave, buf, len, blk, nblk);
+#endif
+
+ opendisk(slave);
+
+ pos = _lseek( fd, blk * BPS, 0 );
+ if (pos != blk * BPS) {
+ printf("lseek pos %d error %d\n", pos, errno );
+ return errno;
+ }
+ if (_read( fd, buf, nblk * BPS ) != nblk * BPS) {
+ printf("read errno %d\n", errno );
+ return errno;
+ }
+ return 0;
+}
+
+scsi_tt_write()
+{
+ return -1;
+}
+
+#include <sys/types.h>
+#include <dev/cons.h>
+
+scnprobe(cp)
+ struct consdev *cp;
+{
+ /* the only game in town */
+ cp->cn_pri = CN_NORMAL; /* XXX remote? */
+}
+
+scninit(cp)
+ struct consdev *cp;
+{
+}
+
+scnputchar(c)
+ int c;
+{
+ char c2;
+ c2 = c;
+ _write(0, &c2, 1);
+}
+
+scngetchar()
+{
+ char c;
+ _read(0, &c, 1);
+ return c;
+}
+
+_rtt() {
+ syscall( SYS_exit, 1 );
+}
+
+alloc(int size)
+{
+ return malloc(size);
+}
diff --git a/sys/arch/pc532/stand/tgets.c b/sys/arch/pc532/stand/tgets.c
new file mode 100644
index 00000000000..232affa930a
--- /dev/null
+++ b/sys/arch/pc532/stand/tgets.c
@@ -0,0 +1,89 @@
+/* $NetBSD: tgets.c,v 1.2 1994/10/26 08:26:00 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)gets.c 8.1 (Berkeley) 6/11/93
+ */
+
+tgets(buf)
+ char *buf;
+{
+ register int c;
+ int i;
+ register char *lp = buf;
+
+ for (i = 2400000; i > 0; i--) {
+ c = tgetchar() & 0177;
+ if (c) {
+ for (;;) {
+ switch (c) {
+ case '\n':
+ case '\r':
+ *lp = '\0';
+ return;
+ case '\b':
+ case '\177':
+ if (lp > buf) {
+ lp--;
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ }
+ break;
+ case '#':
+ if (lp > buf)
+ --lp;
+ break;
+ case 'r'&037: {
+ register char *p;
+
+ putchar('\n');
+ for (p = buf; p < lp; ++p)
+ putchar(*p);
+ break;
+ }
+ case '@':
+ case 'u'&037:
+ case 'w'&037:
+ lp = buf;
+ putchar('\n');
+ break;
+ default:
+ *lp++ = c;
+ }
+ c = getchar() & 0177;
+ }
+ }
+ }
+ return(0);
+}