diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /sys/arch/pc532/stand |
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/pc532/stand')
-rw-r--r-- | sys/arch/pc532/stand/Makefile | 98 | ||||
-rw-r--r-- | sys/arch/pc532/stand/README | 26 | ||||
-rw-r--r-- | sys/arch/pc532/stand/boot.c | 279 | ||||
-rw-r--r-- | sys/arch/pc532/stand/conf.c | 59 | ||||
-rw-r--r-- | sys/arch/pc532/stand/cons.c | 93 | ||||
-rw-r--r-- | sys/arch/pc532/stand/devopen.c | 203 | ||||
-rw-r--r-- | sys/arch/pc532/stand/filesystem.c | 40 | ||||
-rw-r--r-- | sys/arch/pc532/stand/inflate.c | 1433 | ||||
-rw-r--r-- | sys/arch/pc532/stand/machdep.c | 98 | ||||
-rw-r--r-- | sys/arch/pc532/stand/prf.c | 79 | ||||
-rw-r--r-- | sys/arch/pc532/stand/rd.c | 29 | ||||
-rw-r--r-- | sys/arch/pc532/stand/samachdep.h | 42 | ||||
-rw-r--r-- | sys/arch/pc532/stand/scn.c | 103 | ||||
-rw-r--r-- | sys/arch/pc532/stand/scsi_hi.c | 303 | ||||
-rw-r--r-- | sys/arch/pc532/stand/scsi_low.c | 426 | ||||
-rw-r--r-- | sys/arch/pc532/stand/sd.c | 196 | ||||
-rw-r--r-- | sys/arch/pc532/stand/so.h | 67 | ||||
-rw-r--r-- | sys/arch/pc532/stand/srt0.s | 91 | ||||
-rw-r--r-- | sys/arch/pc532/stand/test.c | 191 | ||||
-rw-r--r-- | sys/arch/pc532/stand/tgets.c | 89 |
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); +} |