diff -u --recursive --new-file v1.1.75/linux/CREDITS linux/CREDITS
--- v1.1.75/linux/CREDITS	Thu Dec 29 20:15:55 1994
+++ linux/CREDITS	Sun Jan  1 19:49:18 1995
@@ -64,6 +64,13 @@
 S: Greenbelt, Maryland 20771
 S: USA
 
+N: Randolph Bentson
+E: bentson@grieg.seaslug.org
+D: author of driver for Cyclades Cyclom-Y async mux
+S: 2500 Gilman Dr W, #404
+S: Seattle, WA 98119-2102
+S: USA
+
 N: Stephen R. van den Berg (AKA BuGless)
 E: berg@pool.informatik.rwth-aachen.de
 D: General kernel, gcc, and libc hacker
@@ -74,7 +81,7 @@
 S: The Netherlands
 
 N: Hennus Bergman
-E: hennus@sky.ow.org [My uucp-fed Linux box at home]
+E: hennus@sky.ow.nl [My uucp-fed Linux box at home]
 D: Author and maintainer of the QIC-02 tape driver
 S: The Netherlands
 
diff -u --recursive --new-file v1.1.75/linux/Configure linux/Configure
--- v1.1.75/linux/Configure	Mon Dec  5 18:47:54 1994
+++ linux/Configure	Thu Dec 29 19:58:40 1994
@@ -107,7 +107,16 @@
 echo " * Automatically generated C config: don't edit" >> $CONFIG_H
 echo " */" >> $CONFIG_H
 
-DEFAULT=$1
+DEFAULT=""
+if [ "$1" = "-d" ] ; then
+	DEFAULT="-d"
+	shift
+fi
+
+CONFIG_IN=./config.in
+if [ "$1" != "" ] ; then
+	CONFIG_IN=$1
+fi
 
 if [ -f ./.config ] ; then
 	. ./.config
@@ -115,7 +124,7 @@
 	. /tmp/conf.$$
 	rm /tmp/conf.$$
 fi
-. ./config.in
+. $CONFIG_IN
 
 if [ "$CONFIG_SOUND" = "y" ] ; then
 	$MAKE -C drivers/sound config || exit 1
diff -u --recursive --new-file v1.1.75/linux/Makefile linux/Makefile
--- v1.1.75/linux/Makefile	Thu Dec 29 20:15:55 1994
+++ linux/Makefile	Sun Jan  1 19:55:21 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 75
+SUBLEVEL = 76
 
 ARCH = i386
 
@@ -11,6 +11,15 @@
 	  else echo sh; fi ; fi)
 TOPDIR	:= $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
 
+AS	=as
+LD	=ld
+HOSTCC	=gcc -I$(TOPDIR)/include
+CC	=gcc -D__KERNEL__ -I$(TOPDIR)/include
+MAKE	=make
+CPP	=$(CC) -E
+AR	=ar
+STRIP	=strip
+
 all:	do-it-all
 
 #
@@ -21,7 +30,7 @@
 include .config
 ifeq (.depend,$(wildcard .depend))
 include .depend
-do-it-all:	Version arch-all
+do-it-all:	Version vmlinux
 else
 CONFIGURATION = depend
 do-it-all:	depend
@@ -107,33 +116,43 @@
 Version: dummy
 	rm -f include/linux/version.h
 
-boot:
-	ln -sf arch/$(ARCH)/boot boot
+boot: vmlinux
+	@$(MAKE) -C arch/$(ARCH)/boot
 
-include/asm:
-	( cd include ; ln -sf asm-$(ARCH) asm)
+vmlinux: $(CONFIGURATION) kernel/head.o init/main.o init/version.o linuxsubdirs
+	$(LD) $(LINKFLAGS) kernel/head.o init/main.o init/version.o \
+		$(ARCHIVES) \
+		$(FILESYSTEMS) \
+		$(DRIVERS) \
+		$(LIBS) -o vmlinux
+	nm vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map
 
-kernel/entry.S:
+symlinks:
+	rm -f include/asm
+	( cd include ; ln -sf asm-$(ARCH) asm)
+	ln -sf ../arch/$(ARCH)/traps.c kernel/traps.c
 	ln -sf ../arch/$(ARCH)/entry.S kernel/entry.S
+	ln -sf ../arch/$(ARCH)/head.S kernel/head.S
 
-symlinks: boot include/asm kernel/entry.S
-
-config.in: arch/$(ARCH)/config.in
-	cp $< $@
+oldconfig: symlinks
+	$(CONFIG_SHELL) Configure -d arch/$(ARCH)/config.in
 
-oldconfig: symlinks config.in
-	$(CONFIG_SHELL) Configure -d $(OPTS)
-
-config: symlinks config.in
-	$(CONFIG_SHELL) Configure $(OPTS)
+config: symlinks
+	$(CONFIG_SHELL) Configure arch/$(ARCH)/config.in
 
 linuxsubdirs: dummy
 	set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
 
 $(TOPDIR)/include/linux/version.h: include/linux/version.h
 
-include/linux/version.h: $(CONFIGURE) Makefile
-	@./makever.sh
+newversion:
+	@if [ ! -f .version ]; then \
+		echo 1 > .version; \
+	else \
+		expr `cat .version` + 1 > .version; \
+	fi
+
+include/linux/version.h: $(CONFIGURATION) Makefile newversion
 	@echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > include/linux/version.h
 	@if [ -f .name ]; then \
 	   echo \#define UTS_VERSION \"\#`cat .version`-`cat .name` `date`\"; \
@@ -150,18 +169,15 @@
 	 fi >> include/linux/version.h
 	@echo \#define LINUX_COMPILER \"`$(HOSTCC) -v 2>&1 | tail -1`\" >> include/linux/version.h
 
-tools/build: tools/build.c $(CONFIGURE)
-	$(HOSTCC) $(CFLAGS) -o $@ $< -I$(TOPDIR)/include
+kernel/head.o: kernel/head.s
 
-boot/head.o: $(CONFIGURE) boot/head.s
+kernel/head.s: kernel/head.S include/linux/tasks.h
+	$(CPP) -traditional -o $*.s $<
 
-boot/head.s: boot/head.S $(CONFIGURE) include/linux/tasks.h
-	$(CPP) -traditional $< -o $@
+init/version.o: init/version.c include/linux/version.h
+	$(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c
 
-tools/version.o: tools/version.c include/linux/version.h
-	$(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o tools/version.o tools/version.c
-
-init/main.o: $(CONFIGURE) init/main.c
+init/main.o: init/main.c
 	$(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $<
 
 fs: dummy
@@ -189,16 +205,14 @@
 	rm -f kernel/ksyms.lst
 	rm -f core `find . -name '*.[oas]' -print`
 	rm -f core `find . -name 'core' -print`
-	rm -f zImage zSystem.map tools/zSystem tools/system
-	rm -f Image System.map tools/build
-	rm -f zBoot/zSystem zBoot/xtract zBoot/piggyback
+	rm -f vmlinux System.map
 	rm -f .tmp* drivers/sound/configure
 
 mrproper: clean
 	rm -f include/linux/autoconf.h include/linux/version.h
 	rm -f drivers/sound/local.h
 	rm -f .version .config* config.in config.old
-	rm -f boot include/asm kernel/entry.S
+	rm -f include/asm kernel/entry.S kernel/head.S kernel/traps.c
 	rm -f .depend `find . -name .depend -print`
 
 distclean: mrproper
@@ -207,10 +221,9 @@
 	cd .. && tar cf - linux | gzip -9 > backup.gz
 	sync
 
-depend dep:
+depend dep: archdep
 	touch include/linux/version.h
 	for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done > .tmpdepend
-	for i in tools/*.c;do echo -n "tools/";$(CPP) -M $$i;done >> .tmpdepend
 	set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i dep; done
 	rm -f include/linux/version.h
 	mv .tmpdepend .depend
@@ -233,20 +246,3 @@
 dummy:
 
 endif
-
-#
-# Leave these dummy entries for now to tell people that they are going away..
-#
-Image:
-	@echo
-	@echo Uncompressed kernel images no longer supported. Use
-	@echo \"make zImage\" instead.
-	@echo
-	@exit 1
-
-disk:
-	@echo
-	@echo Uncompressed kernel images no longer supported. Use
-	@echo \"make zdisk\" instead.
-	@echo
-	@exit 1
diff -u --recursive --new-file v1.1.75/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v1.1.75/linux/arch/alpha/Makefile	Thu Dec 29 20:15:55 1994
+++ linux/arch/alpha/Makefile	Thu Dec 29 19:58:40 1994
@@ -8,37 +8,9 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
-AS      =as
-LD      =ld
-HOSTCC  =gcc -I$(TOPDIR)/include
-CC      =gcc -D__KERNEL__ -I$(TOPDIR)/include
-MAKE    =make
-CPP     =$(CC) -E
-AR      =ar
-STRIP   =strip
-
-arch-all: tools/system
-
-tools/system:	boot/head.o init/main.o tools/version.o linuxsubdirs
-	$(LD) $(LOWLDFLAGS) boot/head.o init/main.o tools/version.o \
-		$(ARCHIVES) \
-		$(FILESYSTEMS) \
-		$(DRIVERS) \
-		$(LIBS) \
-		-o tools/system
-		nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \
-		sort > System.map
-
-
-#
-# Leave these dummy entries for now to tell people that they are going away..
-#
-lilo:
-	@echo
-	@echo Uncompressed kernel images no longer supported. Use
-	@echo \"make zlilo\" instead.
-	@echo
-	@exit 1
+LINKFLAGS = -non_shared -T 0xfffffc0000304000 -N
+CFLAGS := $(CFLAGS) -mno-fp-regs
 
 archclean:
-	@rm -f boot/head.o
+
+archdep:
diff -u --recursive --new-file v1.1.75/linux/arch/alpha/boot/Makefile linux/arch/alpha/boot/Makefile
--- v1.1.75/linux/arch/alpha/boot/Makefile	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/boot/Makefile	Thu Dec 29 19:58:40 1994
@@ -0,0 +1,17 @@
+#
+# arch/alpha/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+#
+
+boot:
+	@echo Wait a few days for this one..
+	@exit 1
+
+dep:
+
+clean:
diff -u --recursive --new-file v1.1.75/linux/arch/alpha/boot/head.S linux/arch/alpha/boot/head.S
--- v1.1.75/linux/arch/alpha/boot/head.S	Thu Dec 29 20:15:55 1994
+++ linux/arch/alpha/boot/head.S	Thu Dec 29 19:58:40 1994
@@ -1,112 +0,0 @@
-/*
- * alpha/head.S
- *
- * initial boot stuff..
- */
-
-#include <asm/system.h>
-
-#undef halt
-#define halt .long PAL_halt
-
-/*
- * NOTE! The console bootstrap will load us at 0x20000000, but this image
- * is linked to run at START_ADDR, so the first thing we do is to move
- * ourself up to the right address.. We'd better be position-independent
- * at that stage :-)
- */
-	.set noreorder
-	.globl	__start
-	.ent	__start
-__start:
-	bis	$31,$31,$31
-	br	$1,$200
-	.long START_ADDR, START_ADDR >> 32	/* strange bug in the assembler.. duh */
-	.long START_SIZE, START_SIZE >> 32
-$200:	ldq	$30,0($1)		/* new stack - below this */
-	lda	$2,-8($1)		/* __start */
-	bis	$30,$30,$3		/* new address */
-	subq	$3,$2,$6		/* difference */
-	ldq	$4,8($1)		/* size */
-$201:	subq	$4,8,$4
-	ldq	$5,0($2)
-	addq	$2,8,$2
-	stq	$5,0($3)
-	addq	$3,8,$3
-	bne	$4,$201
-	br	$1,$202
-$202:	addq	$1,$6,$1
-	addq	$1,12,$1		/* $203 in the new address space */
-	jmp	$31,($1),$203
-$203:	br	$27,$100
-$100:	ldgp	$29,0($27)
-	lda	$27,start_kernel
-	jsr	$26,($27),start_kernel
-	halt
-	.end __start
-
-	.align 5
-	.globl	wrent
-	.ent	wrent
-wrent:
-	.long PAL_wrent
-	ret ($26)
-	.end wrent
-
-	.align 5
-	.globl	wrkgp
-	.ent	wrkgp
-wrkgp:
-	.long PAL_wrkgp
-	ret ($26)
-	.end wrkgp
-
-	.align 5
-	.globl	switch_to_osf_pal
-	.ent	switch_to_osf_pal
-switch_to_osf_pal:
-	subq	$30,128,$30
-	stq	$26,0($30)
-	stq	$1,8($30)
-	stq	$2,16($30)
-	stq	$3,24($30)
-	stq	$4,32($30)
-	stq	$5,40($30)
-	stq	$6,48($30)
-	stq	$7,56($30)
-	stq	$8,64($30)
-	stq	$9,72($30)
-	stq	$10,80($30)
-	stq	$11,88($30)
-	stq	$12,96($30)
-	stq	$13,104($30)
-	stq	$14,112($30)
-	stq	$15,120($30)
-
-	stq	$30,0($17)	/* save KSP in PCB */
-
-	bis	$30,$30,$20	/* a4 = KSP */
-	br	$17,__do_swppal
-
-	ldq	$26,0($30)
-	ldq	$1,8($30)
-	ldq	$2,16($30)
-	ldq	$3,24($30)
-	ldq	$4,32($30)
-	ldq	$5,40($30)
-	ldq	$6,48($30)
-	ldq	$7,56($30)
-	ldq	$8,64($30)
-	ldq	$9,72($30)
-	ldq	$10,80($30)
-	ldq	$11,88($30)
-	ldq	$12,96($30)
-	ldq	$13,104($30)
-	ldq	$14,112($30)
-	ldq	$15,120($30)
-	addq	$30,128,$30
-	ret ($26)
-
-__do_swppal:
-	.long	PAL_swppal
-	.end	switch_to_osf_pal
diff -u --recursive --new-file v1.1.75/linux/arch/alpha/boot/tools/build.c linux/arch/alpha/boot/tools/build.c
--- v1.1.75/linux/arch/alpha/boot/tools/build.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/boot/tools/build.c	Thu Dec 29 19:58:40 1994
@@ -0,0 +1,151 @@
+/*
+ * arch/alpha/boot/tools/build.c
+ *
+ * Build a bootable image from the vmlinux binary
+ */
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <a.out.h>
+
+#include <asm/system.h>
+
+#define NR_SECTORS (START_SIZE / 512)
+
+#define MAXSECT 10
+#define MAXBUF 8192
+
+int verbose = 0;
+char * program = "tools/build";
+char buffer[MAXBUF];
+unsigned long bootblock[64];
+struct filehdr fhdr;
+struct aouthdr ahdr;
+struct scnhdr  shdr[MAXSECT];
+
+char * usage = "'build system > secondary' or 'build > primary'";
+
+static void die(char * str)
+{
+	fprintf(stderr,"%s: %s\n", program, str);
+	exit(1);
+}
+
+static int comp(struct scnhdr * a, struct scnhdr * b)
+{
+	return a->s_vaddr - b->s_vaddr;
+}
+
+int main(int argc, char ** argv)
+{
+	int fd, i;
+	unsigned long tmp;
+	unsigned long start;
+	char * infile = NULL;
+
+	if (argc) {
+		program = *(argv++);
+		argc--;
+	}
+	while (argc > 0) {
+		if (**argv == '-') {
+			while (*++*argv) {
+				switch (**argv) {
+					case 'v':
+						verbose++;
+						break;
+					default:
+						die(usage);
+				}
+			}
+		} else if (infile)
+			die(usage);
+		else
+			infile = *argv;
+		argv++;
+		argc--;
+	}
+	if (!infile) {
+		memcpy(bootblock, "Linux Test", 10);
+		bootblock[60] = NR_SECTORS;	/* count (32 kB) */
+		bootblock[61] = 1;		/* starting LBM */
+		bootblock[62] = 0;		/* flags */
+		tmp = 0;
+		for (i = 0 ; i < 63 ; i++)
+			tmp += ~bootblock[i];
+		bootblock[63] = tmp;
+		if (write(1, (char *) bootblock, 512) != 512) {
+			perror("bbwrite");
+			exit(1);
+		}
+		return 0;
+	}
+	fd = open(infile, O_RDONLY);
+	if (fd < 0) {
+		perror(infile);
+		exit(1);
+	}
+	if (read(fd, &fhdr, sizeof(struct filehdr)) != sizeof(struct filehdr))
+		die("unable to read file header");
+	if (fhdr.f_nscns > MAXSECT)
+		die("Too many sections");
+	if (fhdr.f_opthdr != AOUTHSZ)
+		die("optional header doesn't look like a.out");
+	if (read(fd, &ahdr, sizeof(struct aouthdr)) != sizeof(struct aouthdr))
+		die("unable to read a.out header");
+	for (i = 0 ; i < fhdr.f_nscns ; i++) {
+		if (read(fd, i+shdr, sizeof(struct scnhdr)) != sizeof(struct scnhdr))
+			die("unable to read section header");
+		if (shdr[i].s_paddr != shdr[i].s_vaddr)
+			die("unable to handle different phys/virt addresses");
+		if (shdr[i].s_relptr)
+			die("Unable to handle relocation info");
+		if (verbose) {
+			fprintf(stderr, "section %d (%.8s):\t%lx - %lx (at %x)\n",
+				i, shdr[i].s_name,
+				shdr[i].s_vaddr,
+				shdr[i].s_vaddr + shdr[i].s_size,
+				shdr[i].s_scnptr);
+		}
+	}
+	qsort(shdr, fhdr.f_nscns, sizeof(shdr[1]), comp);
+	start = START_ADDR;
+	for (i = 0 ; i < fhdr.f_nscns ; i++) {
+		unsigned long size, offset;
+		memset(buffer, 0, MAXBUF);
+		if (!strcmp(shdr[i].s_name, ".comment"))
+			continue;
+		if (shdr[i].s_vaddr != start)
+			die("Unordered or badly placed segments");
+		size = shdr[i].s_size;
+		start += size;
+		offset = shdr[i].s_scnptr;
+		if (lseek(fd, offset, SEEK_SET) != offset)
+			die("Unable to seek in in-file");
+		while (size > 0) {
+			unsigned long num = size;
+			if (num > MAXBUF)
+				num = MAXBUF;
+			if (offset)
+				if (read(fd, buffer, num) != num)
+					die("partial read");
+			if (write(1, buffer, num) != num)
+				die("partial write");
+			size -= num;
+		}
+		if (verbose) {
+			fprintf(stderr, "section %d (%.8s):\t%lx - %lx (at %x)\n",
+				i, shdr[i].s_name,
+				shdr[i].s_vaddr,
+				shdr[i].s_vaddr + shdr[i].s_size,
+				shdr[i].s_scnptr);
+		}
+	}
+	if (start > START_ADDR + NR_SECTORS*512) {
+		fprintf(stderr, "Boot image too large\n");
+		exit(1);
+	}
+	return 0;
+}
diff -u --recursive --new-file v1.1.75/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v1.1.75/linux/arch/alpha/config.in	Mon Nov 28 14:21:43 1994
+++ linux/arch/alpha/config.in	Thu Dec 29 19:58:40 1994
@@ -5,6 +5,7 @@
 
 comment 'General setup'
 
+bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
 bool 'Normal harddisk support' CONFIG_BLK_DEV_HD n
 bool 'XT harddisk support' CONFIG_BLK_DEV_XD n
 bool 'Networking support' CONFIG_NET y
@@ -16,6 +17,9 @@
 bool 'TCP/IP networking' CONFIG_INET y
 if [ "$CONFIG_INET" "=" "y" ]; then
 bool 'IP forwarding/gatewaying' CONFIG_IP_FORWARD n
+bool 'IP multicasting (ALPHA)' CONFIG_IP_MULTICAST n
+bool 'IP firewalling' CONFIG_IP_FIREWALL n
+bool 'IP accounting' CONFIG_IP_ACCT n
 comment '(it is safe to leave these untouched)'
 bool 'PC/TCP compatibility mode' CONFIG_INET_PCTCP n
 bool 'Reverse ARP' CONFIG_INET_RARP n
@@ -53,15 +57,17 @@
 bool 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F n
 bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN n
 bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 n
-bool 'NCR53c7,8xx SCSI support'  CONFIG_SCSI_NCR53C7xx n
-bool 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 n
+if [ "$CONFIG_PCI" = "y" ]; then
+  bool 'NCR53c7,8xx SCSI support'  CONFIG_SCSI_NCR53C7xx n
+fi
+bool 'Always IN2000 SCSI support (test release)' CONFIG_SCSI_IN2000 n
 bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 n
 bool 'QLOGIC SCSI support' CONFIG_SCSI_QLOGIC n
 bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE n
 bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n
 bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n
 bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n
-bool 'EISA EATA support' CONFIG_SCSI_EATA n
+bool 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA n
 #bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n
 fi
 
@@ -80,6 +86,7 @@
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' SL_COMPRESSED y
+  bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 #  bool ' SLIP debugging on' SL_DUMP y
 fi
 bool 'PPP (point-to-point) support' CONFIG_PPP n
@@ -91,6 +98,7 @@
 	bool 'WD80*3 support' CONFIG_WD80x3 n
 	bool 'SMC Ultra support' CONFIG_ULTRA n
 fi
+bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE n
 bool '3COM cards' CONFIG_NET_VENDOR_3COM n
 if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
 	bool '3c501 support' CONFIG_EL1 n
@@ -103,32 +111,41 @@
 fi
 bool 'Other ISA cards' CONFIG_NET_ISA y
 if [ "$CONFIG_NET_ISA" = "y" ]; then
-	bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n
-	bool 'Cabletron E21xx support (not recommended)' CONFIG_E2100 n
+	bool 'Cabletron E21xx support' CONFIG_E2100 n
 	bool 'DEPCA support' CONFIG_DEPCA y
 	bool 'EtherWorks 3 support' CONFIG_EWRK3 n
 	if [ "$CONFIG_NET_ALPHA" = "y" ]; then
-		bool 'EtherExpress support' CONFIG_EEXPRESS n
+#		bool 'Arcnet support' CONFIG_ARCNET n
 		bool 'AT1700 support' CONFIG_AT1700 n
+#		bool 'EtherExpressPro support' CONFIG_EEXPRESS_PRO n
+		bool 'EtherExpress support' CONFIG_EEXPRESS n
 		bool 'NI5210 support' CONFIG_NI52 n
 		bool 'NI6510 support' CONFIG_NI65 n
 	fi
-	bool 'HP PCLAN support' CONFIG_HPLAN n
-	bool 'HP PCLAN PLUS support' CONFIG_HPLAN_PLUS n
+	bool 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS n
+	bool 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN n
 	bool 'NE2000/NE1000 support' CONFIG_NE2000 n
 	bool 'SK_G16 support' CONFIG_SK_G16 n
 fi
-bool 'EISA and on board controllers' CONFIG_NET_EISA n
+bool 'EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA n
+if [ "$CONFIG_NET_EISA" = "y" ]; then
 	if [ "$CONFIG_NET_ALPHA" = "y" ]; then
 		bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n
 	fi
 	bool 'Apricot Xen-II on board ethernet' CONFIG_APRICOT n
+#	bool 'DEC 21040 PCI support' CONFIG_DEC_ELCP n
+#	bool 'LPL T100V 100Mbs support' CONFIG_LPL_T100 n
+#	bool 'PCnet32 (32 bit VLB and PCI LANCE) support' CONFIG_PCNET32 n
+	bool 'Zenith Z-Note support' CONFIG_ZNET y
+fi
 bool 'Pocket and portable adaptors' CONFIG_NET_POCKET n
 if [ "$CONFIG_NET_POCKET" = "y" ]; then
+	bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n
 	bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n
 	bool 'D-Link DE620 pocket adaptor support' CONFIG_DE620 n
-	bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n
-	bool 'Zenith Z-Note support' CONFIG_ZNET n
+#	bool 'Silicom pocket adaptor support' CONFIG_SILICOM_PEA n
+#	bool 'WaveLAN PCMCIA support' CONFIG_WaveLAN n
+#	bool '3 Com 3c589 PCMCIA support' CONFIG_3C589 n
 fi
 fi
 fi
@@ -172,6 +189,7 @@
 
 comment 'character devices'
 
+bool 'Cyclades async mux support' CONFIG_CYCLADES n
 bool 'Parallel printer support' CONFIG_PRINTER n
 bool 'Logitech busmouse support' CONFIG_BUSMOUSE n
 bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE y
@@ -181,6 +199,11 @@
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
 bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
+bool 'VESA Power Saving Protocol Support' CONFIG_VESA_PSPM n
+if [ "$CONFIG_VESA_PSPM" = "y" ]; then
+bool 'VESA PSPM Force Off' CONFIG_PSPM_FORCE_OFF n
+fi
+
 
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
 if [ "$CONFIG_QIC02_TAPE" = "y" ]; then
@@ -210,6 +233,9 @@
 
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
 bool 'Kernel profiling support' CONFIG_PROFILE n
+if [ "$CONFIG_PROFILE" = "y" ]; then
+  int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
+fi
 if [ "$CONFIG_SCSI" = "y" ]; then
 bool 'Verbose scsi error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS y
 fi
diff -u --recursive --new-file v1.1.75/linux/arch/alpha/entry.S linux/arch/alpha/entry.S
--- v1.1.75/linux/arch/alpha/entry.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/entry.S	Thu Dec 29 19:58:40 1994
@@ -0,0 +1,61 @@
+/*
+ * alpha/entry.S
+ *
+ * kernel entry-points
+ */
+
+#define __ASSEMBLY__
+#include <asm/system.h>
+
+#define halt	.long PAL_halt
+#define rti	.long RAL_rti
+
+.text
+	.set noat
+	.align 6
+	.ent entInt
+entInt:
+	subq	$30,144,$30
+	stq	$0,0($30)
+	stq	$1,8($30)
+	stq	$2,16($30)
+	stq	$3,24($30)
+	stq	$4,32($30)
+	stq	$5,40($30)
+	stq	$6,48($30)
+	stq	$7,56($30)
+	stq	$8,64($30)
+	stq	$19,64($30)
+	stq	$20,72($30)
+	stq	$21,80($30)
+	stq	$22,88($30)
+	stq	$23,96($30)
+	stq	$24,104($30)
+	stq	$25,112($30)
+	stq	$26,120($30)
+	stq	$27,128($30)
+	stq	$28,136($30)
+	lda	$27,do_hw_interrupt
+	jsr	$26,($27),do_hw_interrupt
+	ldq	$0,0($30)
+	ldq	$1,8($30)
+	ldq	$2,16($30)
+	ldq	$3,24($30)
+	ldq	$4,32($30)
+	ldq	$5,40($30)
+	ldq	$6,48($30)
+	ldq	$7,56($30)
+	ldq	$8,64($30)
+	ldq	$19,64($30)
+	ldq	$20,72($30)
+	ldq	$21,80($30)
+	ldq	$22,88($30)
+	ldq	$23,96($30)
+	ldq	$24,104($30)
+	ldq	$25,112($30)
+	ldq	$26,120($30)
+	ldq	$27,128($30)
+	ldq	$28,136($30)
+	addq	$30,144,$30
+	rti
+	.end entInt
diff -u --recursive --new-file v1.1.75/linux/arch/alpha/head.S linux/arch/alpha/head.S
--- v1.1.75/linux/arch/alpha/head.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/head.S	Thu Dec 29 19:58:40 1994
@@ -0,0 +1,112 @@
+/*
+ * alpha/boot/head.S
+ *
+ * initial boot stuff..
+ */
+
+#define __ASSEMBLY__
+#include <asm/system.h>
+
+#define halt .long PAL_halt
+
+/*
+ * NOTE! The console bootstrap will load us at 0x20000000, but this image
+ * is linked to run at START_ADDR, so the first thing we do is to move
+ * ourself up to the right address.. We'd better be position-independent
+ * at that stage :-)
+ */
+	.set noreorder
+	.globl	__start
+	.ent	__start
+__start:
+	bis	$31,$31,$31
+	br	$1,$200
+	.long START_ADDR, START_ADDR >> 32	/* strange bug in the assembler.. duh */
+	.long START_SIZE, START_SIZE >> 32
+$200:	ldq	$30,0($1)		/* new stack - below this */
+	lda	$2,-8($1)		/* __start */
+	bis	$30,$30,$3		/* new address */
+	subq	$3,$2,$6		/* difference */
+	ldq	$4,8($1)		/* size */
+$201:	subq	$4,8,$4
+	ldq	$5,0($2)
+	addq	$2,8,$2
+	stq	$5,0($3)
+	addq	$3,8,$3
+	bne	$4,$201
+	br	$1,$202
+$202:	addq	$1,$6,$1
+	addq	$1,12,$1		/* $203 in the new address space */
+	jmp	$31,($1),$203
+$203:	br	$27,$100
+$100:	ldgp	$29,0($27)
+	lda	$27,start_kernel
+	jsr	$26,($27),start_kernel
+	halt
+	.end __start
+
+	.align 5
+	.globl	wrent
+	.ent	wrent
+wrent:
+	.long PAL_wrent
+	ret ($26)
+	.end wrent
+
+	.align 5
+	.globl	wrkgp
+	.ent	wrkgp
+wrkgp:
+	.long PAL_wrkgp
+	ret ($26)
+	.end wrkgp
+
+	.align 5
+	.globl	switch_to_osf_pal
+	.ent	switch_to_osf_pal
+switch_to_osf_pal:
+	subq	$30,128,$30
+	stq	$26,0($30)
+	stq	$1,8($30)
+	stq	$2,16($30)
+	stq	$3,24($30)
+	stq	$4,32($30)
+	stq	$5,40($30)
+	stq	$6,48($30)
+	stq	$7,56($30)
+	stq	$8,64($30)
+	stq	$9,72($30)
+	stq	$10,80($30)
+	stq	$11,88($30)
+	stq	$12,96($30)
+	stq	$13,104($30)
+	stq	$14,112($30)
+	stq	$15,120($30)
+
+	stq	$30,0($17)	/* save KSP in PCB */
+
+	bis	$30,$30,$20	/* a4 = KSP */
+	br	$17,__do_swppal
+
+	ldq	$26,0($30)
+	ldq	$1,8($30)
+	ldq	$2,16($30)
+	ldq	$3,24($30)
+	ldq	$4,32($30)
+	ldq	$5,40($30)
+	ldq	$6,48($30)
+	ldq	$7,56($30)
+	ldq	$8,64($30)
+	ldq	$9,72($30)
+	ldq	$10,80($30)
+	ldq	$11,88($30)
+	ldq	$12,96($30)
+	ldq	$13,104($30)
+	ldq	$14,112($30)
+	ldq	$15,120($30)
+	addq	$30,128,$30
+	ret ($26)
+
+__do_swppal:
+	.long	PAL_swppal
+	.end	switch_to_osf_pal
diff -u --recursive --new-file v1.1.75/linux/arch/alpha/traps.c linux/arch/alpha/traps.c
--- v1.1.75/linux/arch/alpha/traps.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/traps.c	Thu Dec 29 19:58:40 1994
@@ -0,0 +1,58 @@
+/*
+ * kernel/traps.c
+ *
+ * (C) Copyright 1994 Linus Torvalds
+ */
+
+/*
+ * This file initializes the trap entry points
+ */
+
+#include <linux/sched.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+extern asmlinkage void entInt(void);
+void keyboard_interrupt(void);
+
+void do_hw_interrupt(unsigned long type, unsigned long vector)
+{
+	if (type == 1) {
+		jiffies++;
+		return;
+	}
+	/* keyboard or mouse */
+	if (type == 3) {
+		if (vector == 0x980) {
+			keyboard_interrupt();
+			return;
+		} else {
+		unsigned char c = inb_local(0x64);
+		printk("IO device interrupt, vector = %lx\n", vector);
+		if (!(c & 1)) {
+			int i;
+			printk("Hmm. Keyboard interrupt, status = %02x\n", c);
+			for (i = 0; i < 10000000 ; i++)
+				/* nothing */;
+			printk("Serial line interrupt status: %02x\n", inb_local(0x3fa));
+		} else {
+			c = inb_local(0x60);
+			printk("#%02x# ", c);
+		}
+		return;
+		}
+	}
+	printk("Hardware intr %ld %ld\n", type, vector);
+}
+
+void trap_init(void)
+{
+	unsigned long gptr;
+
+	__asm__("br %0,___tmp\n"
+		"___tmp:\tldgp %0,0(%0)"
+		: "=r" (gptr));
+	wrkgp(gptr);
+	wrent(entInt, 0);
+}
diff -u --recursive --new-file v1.1.75/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v1.1.75/linux/arch/i386/Makefile	Thu Dec 29 20:15:55 1994
+++ linux/arch/i386/Makefile	Mon Jan  2 09:25:17 1995
@@ -1,6 +1,11 @@
 #
 # i386/Makefile
 #
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
 # This file is subject to the terms and conditions of the GNU General Public
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
@@ -8,17 +13,18 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
-AS86    =as86 -0 -a
-LD86    =ld86 -0
-AS      =as
-LD      =ld
-HOSTCC  =gcc -I$(TOPDIR)/include
-CC      =gcc -D__KERNEL__ -I$(TOPDIR)/include
-MAKE    =make
-CPP     =$(CC) -E
-AR      =ar
-STRIP   =strip
-
+#
+# Set these to indicate how to link it..
+#
+# -zmagic:   
+#
+# ZLINKFLAGS   = -Ttext 0x1000
+# LINKFLAGS    = -Ttext 0x100000
+#
+# -qmagic (we need to remove the 32 byte header for bootup purposes)
+#
+ZLINKFLAGS =-qmagic -Ttext 0xfe0
+LINKFLAGS =-qmagic -Ttext 0xfffe0
 CFLAGS := $(CFLAGS) -pipe
 
 ifdef CONFIG_M486
@@ -31,85 +37,18 @@
 endif
 endif
 
-arch-all: zImage
+MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
-zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem
-	$(MAKE) -C zBoot
+zImage: vmlinux
+	@$(MAKEBOOT) zImage
 
-zImage: $(CONFIGURE) boot/bootsect boot/setup zBoot/zSystem tools/build
-	tools/build boot/bootsect boot/setup zBoot/zSystem $(ROOT_DEV) > zImage
-	sync
-
-zdisk: zImage
-	dd bs=8192 if=zImage of=/dev/fd0
-
-zlilo: $(CONFIGURE) zImage
-	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
-	if [ -f $(INSTALL_PATH)/zSystem.map ]; then mv $(INSTALL_PATH)/zSystem.map $(INSTALL_PATH)/zSystem.old; fi
-	cat zImage > $(INSTALL_PATH)/vmlinuz
-	cp zSystem.map $(INSTALL_PATH)/
-	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+compressed: zImage
 
-#
-# Set these to indicate how to link it..
-#
-# -zmagic:
-#
-#LOWLDFLAGS     = -Ttext 0x1000
-#HIGHLDFLAGS    = -Ttext 0x100000
-#
-# -qmagic (we need to remove the 32 byte header for bootup purposes)
-#
-LOWLDFLAGS      =-qmagic -Ttext 0xfe0
-HIGHLDFLAGS     =-qmagic -Ttext 0xfffe0
-
-tools/system:	boot/head.o init/main.o tools/version.o linuxsubdirs
-	$(LD) $(LOWLDFLAGS) boot/head.o init/main.o tools/version.o \
-		$(ARCHIVES) \
-		$(FILESYSTEMS) \
-		$(DRIVERS) \
-		$(LIBS) \
-		-o tools/system
-		nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \
-		sort > System.map
-
-boot/setup: boot/setup.o
-	$(LD86) -s -o $@ $<
-
-boot/setup.o: boot/setup.s
-	$(AS86) -o $@ $<
-
-boot/setup.s: boot/setup.S $(CONFIGURE) include/linux/config.h Makefile
-	$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
-
-boot/bootsect: boot/bootsect.o
-	$(LD86) -s -o $@ $<
-
-boot/bootsect.o: boot/bootsect.s
-	$(AS86) -o $@ $<
-
-boot/bootsect.s: boot/bootsect.S $(CONFIGURE) include/linux/config.h Makefile
-	$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
-
-tools/zSystem:	boot/head.o init/main.o tools/version.o linuxsubdirs
-	$(LD) $(HIGHLDFLAGS) boot/head.o init/main.o tools/version.o \
-		$(ARCHIVES) \
-		$(FILESYSTEMS) \
-		$(DRIVERS) \
-		$(LIBS) \
-		-o tools/zSystem
-	nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \
-		sort > zSystem.map
-
-#
-# Leave these dummy entries for now to tell people that they are going away..
-#
-lilo:
-	@echo
-	@echo Uncompressed kernel images no longer supported. Use
-	@echo \"make zlilo\" instead.
-	@echo
-	@exit 1
+zlilo: vmlinux
+	@$(MAKEBOOT) zlilo
 
 archclean:
-	rm -f boot/bootsect boot/setup
+	@$(MAKEBOOT) clean
+
+archdep:
+	@$(MAKEBOOT) dep
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/Makefile linux/arch/i386/boot/Makefile
--- v1.1.75/linux/arch/i386/boot/Makefile	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/Makefile	Mon Jan  2 09:23:11 1995
@@ -0,0 +1,57 @@
+#
+# arch/i386/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+#
+
+AS86    =as86 -0 -a
+LD86    =ld86 -0
+
+zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
+	tools/build bootsect setup compressed/vmlinux $(ROOT_DEV) > zImage
+	sync
+
+compressed/vmlinux: $(TOPDIR)/vmlinux
+	@$(MAKE) -C compressed vmlinux
+
+zdisk: zImage
+	dd bs=8192 if=zImage of=/dev/fd0
+
+zlilo: $(CONFIGURE) zImage
+	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
+	if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
+	cat zImage > $(INSTALL_PATH)/vmlinuz
+	cp $(TOPDIR)/System.map $(INSTALL_PATH)/
+	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+
+tools/build: tools/build.c
+	$(HOSTCC) $(CFLAGS) -o $@ $< -I$(TOPDIR)/include
+
+setup: setup.o
+	$(LD86) -s -o $@ $<
+
+setup.o: setup.s
+	$(AS86) -o $@ $<
+
+setup.s: setup.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
+	$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
+
+bootsect: bootsect.o
+	$(LD86) -s -o $@ $<
+
+bootsect.o: bootsect.s
+	$(AS86) -o $@ $<
+
+bootsect.s: bootsect.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
+	$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
+
+dep:
+
+clean:
+	rm -f bootsect setup
+	rm -f zImage tools/build
+	@$(MAKE) -C compressed clean
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile
--- v1.1.75/linux/arch/i386/boot/compressed/Makefile	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/Makefile	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,35 @@
+#
+# linux/archi/i386/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+HEAD = head.o
+SYSTEM = $(TOPDIR)/vmlinux
+
+OBJECTS = $(HEAD) inflate.o unzip.o misc.o
+
+CFLAGS = -O2 -DSTDC_HEADERS
+
+.c.s:
+	$(CC) $(CFLAGS) -S $<
+.s.o:
+	$(AS) -o $*.o $<
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+all: vmlinux
+
+vmlinux:	piggy.o $(OBJECTS)
+		$(LD) $(ZLINKFLAGS) -o vmlinux $(OBJECTS) piggy.o
+
+head.o:	head.s
+
+head.s: head.S $(TOPDIR)/include/linux/tasks.h
+	$(CPP) -traditional head.S -o head.s
+
+piggy.o:	$(SYSTEM) xtract piggyback
+		./xtract $(SYSTEM) | gzip -9 | ./piggyback > piggy.o
+
+clean:
+	rm -f xtract piggyback vmlinux
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/crypt.h linux/arch/i386/boot/compressed/crypt.h
--- v1.1.75/linux/arch/i386/boot/compressed/crypt.h	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/crypt.h	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,12 @@
+/* crypt.h (dummy version) -- do not perform encryption
+ * Hardly worth copyrighting :-)
+ */
+
+#ifdef CRYPT
+#  undef CRYPT      /* dummy version */
+#endif
+
+#define RAND_HEAD_LEN  12  /* length of encryption random header */
+
+#define zencode
+#define zdecode
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/gzip.h linux/arch/i386/boot/compressed/gzip.h
--- v1.1.75/linux/arch/i386/boot/compressed/gzip.h	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/gzip.h	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,284 @@
+/* gzip.h -- common declarations for all gzip modules
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if defined(__STDC__) || defined(PROTO)
+#  define OF(args)  args
+#else
+#  define OF(args)  ()
+#endif
+
+#ifdef __STDC__
+   typedef void *voidp;
+#else
+   typedef char *voidp;
+#endif
+
+/* I don't like nested includes, but the string functions are used too often */
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#  include <string.h>
+#  define memzero(s, n)     memset ((s), 0, (n))
+#else
+#  include <strings.h>
+#  define strchr            index 
+#  define strrchr           rindex
+#  define memcpy(d, s, n)   bcopy((s), (d), (n)) 
+#  define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) 
+#  define memzero(s, n)     bzero((s), (n))
+#endif
+
+#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
+#  include <memory.h>
+#endif
+
+#ifndef RETSIGTYPE
+#  define RETSIGTYPE void
+#endif
+
+#define local static
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+/* Return codes from gzip */
+#define OK      0
+#define ERROR   1
+#define WARNING 2
+
+/* Compression methods (see algorithm.doc) */
+#define STORED     0
+#define COMPRESSED 1
+#define PACKED     2
+/* methods 3 to 7 reserved */
+#define DEFLATED   8
+extern int method;         /* compression method */
+
+/* To save memory for 16 bit systems, some arrays are overlayed between
+ * the various modules:
+ * deflate:  prev+head   window      d_buf  l_buf  outbuf
+ * unlzw:    tab_prefix  tab_suffix  stack  inbuf  outbuf
+ * inflate:              window             inbuf
+ * unpack:               window             inbuf
+ * For compression, input is done in window[]. For decompression, output
+ * is done in window except for unlzw.
+ */
+
+#ifndef	INBUFSIZ
+#  define INBUFSIZ  0x8000  /* input buffer size */
+#endif
+#define INBUF_EXTRA  64     /* required by unlzw() */
+
+#ifndef	OUTBUFSIZ
+#  define OUTBUFSIZ  16384  /* output buffer size */
+#endif
+#define OUTBUF_EXTRA 2048   /* required by unlzw() */
+
+#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
+
+#ifdef DYN_ALLOC
+#  define EXTERN(type, array)  extern type * near array
+#  define DECLARE(type, array, size)  type * near array
+#  define ALLOC(type, array, size) { \
+      array = (type*)fcalloc((unsigned)(((size)+1L)/2), 2*sizeof(type)); \
+      if (array == NULL) error("insufficient memory"); \
+   }
+#  define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
+#else
+#  define EXTERN(type, array)  extern type array[]
+#  define DECLARE(type, array, size)  type array[size]
+#  define ALLOC(type, array, size)
+#  define FREE(array)
+#endif
+
+EXTERN(uch, inbuf);          /* input buffer */
+EXTERN(uch, outbuf);         /* output buffer */
+EXTERN(ush, d_buf);          /* buffer for distances, see trees.c */
+EXTERN(uch, window);         /* Sliding window and suffix table (unlzw) */
+#define tab_suffix window
+#ifndef MAXSEG_64K
+#  define tab_prefix prev    /* hash link (see deflate.c) */
+#  define head (prev+WSIZE)  /* hash head (see deflate.c) */
+   EXTERN(ush, tab_prefix);  /* prefix code (see unlzw.c) */
+#else
+#  define tab_prefix0 prev
+#  define head tab_prefix1
+   EXTERN(ush, tab_prefix0); /* prefix for even codes */
+   EXTERN(ush, tab_prefix1); /* prefix for odd  codes */
+#endif
+
+extern unsigned insize; /* valid bytes in inbuf */
+extern unsigned inptr;  /* index of next byte to be processed in inbuf */
+extern unsigned outcnt; /* bytes in output buffer */
+
+extern long bytes_in;   /* number of input bytes */
+extern long bytes_out;  /* number of output bytes */
+extern long overhead;   /* number of bytes in gzip header */
+
+#define isize bytes_in
+/* for compatibility with old zip sources (to be cleaned) */
+
+extern int  ifd;        /* input file descriptor */
+extern int  ofd;        /* output file descriptor */
+extern char ifname[];   /* input filename or "stdin" */
+extern char ofname[];   /* output filename or "stdout" */
+
+extern ulg time_stamp;  /* original time stamp (modification time) */
+extern long ifile_size; /* input file size, -1 for devices (debug only) */
+
+extern int exit_code;   /* program exit code */
+
+typedef int file_t;     /* Do not use stdio */
+#define NO_FILE  (-1)   /* in memory compression */
+
+
+#define	GZIP_MAGIC     "\037\213" /* Magic header for gzip files, 1F 8B */
+#define	OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
+#define	PKZIP_MAGIC  "PK\003\004" /* Magic header for pkzip files */
+#define	PACK_MAGIC     "\037\036" /* Magic header for packed files */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+/* internal file attribute */
+#define UNKNOWN (-1)
+#define BINARY  0
+#define ASCII   1
+
+#ifndef WSIZE
+#  define WSIZE 0x8000     /* window size--must be a power of two, and */
+#endif                     /*  at least 32K for zip's deflate method */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST  (WSIZE-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+extern int decrypt;        /* flag to turn on decryption */
+extern int save_orig_name; /* set if original name must be saved */
+extern int verbose;        /* be verbose (-v) */
+extern int level;          /* compression level */
+extern int test;           /* check .z file integrity */
+extern int to_stdout;      /* output to stdout (-c) */
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+
+/* put_byte is used for the compressed output, put_char for the
+ * uncompressed output. However unlzw() uses window for its
+ * suffix table instead of its output buffer, so it does not use put_char.
+ * (to be cleaned up).
+ */
+#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
+   flush_outbuf();}
+#define put_char(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\
+   flush_window();}
+
+/* Output a 16 bit value, lsb first */
+#define put_short(w) \
+{ if (outcnt < OUTBUFSIZ-2) { \
+    outbuf[outcnt++] = (uch) ((w) & 0xff); \
+    outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
+  } else { \
+    put_byte((uch)((w) & 0xff)); \
+    put_byte((uch)((ush)(w) >> 8)); \
+  } \
+}
+
+/* Output a 32 bit value to the bit stream, lsb first */
+#define put_long(n) { \
+    put_short((n) & 0xffff); \
+    put_short(((ulg)(n)) >> 16); \
+}
+
+#define seekable()    0  /* force sequential output */
+#define translate_eol 0  /* no option -a yet */
+
+#define tolow(c)  (isupper(c) ? (c)-'A'+'a' : (c))    /* force to lower case */
+
+/* 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))
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+	/* in zip.c: */
+extern void zip    OF((int in, int out));
+extern int file_read  OF((char *buf,  unsigned size));
+
+	/* in unzip.c */
+extern void unzip        OF((int in, int out));
+extern int check_zipfile OF((int in));
+
+	/* in unpack.c */
+extern void unpack        OF((int in, int out));
+
+	/* in gzip.c */
+RETSIGTYPE abort_gzip   OF((void));
+
+        /* in deflate.c */
+void lm_init OF((int pack_level, ush *flags));
+ulg  deflate OF((void));
+
+        /* in trees.c */
+void ct_init     OF((ush *attr, int *method));
+int  ct_tally    OF((int dist, int lc));
+ulg  flush_block OF((char *buf, ulg stored_len, int eof));
+
+        /* in bits.c */
+void     bi_init    OF((file_t zipfile));
+void     send_bits  OF((int value, int length));
+unsigned bi_reverse OF((unsigned value, int length));
+void     bi_windup  OF((void));
+void     copy_block OF((char *buf, unsigned len, int header));
+extern   int (*read_buf) OF((char *buf, unsigned size));
+
+	/* in util.c: */
+extern ulg  updcrc        OF((uch *s, unsigned n));
+extern void clear_bufs    OF((void));
+extern int  fill_inbuf    OF((void));
+extern void flush_outbuf  OF((void));
+extern void flush_window  OF((void));
+extern char *strlwr       OF((char *s));
+extern char *basename     OF((char *fname));
+extern char *add_envopt   OF((int *argcp, char ***argvp, char *env));
+extern void error         OF((char *m));
+extern void warn          OF((char *a, char *b));
+extern void read_error    OF((void));
+extern void write_error   OF((void));
+extern void display_ratio OF((long num, long den));
+extern voidp xmalloc      OF((unsigned int size));
+
+	/* in inflate.c */
+extern int inflate OF((void));
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/head.S linux/arch/i386/boot/compressed/head.S
--- v1.1.75/linux/arch/i386/boot/compressed/head.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/head.S	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,59 @@
+/*
+ *  linux/boot/head.S
+ *
+ *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
+ */
+
+/*
+ *  head.S contains the 32-bit startup code.
+ *
+ * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
+ * the page directory will exist. The startup code will be overwritten by
+ * the page directory.
+ *
+ * Page 0 is deliberately kept safe, since System Management Mode code in 
+ * laptops may need to access the BIOS data stored there.  This is also
+ * useful for future device drivers that either access the BIOS via VM86 
+ * mode.
+ */
+.text
+
+#define __ASSEMBLY__
+#include <asm/segment.h>
+
+startup_32:
+	cld
+	cli
+	movl $(KERNEL_DS),%eax
+	mov %ax,%ds
+	mov %ax,%es
+	mov %ax,%fs
+	mov %ax,%gs
+	lss _stack_start,%esp
+	xorl %eax,%eax
+1:	incl %eax		# check that A20 really IS enabled
+	movl %eax,0x000000	# loop forever if it isn't
+	cmpl %eax,0x100000
+	je 1b
+/*
+ * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
+ * confuse the debugger if this code is traced.
+ * XXX - best to initialize before switching to protected mode.
+ */
+	pushl $0
+	popfl
+/*
+ * Clear BSS
+ */
+	xorl %eax,%eax
+	movl $__edata,%edi
+	movl $__end,%ecx
+	subl %edi,%ecx
+	cld
+	rep
+	stosb
+/*
+ * Do the decompression, and jump to the new kernel..
+ */
+	call _decompress_kernel
+	ljmp $(KERNEL_CS), $0x100000
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/inflate.c linux/arch/i386/boot/compressed/inflate.c
--- v1.1.75/linux/arch/i386/boot/compressed/inflate.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/inflate.c	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,810 @@
+#define DEBG(x)
+#define DEBG1(x)
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+   version c10p1, 10 January 1993 */
+
+/* 
+ * Adapted for booting Linux by Hannu Savolainen 1993
+ * based on gzip-1.0.3 
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: inflate.c,v 0.10 1993/02/04 13:21:06 jloup Exp $";
+#endif
+
+#include "gzip.h"
+#define slide window
+
+#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
+#  include <sys/types.h>
+#  include <stdlib.h>
+#endif
+
+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;
+};
+
+
+/* Function prototypes */
+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));
+
+
+#define wp outcnt
+#define flush_output(w) (wp=(w),flush_window())
+
+/* 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};
+
+
+ulg bb;                         /* bit buffer */
+unsigned bk;                    /* bits in bit buffer */
+
+ush mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#ifdef CRYPT
+  uch cc;
+#  define NEXTBYTE() \
+     (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
+#else
+#  define NEXTBYTE()  (uch)get_byte()
+#endif
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+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 */
+
+
+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. */
+{
+  unsigned a;                   /* counter for codes of length k */
+  unsigned c[BMAX+1];           /* bit length count table */
+  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 l;                        /* bits per table (returned in m) */
+  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 */
+  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 */
+
+DEBG("huft1 ");
+
+  /* Generate counts for each bit length */
+  memzero(c, sizeof(c));
+  p = b;  i = n;
+  do {
+    c[*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;
+  }
+
+DEBG("huft2 ");
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((unsigned)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((unsigned)l > i)
+    l = i;
+  *m = l;
+
+DEBG("huft3 ");
+
+  /* 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;
+
+DEBG("huft4 ");
+
+  /* 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++);
+  }
+
+DEBG("huft5 ");
+
+  /* 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);
+
+DEBG("h6 ");
+
+  /* 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;                       /* bits decoded == (l * h) */
+  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
+  q = (struct huft *)NULL;      /* ditto */
+  z = 0;                        /* ditto */
+DEBG("h6a ");
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+DEBG("h6b ");
+    a = c[k];
+    while (a--)
+    {
+DEBG("h6b1 ");
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+DEBG1("1 ");
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = (z = g - w) > (unsigned)l ? l : z;  /* upper limit on table size */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+DEBG1("2 ");
+          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 */
+          }
+        }
+DEBG1("3 ");
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate and link in new table */
+        q = (struct huft *)malloc((z + 1)*sizeof(struct huft));
+DEBG1("4 ");
+        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 */
+
+DEBG1("5 ");
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.b = (uch)l;         /* 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 >> (w - l);     /* (get around Turbo C bug) */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+DEBG1("6 ");
+      }
+DEBG("h6c ");
+
+      /* 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];
+      }
+DEBG("h6d ");
+
+      /* 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])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+      }
+DEBG("h6e ");
+    }
+DEBG("h6f ");
+  }
+
+DEBG("huft7 ");
+
+  /* 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(p);
+    p = q;
+  } 
+  return 0;
+}
+
+
+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_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  for (;;)                      /* 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_bits[e]))->e) > 16);
+    DUMPBITS(t->b)
+    if (e == 16)                /* then it's a literal */
+    {
+      slide[w++] = (uch)t->v.n;
+      if (w == WSIZE)
+      {
+        flush_output(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_bits[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_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      NEEDBITS(e)
+      d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e)
+
+      /* do the copy */
+      do {
+        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+#if !defined(NOMEMCPY) && !defined(DEBUG)
+        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_output(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;
+}
+
+
+
+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 */
+
+DEBG("<stor");
+
+  /* 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_output(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;
+
+  DEBG(">");
+  return 0;
+}
+
+
+
+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. */
+{
+  int i;                /* temporary variable */
+  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 l[288];      /* length list for huft_build */
+
+DEBG("<fix");
+
+  /* set up 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;
+  bl = 7;
+  if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+    return i;
+
+
+  /* set up distance table */
+  for (i = 0; i < 30; i++)      /* make an incomplete code set */
+    l[i] = 5;
+  bd = 5;
+  if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
+  {
+    huft_free(tl);
+
+    DEBG(">");
+    return i;
+  }
+
+
+  /* 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_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
+  unsigned ll[288+32];  /* literal/length and distance code lengths */
+#else
+  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 */
+
+DEBG("<dyn");
+
+  /* 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 */
+
+DEBG("dyn1 ");
+
+  /* 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;
+
+DEBG("dyn2 ");
+
+  /* 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 */
+  }
+
+DEBG("dyn3 ");
+
+  /* read in literal and distance code lengths */
+  n = nl + nd;
+  m = mask_bits[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;
+    }
+  }
+
+DEBG("dyn4 ");
+
+  /* free decoding table for trees */
+  huft_free(tl);
+
+DEBG("dyn5 ");
+
+  /* restore the global bit buffer */
+  bb = b;
+  bk = k;
+
+DEBG("dyn5a ");
+
+  /* build the decoding tables for literal/length and distance codes */
+  bl = lbits;
+  if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+  {
+DEBG("dyn5b ");
+    if (i == 1) {
+      error(" incomplete literal tree\n");
+      huft_free(tl);
+    }
+    return i;                   /* incomplete code set */
+  }
+DEBG("dyn5c ");
+  bd = dbits;
+  if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+  {
+DEBG("dyn5d ");
+    if (i == 1) {
+      error(" incomplete distance tree\n");
+#ifdef PKZIP_BUG_WORKAROUND
+      i = 0;
+    }
+#else
+      huft_free(td);
+    }
+    huft_free(tl);
+    return i;                   /* incomplete code set */
+#endif
+  }
+
+DEBG("dyn6 ");
+
+  /* decompress until an end-of-block code */
+  if (inflate_codes(tl, td, bl, bd))
+    return 1;
+
+DEBG("dyn7 ");
+
+  /* free the decoding tables, return */
+  huft_free(tl);
+  huft_free(td);
+
+  DEBG(">");
+  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 */
+
+  DEBG("<blk");
+
+  /* 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();
+
+  DEBG(">");
+
+  /* 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);
+
+  /* Undo too much lookahead. The next read will be byte aligned so we
+   * can discard unused bits in the last meaningful byte.
+   */
+  while (bk >= 8) {
+    bk -= 8;
+    inptr--;
+  }
+
+  /* flush out slide */
+  flush_output(wp);
+
+
+  /* return success */
+#ifdef DEBUG
+  fprintf(stderr, "<%u> ", h);
+#endif /* DEBUG */
+  return 0;
+}
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/lzw.h linux/arch/i386/boot/compressed/lzw.h
--- v1.1.75/linux/arch/i386/boot/compressed/lzw.h	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/lzw.h	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,42 @@
+/* lzw.h -- define the lzw functions.
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if !defined(OF) && defined(lint)
+#  include "gzip.h"
+#endif
+
+#ifndef BITS
+#  define BITS 16
+#endif
+#define INIT_BITS 9              /* Initial number of bits per code */
+
+#define	LZW_MAGIC  "\037\235"   /* Magic header for lzw files, 1F 9D */
+
+#define BIT_MASK    0x1f /* Mask for 'number of compression bits' */
+/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
+ * It's a pity that old uncompress does not check bit 0x20. That makes
+ * extension of the format actually undesirable because old compress
+ * would just crash on the new format instead of giving a meaningful
+ * error message. It does check the number of bits, but it's more
+ * helpful to say "unsupported format, get a new version" than
+ * "can only handle 16 bits".
+ */
+
+#define BLOCK_MODE  0x80
+/* Block compression: if table is full and compression rate is dropping,
+ * clear the dictionary.
+ */
+
+#define LZW_RESERVED 0x60 /* reserved bits */
+
+#define	CLEAR  256       /* flush the dictionary */
+#define FIRST  (CLEAR+1) /* first free entry */
+
+extern int maxbits;      /* max bits per code for LZW */
+extern int block_mode;   /* block compress mode -C compatible with 2.0 */
+
+extern void lzw    OF((int in, int out));
+extern void unlzw  OF((int in, int out));
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c
--- v1.1.75/linux/arch/i386/boot/compressed/misc.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/misc.c	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,418 @@
+/*
+ * misc.c
+ * 
+ * This is a collection of several routines from gzip-1.0.3 
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ * puts by Nick Holloway 1993
+ */
+
+#include "gzip.h"
+#include "lzw.h"
+
+#include <asm/segment.h>
+
+/*
+ * These are set up by the setup-routine at boot-time:
+ */
+
+struct screen_info {
+	unsigned char  orig_x;
+	unsigned char  orig_y;
+	unsigned char  unused1[2];
+	unsigned short orig_video_page;
+	unsigned char  orig_video_mode;
+	unsigned char  orig_video_cols;
+	unsigned short orig_video_ega_ax;
+	unsigned short orig_video_ega_bx;
+	unsigned short orig_video_ega_cx;
+	unsigned char  orig_video_lines;
+};
+
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define EXT_MEM_K (*(unsigned short *)0x90002)
+#define DRIVE_INFO (*(struct drive_info *)0x90080)
+#define SCREEN_INFO (*(struct screen_info *)0x90000)
+#define RAMDISK_SIZE (*(unsigned short *)0x901F8)
+#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
+#define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
+
+#define EOF -1
+
+DECLARE(uch, inbuf, INBUFSIZ);
+DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
+DECLARE(uch, window, WSIZE);
+
+unsigned outcnt;
+unsigned insize;
+unsigned inptr;
+
+extern char input_data[];
+extern int input_len;
+
+int input_ptr;
+
+int method, exit_code, part_nb, last_member;
+int test = 0;
+int force = 0;
+int verbose = 1;
+long bytes_in, bytes_out;
+
+char *output_data;
+unsigned long output_ptr;
+
+extern int end;
+long free_mem_ptr = (long)&end;
+
+int to_stdout = 0;
+int hard_math = 0;
+
+void (*work)(int inf, int outf);
+void makecrc(void);
+
+local int get_method(int);
+
+char *vidmem = (char *)0xb8000;
+int lines, cols;
+
+static void puts(const char *);
+
+void *malloc(int size)
+{
+	void *p;
+
+	if (size <0) error("Malloc error\n");
+	if (free_mem_ptr <= 0) error("Memory error\n");
+
+   while(1) {
+	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
+
+	p = (void *)free_mem_ptr;
+	free_mem_ptr += size;
+
+	/*
+  	 * The part of the compressed kernel which has already been expanded
+	 * is no longer needed. Therefore we can reuse it for malloc.
+	 * With bigger kernels, this is necessary.
+	 */
+          
+	if (free_mem_ptr < (long)&end) {
+		if (free_mem_ptr > (long)&input_data[input_ptr])
+			error("\nOut of memory\n");
+
+		return p;
+	}
+	if (free_mem_ptr < 0x90000)
+	return p;
+	puts("memory is tight...");
+	free_mem_ptr = (long)input_data;
+	}
+}
+
+void free(void *where)
+{	/* Don't care */
+}
+
+static void scroll()
+{
+	int i;
+
+	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+		vidmem[i] = ' ';
+}
+
+static void puts(const char *s)
+{
+	int x,y;
+	char c;
+
+	x = SCREEN_INFO.orig_x;
+	y = SCREEN_INFO.orig_y;
+
+	while ( ( c = *s++ ) != '\0' ) {
+		if ( c == '\n' ) {
+			x = 0;
+			if ( ++y >= lines ) {
+				scroll();
+				y--;
+			}
+		} else {
+			vidmem [ ( x + cols * y ) * 2 ] = c; 
+			if ( ++x >= cols ) {
+				x = 0;
+				if ( ++y >= lines ) {
+					scroll();
+					y--;
+				}
+			}
+		}
+	}
+
+	SCREEN_INFO.orig_x = x;
+	SCREEN_INFO.orig_y = y;
+}
+
+__ptr_t memset(__ptr_t s, int c, size_t n)
+{
+	int i;
+	char *ss = (char*)s;
+
+	for (i=0;i<n;i++) ss[i] = c;
+}
+
+__ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
+			    size_t __n)
+{
+	int i;
+	char *d = (char *)__dest, *s = (char *)__src;
+
+	for (i=0;i<__n;i++) d[i] = s[i];
+}
+
+extern ulg crc_32_tab[];   /* crc table, defined below */
+
+/* ===========================================================================
+ * 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.
+ */
+ulg updcrc(s, n)
+    uch *s;                 /* pointer to bytes to pump through */
+    unsigned n;             /* number of bytes in s[] */
+{
+    register ulg c;         /* temporary variable */
+
+    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
+
+    if (s == 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) */
+}
+
+/* ===========================================================================
+ * Clear input and output buffers
+ */
+void clear_bufs()
+{
+    outcnt = 0;
+    insize = inptr = 0;
+    bytes_in = bytes_out = 0L;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+int fill_inbuf()
+{
+    int len, i;
+
+    /* Read as much as possible */
+    insize = 0;
+    do {
+	len = INBUFSIZ-insize;
+	if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1;
+        if (len == 0 || len == EOF) break;
+
+        for (i=0;i<len;i++) inbuf[insize+i] = input_data[input_ptr+i];
+	insize += len;
+	input_ptr += len;
+    } while (insize < INBUFSIZ);
+
+    if (insize == 0) {
+	error("unable to fill buffer\n");
+    }
+    bytes_in += (ulg)insize;
+    inptr = 1;
+    return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+void flush_window()
+{
+    if (outcnt == 0) return;
+    updcrc(window, outcnt);
+
+    memcpy(&output_data[output_ptr], (char *)window, outcnt);
+
+    bytes_out += (ulg)outcnt;
+    output_ptr += (ulg)outcnt;
+    outcnt = 0;
+}
+
+/*
+ * Code to compute the CRC-32 table. Borrowed from 
+ * gzip-1.0.3/makecrc.c.
+ */
+
+ulg crc_32_tab[256];
+
+void
+makecrc(void)
+{
+/* Not copyrighted 1990 Mark Adler	*/
+
+  unsigned long c;      /* crc shift register */
+  unsigned long e;      /* polynomial exclusive-or pattern */
+  int i;                /* counter for all possible eight bit values */
+  int k;                /* byte being shifted into crc apparatus */
+
+  /* terms of polynomial defining this crc (except x^32): */
+  static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* Make exclusive-or pattern from polynomial */
+  e = 0;
+  for (i = 0; i < sizeof(p)/sizeof(int); i++)
+    e |= 1L << (31 - p[i]);
+
+  crc_32_tab[0] = 0;
+
+  for (i = 1; i < 256; i++)
+  {
+    c = 0;
+    for (k = i | 256; k != 1; k >>= 1)
+    {
+      c = c & 1 ? (c >> 1) ^ e : c >> 1;
+      if (k & 1)
+        c ^= e;
+    }
+    crc_32_tab[i] = c;
+  }
+}
+
+void error(char *x)
+{
+	puts("\n\n");
+	puts(x);
+	puts("\n\n -- System halted");
+
+	while(1);	/* Halt */
+}
+
+#define STACK_SIZE (4096)
+
+long user_stack [STACK_SIZE];
+
+struct {
+	long * a;
+	short b;
+	} stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS };
+
+void decompress_kernel()
+{
+	if (SCREEN_INFO.orig_video_mode == 7)
+		vidmem = (char *) 0xb0000;
+	else
+		vidmem = (char *) 0xb8000;
+
+	lines = SCREEN_INFO.orig_video_lines;
+	cols = SCREEN_INFO.orig_video_cols;
+
+	if (EXT_MEM_K < 1024) error("<2M of mem\n");
+
+	output_data = (char *)0x100000;	/* Points to 1M */
+	output_ptr = 0;
+
+	exit_code = 0;
+	test = 0;
+	input_ptr = 0;
+	part_nb = 0;
+
+	clear_bufs();
+	makecrc();
+
+	puts("Uncompressing Linux...");
+
+	method = get_method(0);
+
+	work(0, 0);
+
+	puts("done.\n");
+
+	puts("Now booting the kernel\n");
+}
+
+/* ========================================================================
+ * Check the magic number of the input file and update ofname if an
+ * original name was given and to_stdout is not set.
+ * Return the compression method, -1 for error, -2 for warning.
+ * Set inptr to the offset of the next byte to be processed.
+ * This function may be called repeatedly for an input file consisting
+ * of several contiguous gzip'ed members.
+ * IN assertions: there is at least one remaining compressed member.
+ *   If the member is a zip file, it must be the only one.
+ */
+local int get_method(in)
+    int in;        /* input file descriptor */
+{
+    uch flags;
+    char magic[2]; /* magic header */
+
+    magic[0] = (char)get_byte();
+    magic[1] = (char)get_byte();
+
+    method = -1;                 /* unknown yet */
+    part_nb++;                   /* number of parts in gzip file */
+    last_member = 0;
+    /* assume multiple members in gzip file except for record oriented I/O */
+
+    if (memcmp(magic, GZIP_MAGIC, 2) == 0
+        || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
+
+	work = unzip;
+	method = (int)get_byte();
+	flags  = (uch)get_byte();
+	if ((flags & ENCRYPTED) != 0)
+	    error("Input is encrypted\n");
+	if ((flags & CONTINUATION) != 0)
+	       error("Multi part input\n");
+	if ((flags & RESERVED) != 0) {
+	    error("Input has invalid flags\n");
+	    exit_code = ERROR;
+	    if (force <= 1) return -1;
+	}
+	(ulg)get_byte();	/* Get timestamp */
+	((ulg)get_byte()) << 8;
+	((ulg)get_byte()) << 16;
+	((ulg)get_byte()) << 24;
+
+	(void)get_byte();  /* Ignore extra flags for the moment */
+	(void)get_byte();  /* Ignore OS type for the moment */
+
+	if ((flags & EXTRA_FIELD) != 0) {
+	    unsigned len = (unsigned)get_byte();
+	    len |= ((unsigned)get_byte())<<8;
+	    while (len--) (void)get_byte();
+	}
+
+	/* Get original file name if it was truncated */
+	if ((flags & ORIG_NAME) != 0) {
+	    if (to_stdout || part_nb > 1) {
+		/* Discard the old name */
+		while (get_byte() != 0) /* null */ ;
+	    } else {
+	    } /* to_stdout */
+	} /* orig_name */
+
+	/* Discard file comment if any */
+	if ((flags & COMMENT) != 0) {
+	    while (get_byte() != 0) /* null */ ;
+	}
+    } else
+	error("unknown compression method");
+    return method;
+}
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/piggyback.c linux/arch/i386/boot/compressed/piggyback.c
--- v1.1.75/linux/arch/i386/boot/compressed/piggyback.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/piggyback.c	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,81 @@
+/*
+ *	linux/zBoot/piggyback.c
+ *
+ *	(C) 1993 Hannu Savolainen
+ */
+
+/*
+ *	This program reads the compressed system image from stdin and
+ *	encapsulates it into an object file written to the stdout.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <a.out.h>
+
+int main(int argc, char *argv[])
+{
+	int c, n=0, len=0;
+	char tmp_buf[512*1024];
+	
+	struct exec obj = {0x00640107};	/* object header */
+	char string_names[] = {"_input_data\0_input_len\0"};
+
+	struct nlist var_names[2] = /* Symbol table */
+		{	
+			{	/* _input_data	*/
+				(char *)4, 7, 0, 0, 0
+			},
+			{	/* _input_len */
+				(char *)16, 7, 0, 0, 0
+			}
+		};
+
+
+	len = 0;
+	while ((n = read(0, &tmp_buf[len], sizeof(tmp_buf)-len+1)) > 0)
+	      len += n;
+
+	if (n==-1)
+	{
+		perror("stdin");
+		exit(-1);
+	}
+
+	if (len >= sizeof(tmp_buf))
+	{
+		fprintf(stderr, "%s: Input too large\n", argv[0]);
+		exit(-1);
+	}
+
+	fprintf(stderr, "Compressed size %d.\n", len);
+
+/*
+ *	Output object header
+ */
+	obj.a_data = len + sizeof(long);
+	obj.a_syms = sizeof(var_names);
+	write(1, (char *)&obj, sizeof(obj));
+
+/*
+ *	Output data segment (compressed system & len)
+ */
+	write(1, tmp_buf, len);
+	write(1, (char *)&len, sizeof(len));
+
+/*
+ *	Output symbol table
+ */
+	var_names[1].n_value = len;
+	write(1, (char *)&var_names, sizeof(var_names));
+
+/*
+ *	Output string table
+ */
+	len = sizeof(string_names) + sizeof(len);
+	write(1, (char *)&len, sizeof(len));
+	write(1, string_names, sizeof(string_names));
+
+	exit(0);
+
+}
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/unzip.c linux/arch/i386/boot/compressed/unzip.c
--- v1.1.75/linux/arch/i386/boot/compressed/unzip.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/unzip.c	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,180 @@
+/* unzip.c -- decompress files in gzip or pkzip format.
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ *
+ * Adapted for Linux booting by Hannu Savolainen 1993
+ *
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ *
+ * The code in this file is derived from the file funzip.c written
+ * and put in the public domain by Mark Adler.
+ */
+
+/*
+   This version can extract files in gzip or pkzip format.
+   For the latter, only the first entry is extracted, and it has to be
+   either deflated or stored.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: unzip.c,v 0.9 1993/02/10 16:07:22 jloup Exp $";
+#endif
+
+#include "gzip.h"
+#include "crypt.h"
+
+#include <stdio.h>
+
+/* PKZIP header definitions */
+#define LOCSIG 0x04034b50L      /* four-byte lead-in (lsb first) */
+#define LOCFLG 6                /* offset of bit flag */
+#define  CRPFLG 1               /*  bit for encrypted entry */
+#define  EXTFLG 8               /*  bit for extended local header */
+#define LOCHOW 8                /* offset of compression method */
+#define LOCTIM 10               /* file mod time (for decryption) */
+#define LOCCRC 14               /* offset of crc */
+#define LOCSIZ 18               /* offset of compressed size */
+#define LOCLEN 22               /* offset of uncompressed length */
+#define LOCFIL 26               /* offset of file name field length */
+#define LOCEXT 28               /* offset of extra field length */
+#define LOCHDR 30               /* size of local header, including sig */
+#define EXTHDR 16               /* size of extended local header, inc sig */
+
+
+/* Globals */
+
+int decrypt;      /* flag to turn on decryption */
+char *key;        /* not used--needed to link crypt.c */
+int pkzip = 0;    /* set for a pkzip file */
+int extended = 0; /* set if extended local header */
+
+/* ===========================================================================
+ * Check zip file and advance inptr to the start of the compressed data.
+ * Get ofname from the local header if necessary.
+ */
+int check_zipfile(in)
+    int in;   /* input file descriptors */
+{
+    uch *h = inbuf + inptr; /* first local header */
+
+    /* ifd = in; */
+
+    /* Check validity of local header, and skip name and extra fields */
+    inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
+
+    if (inptr > insize || LG(h) != LOCSIG) {
+	error("input not a zip");
+    }
+    method = h[LOCHOW];
+    if (method != STORED && method != DEFLATED) {
+	error("first entry not deflated or stored--can't extract");
+    }
+
+    /* If entry encrypted, decrypt and validate encryption header */
+    if ((decrypt = h[LOCFLG] & CRPFLG) != 0) {
+	error("encrypted file\n");
+	exit_code = ERROR;
+	return -1;
+    }
+
+    /* Save flags for unzip() */
+    extended = (h[LOCFLG] & EXTFLG) != 0;
+    pkzip = 1;
+
+    /* Get ofname and time stamp from local header (to be done) */
+    return 0;
+}
+
+/* ===========================================================================
+ * Unzip in to out.  This routine works on both gzip and pkzip files.
+ *
+ * IN assertions: the buffer inbuf contains already the beginning of
+ *   the compressed data, from offsets inptr to insize-1 included.
+ *   The magic header has already been checked. The output buffer is cleared.
+ */
+void unzip(in, out)
+    int in, out;   /* input and output file descriptors */
+{
+    ulg orig_crc = 0;       /* original crc */
+    ulg orig_len = 0;       /* original uncompressed length */
+    int n;
+    uch buf[EXTHDR];        /* extended local header */
+
+    /* ifd = in;
+    ofd = out; */
+
+    updcrc(NULL, 0);           /* initialize crc */
+
+    if (pkzip && !extended) {  /* crc and length at the end otherwise */
+	orig_crc = LG(inbuf + LOCCRC);
+	orig_len = LG(inbuf + LOCLEN);
+    }
+
+    /* Decompress */
+    if (method == DEFLATED)  {
+
+	int res = inflate();
+
+	if (res == 3) {
+	    error("out of memory");
+	} else if (res != 0) {
+	    error("invalid compressed format");
+	}
+
+    } else if (pkzip && method == STORED) {
+
+	register ulg n = LG(inbuf + LOCLEN);
+
+	if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) {
+
+	    error("length mismatch");
+	}
+	while (n--) {
+	    uch c = (uch)get_byte();
+#ifdef CRYPT
+	    if (decrypt) zdecode(c);
+#endif
+	    if (!test) put_char(c);
+	}
+    } else {
+	error("internal error, invalid method");
+    }
+
+    /* Get the crc and original length */
+    if (!pkzip) {
+        /* crc32  (see algorithm.doc)
+	 * uncompressed input size modulo 2^32
+         */
+	for (n = 0; n < 8; n++) {
+	    buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+	}
+	orig_crc = LG(buf);
+	orig_len = LG(buf+4);
+
+    } else if (extended) {  /* If extended header, check it */
+	/* signature - 4bytes: 0x50 0x4b 0x07 0x08
+	 * CRC-32 value
+         * compressed size 4-bytes
+         * uncompressed size 4-bytes
+	 */
+	for (n = 0; n < EXTHDR; n++) {
+	    buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+	}
+	orig_crc = LG(buf+4);
+	orig_len = LG(buf+12);
+    }
+
+    /* Validate decompression */
+    if (orig_crc != updcrc(outbuf, 0)) {
+	error("crc error");
+    }
+    if (orig_len != bytes_out) {
+	error("length error");
+    }
+
+    /* Check if there are more entries in a pkzip file */
+    if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
+	    error("zip file has more than one entry");
+    }
+    extended = pkzip = 0; /* for next file */
+}
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/compressed/xtract.c linux/arch/i386/boot/compressed/xtract.c
--- v1.1.75/linux/arch/i386/boot/compressed/xtract.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/xtract.c	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,87 @@
+/*
+ *  linux/zBoot/xtract.c
+ *
+ *  Copyright (C) 1993  Hannu Savolainen
+ *
+ *	Extracts the system image and writes it to the stdout.
+ *	based on tools/build.c by Linus Torvalds
+ */
+
+#include <stdio.h>	/* fprintf */
+#include <string.h>
+#include <stdlib.h>	/* contains exit */
+#include <sys/types.h>	/* unistd.h needs this */
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>	/* contains read/write */
+#include <fcntl.h>
+#include <a.out.h>
+#include <linux/config.h>
+
+#define N_MAGIC_OFFSET 1024
+
+static int GCC_HEADER = sizeof(struct exec);
+
+#define STRINGIFY(x) #x
+
+void die(char * str)
+{
+	fprintf(stderr,"%s\n",str);
+	exit(1);
+}
+
+void usage(void)
+{
+	die("Usage: xtract system [ | gzip | piggyback > piggy.s]");
+}
+
+int main(int argc, char ** argv)
+{
+	int i,c,id, sz;
+	char buf[1024];
+	char major_root, minor_root;
+	struct stat sb;
+
+	struct exec *ex = (struct exec *)buf;
+
+	if (argc  != 2)
+		usage();
+	
+	if ((id=open(argv[1],O_RDONLY,0))<0)
+		die("Unable to open 'system'");
+	if (read(id,buf,GCC_HEADER) != GCC_HEADER)
+		die("Unable to read header of 'system'");
+	if (N_MAGIC(*ex) == ZMAGIC) {
+		GCC_HEADER = N_MAGIC_OFFSET;
+		lseek(id, GCC_HEADER, SEEK_SET);
+	} else if (N_MAGIC(*ex) != QMAGIC)
+		die("Non-GCC header of 'system'");
+
+	sz = N_SYMOFF(*ex) - GCC_HEADER + 4;	/* +4 to get the same result than tools/build */
+
+	fprintf(stderr, "System size is %d\n", sz);
+
+	while (sz)
+	{
+		int l, n;
+
+		l = sz;
+		if (l > sizeof(buf)) l = sizeof(buf);
+
+		if ((n=read(id, buf, l)) !=l)
+		{
+			if (n == -1) 
+			   perror(argv[1]);
+			else
+			   fprintf(stderr, "Unexpected EOF\n");
+
+			die("Can't read system");
+		}
+
+		write(1, buf, l);
+		sz -= l;
+	}
+
+	close(id);
+	return(0);
+}
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/head.S linux/arch/i386/boot/head.S
--- v1.1.75/linux/arch/i386/boot/head.S	Thu Dec 29 20:15:56 1994
+++ linux/arch/i386/boot/head.S	Thu Dec 29 19:58:41 1994
@@ -1,362 +0,0 @@
-/*
- *  linux/boot/head.S
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-/*
- *  head.S contains the 32-bit startup code.
- */
-
-.text
-.globl _idt,_gdt,
-.globl _swapper_pg_dir,_pg0
-.globl _empty_bad_page
-.globl _empty_bad_page_table
-.globl _empty_zero_page
-.globl _floppy_track_buffer
-
-#define __ASSEMBLY__
-#include <linux/tasks.h>
-#include <linux/fd.h>
-#include <asm/segment.h>
-
-#define CL_MAGIC_ADDR	0x90020
-#define CL_MAGIC	0xA33F
-#define CL_BASE_ADDR	0x90000
-#define CL_OFFSET	0x90022
-
-/*
- * swapper_pg_dir is the main page directory, address 0x00001000 (or at
- * address 0x00101000 for a compressed boot).
- */
-startup_32:
-	cld
-	movl $(KERNEL_DS),%eax
-	mov %ax,%ds
-	mov %ax,%es
-	mov %ax,%fs
-	mov %ax,%gs
-	lss stack_start,%esp
-/*
- * Clear BSS first so that there are no surprises...
- */
-	xorl %eax,%eax
-	movl $__edata,%edi
-	movl $__end,%ecx
-	subl %edi,%ecx
-	cld
-	rep
-	stosb
-/*
- * start system 32-bit setup. We need to re-do some of the things done
- * in 16-bit mode for the "real" operations.
- */
-	call setup_idt
-	xorl %eax,%eax
-1:	incl %eax		# check that A20 really IS enabled
-	movl %eax,0x000000	# loop forever if it isn't
-	cmpl %eax,0x100000
-	je 1b
-/*
- * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
- * confuse the debugger if this code is traced.
- * XXX - best to initialize before switching to protected mode.
- */
-	pushl $0
-	popfl
-/*
- * Copy bootup parameters out of the way. First 2kB of
- * _empty_zero_page is for boot parameters, second 2kB
- * is for the command line.
- */
-	movl $0x90000,%esi
-	movl $_empty_zero_page,%edi
-	movl $512,%ecx
-	cld
-	rep
-	movsl
-	xorl %eax,%eax
-	movl $512,%ecx
-	rep
-	stosl
-	cmpw $(CL_MAGIC),CL_MAGIC_ADDR
-	jne 1f
-	movl $_empty_zero_page+2048,%edi
-	movzwl CL_OFFSET,%esi
-	addl $(CL_BASE_ADDR),%esi
-	movl $2048,%ecx
-	rep
-	movsb
-1:
-/* check if it is 486 or 386. */
-/*
- * XXX - this does a lot of unnecessary setup.  Alignment checks don't
- * apply at our cpl of 0 and the stack ought to be aligned already, and
- * we don't need to preserve eflags.
- */
-	movl $3,_x86
-	pushfl			# push EFLAGS
-	popl %eax		# get EFLAGS
-	movl %eax,%ecx		# save original EFLAGS
-	xorl $0x40000,%eax	# flip AC bit in EFLAGS
-	pushl %eax		# copy to EFLAGS
-	popfl			# set EFLAGS
-	pushfl			# get new EFLAGS
-	popl %eax		# put it in eax
-	xorl %ecx,%eax		# change in flags
-	andl $0x40000,%eax	# check if AC bit changed
-	je is386
-	movl $4,_x86
-	movl %ecx,%eax
-	xorl $0x200000,%eax	# check ID flag
-	pushl %eax
-	popfl			# if we are on a straight 486DX, SX, or
-	pushfl			# 487SX we can't change it
-	popl %eax
-	xorl %ecx,%eax
-	andl $0x200000,%eax
-	je is486
-isnew:	pushl %ecx		# restore original EFLAGS
-	popfl
-	/* get processor type */
-	movl $1, %eax		# Use the CPUID instruction to 
-	.byte 0x0f, 0xa2	# check the processor type
-	movb %al, %cl		# save reg for future use
-	andb $0x0f,%ah		# mask processor family
-	movb %ah, _x86
-	andb $0xf0, %eax	# mask model
-	shrb $4, %al
-	movb %al, _x86_model
-	andb $0x0f, %cl		# mask mask revision
-	movb %cl, _x86_mask
-	movl %edx, _x86_capability
-	/* get vendor info */
-	xorl %eax, %eax			# call CPUID with 0 -> return vendor ID
-	.byte 0x0f, 0xa2		# CPUID
-	movl %ebx, _x86_vendor_id	# lo 4 chars
-	movl %edx, _x86_vendor_id+4	# next 4 chars
-	movl %ecx, _x86_vendor_id+8	# last 4 chars
-
-	movl %cr0,%eax		# 486+
-	andl $0x80000011,%eax	# Save PG,PE,ET
-	orl $0x50022,%eax	# set AM, WP, NE and MP
-	jmp 2f
-is486:	pushl %ecx		# restore original EFLAGS
-	popfl
-	movl %cr0,%eax		# 486
-	andl $0x80000011,%eax	# Save PG,PE,ET
-	orl $0x50022,%eax	# set AM, WP, NE and MP
-	jmp 2f
-is386:	pushl %ecx		# restore original EFLAGS
-	popfl
-	movl %cr0,%eax		# 386
-	andl $0x80000011,%eax	# Save PG,PE,ET
-	orl $2,%eax		# set MP
-2:	movl %eax,%cr0
-	call check_x87
-	call setup_paging
-	lgdt gdt_descr
-	lidt idt_descr
-	ljmp $(KERNEL_CS),$1f
-1:	movl $(KERNEL_DS),%eax	# reload all the segment registers
-	mov %ax,%ds		# after changing gdt.
-	mov %ax,%es
-	mov %ax,%fs
-	mov %ax,%gs
-	lss stack_start,%esp
-	xorl %eax,%eax
-	lldt %ax
-	pushl %eax		# These are the parameters to main :-)
-	pushl %eax
-	pushl %eax
-	cld			# gcc2 wants the direction flag cleared at all times
-	call _start_kernel
-L6:
-	jmp L6			# main should never return here, but
-				# just in case, we know what happens.
-
-/*
- * We depend on ET to be correct. This checks for 287/387.
- */
-check_x87:
-	movb $0,_hard_math
-	clts
-	fninit
-	fstsw %ax
-	cmpb $0,%al
-	je 1f
-	movl %cr0,%eax		/* no coprocessor: have to set bits */
-	xorl $4,%eax		/* set EM */
-	movl %eax,%cr0
-	ret
-.align 2
-1:	movb $1,_hard_math
-	.byte 0xDB,0xE4		/* fsetpm for 287, ignored by 387 */
-	ret
-
-/*
- *  setup_idt
- *
- *  sets up a idt with 256 entries pointing to
- *  ignore_int, interrupt gates. It doesn't actually load
- *  idt - that can be done only after paging has been enabled
- *  and the kernel moved to 0xC0000000. Interrupts
- *  are enabled elsewhere, when we can be relatively
- *  sure everything is ok.
- */
-setup_idt:
-	lea ignore_int,%edx
-	movl $(KERNEL_CS << 16),%eax
-	movw %dx,%ax		/* selector = 0x0010 = cs */
-	movw $0x8E00,%dx	/* interrupt gate - dpl=0, present */
-
-	lea _idt,%edi
-	mov $256,%ecx
-rp_sidt:
-	movl %eax,(%edi)
-	movl %edx,4(%edi)
-	addl $8,%edi
-	dec %ecx
-	jne rp_sidt
-	ret
-
-
-/*
- * Setup_paging
- *
- * This routine sets up paging by setting the page bit
- * in cr0. The page tables are set up, identity-mapping
- * the first 4MB.  The rest are initialized later.
- *
- * (ref: added support for up to 32mb, 17Apr92)  -- Rik Faith
- * (ref: update, 25Sept92)  -- croutons@crunchy.uucp 
- * (ref: 92.10.11 - Linus Torvalds. Corrected 16M limit - no upper memory limit)
- */
-.align 2
-setup_paging:
-	movl $1024*2,%ecx		/* 2 pages - swapper_pg_dir+1 page table */
-	xorl %eax,%eax
-	movl $_swapper_pg_dir,%edi	/* swapper_pg_dir is at 0x1000 */
-	cld;rep;stosl
-/* Identity-map the kernel in low 4MB memory for ease of transition */
-	movl $_pg0+7,_swapper_pg_dir		/* set present bit/user r/w */
-/* But the real place is at 0xC0000000 */
-	movl $_pg0+7,_swapper_pg_dir+3072	/* set present bit/user r/w */
-	movl $_pg0+4092,%edi
-	movl $0x03ff007,%eax		/*  4Mb - 4096 + 7 (r/w user,p) */
-	std
-1:	stosl			/* fill the page backwards - more efficient :-) */
-	subl $0x1000,%eax
-	jge 1b
-	cld
-	movl $_swapper_pg_dir,%eax
-	movl %eax,%cr3			/* cr3 - page directory start */
-	movl %cr0,%eax
-	orl $0x80000000,%eax
-	movl %eax,%cr0		/* set paging (PG) bit */
-	ret			/* this also flushes the prefetch-queue */
-
-/*
- * page 0 is made non-existent, so that kernel NULL pointer references get
- * caught. Thus the swapper page directory has been moved to 0x1000
- *
- * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte,
- * with the introduction of the compressed boot code.  Theoretically,
- * the original design of overlaying the startup code with the swapper
- * page directory is still possible --- it would reduce the size of the kernel
- * by 2-3k.  This would be a good thing to do at some point.....
- */
-.org 0x1000
-_swapper_pg_dir:
-/*
- * The page tables are initialized to only 4MB here - the final page
- * tables are set up later depending on memory size.
- */
-.org 0x2000
-_pg0:
-
-.org 0x3000
-_empty_bad_page:
-
-.org 0x4000
-_empty_bad_page_table:
-
-.org 0x5000
-_empty_zero_page:
-
-.org 0x6000
-/*
- * floppy_track_buffer is used to buffer one track of floppy data: it
- * has to be separate from the tmp_floppy area, as otherwise a single-
- * sector read/write can mess it up. It can contain one full cylinder (sic) of
- * data (36*2*512 bytes).
- */
-_floppy_track_buffer:
-	.fill 512*2*MAX_BUFFER_SECTORS,1,0
-	
-stack_start:
-	.long _init_user_stack+4096
-	.long KERNEL_DS
-
-/* This is the default interrupt "handler" :-) */
-int_msg:
-	.asciz "Unknown interrupt\n"
-.align 2
-ignore_int:
-	cld
-	pushl %eax
-	pushl %ecx
-	pushl %edx
-	push %ds
-	push %es
-	push %fs
-	movl $(KERNEL_DS),%eax
-	mov %ax,%ds
-	mov %ax,%es
-	mov %ax,%fs
-	pushl $int_msg
-	call _printk
-	popl %eax
-	pop %fs
-	pop %es
-	pop %ds
-	popl %edx
-	popl %ecx
-	popl %eax
-	iret
-
-/*
- * The interrupt descriptor table has room for 256 idt's
- */
-.align 4
-.word 0
-idt_descr:
-	.word 256*8-1		# idt contains 256 entries
-	.long 0xc0000000+_idt
-
-.align 4
-_idt:
-	.fill 256,8,0		# idt is uninitialized
-
-.align 4
-.word 0
-gdt_descr:
-	.word (8+2*NR_TASKS)*8-1
-	.long 0xc0000000+_gdt
-
-/*
- * This gdt setup gives the kernel a 1GB address space at virtual
- * address 0xC0000000 - space enough for expansion, I hope.
- */
-.align 4
-_gdt:
-	.quad 0x0000000000000000	/* NULL descriptor */
-	.quad 0x0000000000000000	/* not used */
-	.quad 0xc0c39a000000ffff	/* 0x10 kernel 1GB code at 0xC0000000 */
-	.quad 0xc0c392000000ffff	/* 0x18 kernel 1GB data at 0xC0000000 */
-	.quad 0x00cbfa000000ffff	/* 0x23 user   3GB code at 0x00000000 */
-	.quad 0x00cbf2000000ffff	/* 0x2b user   3GB data at 0x00000000 */
-	.quad 0x0000000000000000	/* not used */
-	.quad 0x0000000000000000	/* not used */
-	.fill 2*NR_TASKS,8,0		/* space for LDT's and TSS's etc */
diff -u --recursive --new-file v1.1.75/linux/arch/i386/boot/tools/build.c linux/arch/i386/boot/tools/build.c
--- v1.1.75/linux/arch/i386/boot/tools/build.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/tools/build.c	Thu Dec 29 19:58:41 1994
@@ -0,0 +1,238 @@
+/*
+ *  linux/tools/build.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * This file builds a disk-image from three different files:
+ *
+ * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ * - setup: 8086 machine code, sets up system parm
+ * - system: 80386 code for actual system
+ *
+ * It does some checking that all files are of the correct type, and
+ * just writes the result to stdout, removing headers and padding to
+ * the right amount. It also writes some system data to stderr.
+ */
+
+/*
+ * Changes by tytso to allow root device specification
+ */
+
+#include <stdio.h>	/* fprintf */
+#include <string.h>
+#include <stdlib.h>	/* contains exit */
+#include <sys/types.h>	/* unistd.h needs this */
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>	/* contains read/write */
+#include <fcntl.h>
+#include <linux/config.h>
+#include <linux/a.out.h>
+
+#define MINIX_HEADER 32
+
+#define N_MAGIC_OFFSET 1024
+static int GCC_HEADER = sizeof(struct exec);
+
+#define SYS_SIZE DEF_SYSSIZE
+
+#define DEFAULT_MAJOR_ROOT 0
+#define DEFAULT_MINOR_ROOT 0
+
+/* max nr of sectors of setup: don't change unless you also change
+ * bootsect etc */
+#define SETUP_SECTS 4
+
+#define STRINGIFY(x) #x
+
+typedef union {
+	long l;
+	short s[2];
+	char b[4];
+} conv;
+
+long intel_long(long l)
+{
+	conv t;
+
+	t.b[0] = l & 0xff; l >>= 8;
+	t.b[1] = l & 0xff; l >>= 8;
+	t.b[2] = l & 0xff; l >>= 8;
+	t.b[3] = l & 0xff; l >>= 8;
+	return t.l;
+}
+
+short intel_short(short l)
+{
+	conv t;
+
+	t.b[0] = l & 0xff; l >>= 8;
+	t.b[1] = l & 0xff; l >>= 8;
+	return t.s[0];
+}
+
+void die(char * str)
+{
+	fprintf(stderr,"%s\n",str);
+	exit(1);
+}
+
+void usage(void)
+{
+	die("Usage: build bootsect setup system [rootdev] [> image]");
+}
+
+int main(int argc, char ** argv)
+{
+	int i,c,id, sz;
+	unsigned long sys_size;
+	char buf[1024];
+	struct exec *ex = (struct exec *)buf;
+	char major_root, minor_root;
+	struct stat sb;
+	unsigned char setup_sectors;
+
+	if ((argc < 4) || (argc > 5))
+		usage();
+	if (argc > 4) {
+		if (!strcmp(argv[4], "CURRENT")) {
+			if (stat("/", &sb)) {
+				perror("/");
+				die("Couldn't stat /");
+			}
+			major_root = major(sb.st_dev);
+			minor_root = minor(sb.st_dev);
+		} else if (strcmp(argv[4], "FLOPPY")) {
+			if (stat(argv[4], &sb)) {
+				perror(argv[4]);
+				die("Couldn't stat root device.");
+			}
+			major_root = major(sb.st_rdev);
+			minor_root = minor(sb.st_rdev);
+		} else {
+			major_root = 0;
+			minor_root = 0;
+		}
+	} else {
+		major_root = DEFAULT_MAJOR_ROOT;
+		minor_root = DEFAULT_MINOR_ROOT;
+	}
+	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
+	for (i=0;i<sizeof buf; i++) buf[i]=0;
+	if ((id=open(argv[1],O_RDONLY,0))<0)
+		die("Unable to open 'boot'");
+	if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
+		die("Unable to read header of 'boot'");
+	if (((long *) buf)[0]!=intel_long(0x04100301))
+		die("Non-Minix header of 'boot'");
+	if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
+		die("Non-Minix header of 'boot'");
+	if (((long *) buf)[3] != 0)
+		die("Illegal data segment in 'boot'");
+	if (((long *) buf)[4] != 0)
+		die("Illegal bss in 'boot'");
+	if (((long *) buf)[5] != 0)
+		die("Non-Minix header of 'boot'");
+	if (((long *) buf)[7] != 0)
+		die("Illegal symbol table in 'boot'");
+	i=read(id,buf,sizeof buf);
+	fprintf(stderr,"Boot sector %d bytes.\n",i);
+	if (i != 512)
+		die("Boot block must be exactly 512 bytes");
+	if ((*(unsigned short *)(buf+510)) != (unsigned short)intel_short(0xAA55))
+		die("Boot block hasn't got boot flag (0xAA55)");
+	buf[508] = (char) minor_root;
+	buf[509] = (char) major_root;	
+	i=write(1,buf,512);
+	if (i!=512)
+		die("Write call failed");
+	close (id);
+	
+	if ((id=open(argv[2],O_RDONLY,0))<0)
+		die("Unable to open 'setup'");
+	if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
+		die("Unable to read header of 'setup'");
+	if (((long *) buf)[0]!=intel_long(0x04100301))
+		die("Non-Minix header of 'setup'");
+	if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
+		die("Non-Minix header of 'setup'");
+	if (((long *) buf)[3] != 0)
+		die("Illegal data segment in 'setup'");
+	if (((long *) buf)[4] != 0)
+		die("Illegal bss in 'setup'");
+	if (((long *) buf)[5] != 0)
+		die("Non-Minix header of 'setup'");
+	if (((long *) buf)[7] != 0)
+		die("Illegal symbol table in 'setup'");
+	for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
+		if (write(1,buf,c)!=c)
+			die("Write call failed");
+	if (c != 0)
+		die("read-error on 'setup'");
+	close (id);
+	setup_sectors = (unsigned char)((i + 511) / 512);
+	/* for compatibility with LILO */
+	if (setup_sectors < SETUP_SECTS)
+		setup_sectors = SETUP_SECTS;
+	fprintf(stderr,"Setup is %d bytes.\n",i);
+	for (c=0 ; c<sizeof(buf) ; c++)
+		buf[c] = '\0';
+	while (i < setup_sectors * 512) {
+		c = setup_sectors * 512 - i;
+		if (c > sizeof(buf))
+			c = sizeof(buf);
+		if (write(1,buf,c) != c)
+			die("Write call failed");
+		i += c;
+	}
+	
+	if ((id=open(argv[3],O_RDONLY,0))<0)
+		die("Unable to open 'system'");
+	if (read(id,buf,GCC_HEADER) != GCC_HEADER)
+		die("Unable to read header of 'system'");
+	if (N_MAGIC(*ex) == ZMAGIC) {
+		GCC_HEADER = N_MAGIC_OFFSET;
+		lseek(id, GCC_HEADER, SEEK_SET);
+	} else if (N_MAGIC(*ex) != QMAGIC)
+		die("Non-GCC header of 'system'");
+	fprintf(stderr,"System is %d kB (%d kB code, %d kB data and %d kB bss)\n",
+		(ex->a_text+ex->a_data+ex->a_bss)/1024,
+		ex->a_text /1024,
+		ex->a_data /1024,
+		ex->a_bss  /1024);
+	sz = N_SYMOFF(*ex) - GCC_HEADER + 4;
+	sys_size = (sz + 15) / 16;
+	if (sys_size > SYS_SIZE)
+		die("System is too big");
+	while (sz > 0) {
+		int l, n;
+
+		l = sz;
+		if (l > sizeof(buf))
+			l = sizeof(buf);
+		if ((n=read(id, buf, l)) != l) {
+			if (n == -1) 
+				perror(argv[1]);
+			else
+				fprintf(stderr, "Unexpected EOF\n");
+			die("Can't read 'system'");
+		}
+		if (write(1, buf, l) != l)
+			die("Write failed");
+		sz -= l;
+	}
+	close(id);
+	if (lseek(1, 497, 0) == 497) {
+		if (write(1, &setup_sectors, 1) != 1)
+			die("Write of setup sectors failed");
+	}
+	if (lseek(1,500,0) == 500) {
+		buf[0] = (sys_size & 0xff);
+		buf[1] = ((sys_size >> 8) & 0xff);
+		if (write(1, buf, 2) != 2)
+			die("Write failed");
+	}
+	return(0);
+}
diff -u --recursive --new-file v1.1.75/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.1.75/linux/arch/i386/config.in	Tue Dec 27 09:56:45 1994
+++ linux/arch/i386/config.in	Sun Jan  1 19:49:19 1995
@@ -7,7 +7,19 @@
 
 bool 'Kernel math emulation' CONFIG_MATH_EMULATION n
 bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
-bool 'Normal harddisk support' CONFIG_BLK_DEV_HD y
+bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 y
+if [ "$CONFIG_ST506" = "y" ]; then
+  bool '   Use old (reliable) disk-only driver for primary i/f' CONFIG_BLK_DEV_HD y
+  if [ "$CONFIG_BLK_DEV_HD" = "y" ]; then
+    bool '   Include new IDE driver for secondary i/f support' CONFIG_BLK_DEV_IDE n
+  else
+    bool '   Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE y
+  fi
+  if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
+    bool '   Include support for IDE CDROM (ATAPI)' CONFIG_BLK_DEV_IDECD n
+  fi
+fi
+
 bool 'XT harddisk support' CONFIG_BLK_DEV_XD n
 bool 'Networking support' CONFIG_NET y
 bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
@@ -206,10 +218,6 @@
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
 bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
-bool 'VESA Power Saving Protocol Support' CONFIG_VESA_PSPM n
-if [ "$CONFIG_VESA_PSPM" = "y" ]; then
-bool 'VESA PSPM Force Off' CONFIG_PSPM_FORCE_OFF n
-fi
 
 
 bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
diff -u --recursive --new-file v1.1.75/linux/arch/i386/head.S linux/arch/i386/head.S
--- v1.1.75/linux/arch/i386/head.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/head.S	Mon Jan  2 15:19:59 1995
@@ -0,0 +1,362 @@
+/*
+ *  linux/arch/i386/head.S
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ *  head.S contains the 32-bit startup code.
+ */
+
+.text
+.globl _idt,_gdt,
+.globl _swapper_pg_dir,_pg0
+.globl _empty_bad_page
+.globl _empty_bad_page_table
+.globl _empty_zero_page
+.globl _floppy_track_buffer
+
+#define __ASSEMBLY__
+#include <linux/tasks.h>
+#include <linux/fd.h>
+#include <asm/segment.h>
+
+#define CL_MAGIC_ADDR	0x90020
+#define CL_MAGIC	0xA33F
+#define CL_BASE_ADDR	0x90000
+#define CL_OFFSET	0x90022
+
+/*
+ * swapper_pg_dir is the main page directory, address 0x00001000 (or at
+ * address 0x00101000 for a compressed boot).
+ */
+startup_32:
+	cld
+	movl $(KERNEL_DS),%eax
+	mov %ax,%ds
+	mov %ax,%es
+	mov %ax,%fs
+	mov %ax,%gs
+	lss stack_start,%esp
+/*
+ * Clear BSS first so that there are no surprises...
+ */
+	xorl %eax,%eax
+	movl $__edata,%edi
+	movl $__end,%ecx
+	subl %edi,%ecx
+	cld
+	rep
+	stosb
+/*
+ * start system 32-bit setup. We need to re-do some of the things done
+ * in 16-bit mode for the "real" operations.
+ */
+	call setup_idt
+	xorl %eax,%eax
+1:	incl %eax		# check that A20 really IS enabled
+	movl %eax,0x000000	# loop forever if it isn't
+	cmpl %eax,0x100000
+	je 1b
+/*
+ * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
+ * confuse the debugger if this code is traced.
+ * XXX - best to initialize before switching to protected mode.
+ */
+	pushl $0
+	popfl
+/*
+ * Copy bootup parameters out of the way. First 2kB of
+ * _empty_zero_page is for boot parameters, second 2kB
+ * is for the command line.
+ */
+	movl $0x90000,%esi
+	movl $_empty_zero_page,%edi
+	movl $512,%ecx
+	cld
+	rep
+	movsl
+	xorl %eax,%eax
+	movl $512,%ecx
+	rep
+	stosl
+	cmpw $(CL_MAGIC),CL_MAGIC_ADDR
+	jne 1f
+	movl $_empty_zero_page+2048,%edi
+	movzwl CL_OFFSET,%esi
+	addl $(CL_BASE_ADDR),%esi
+	movl $2048,%ecx
+	rep
+	movsb
+1:
+/* check if it is 486 or 386. */
+/*
+ * XXX - this does a lot of unnecessary setup.  Alignment checks don't
+ * apply at our cpl of 0 and the stack ought to be aligned already, and
+ * we don't need to preserve eflags.
+ */
+	movl $3,_x86
+	pushfl			# push EFLAGS
+	popl %eax		# get EFLAGS
+	movl %eax,%ecx		# save original EFLAGS
+	xorl $0x40000,%eax	# flip AC bit in EFLAGS
+	pushl %eax		# copy to EFLAGS
+	popfl			# set EFLAGS
+	pushfl			# get new EFLAGS
+	popl %eax		# put it in eax
+	xorl %ecx,%eax		# change in flags
+	andl $0x40000,%eax	# check if AC bit changed
+	je is386
+	movl $4,_x86
+	movl %ecx,%eax
+	xorl $0x200000,%eax	# check ID flag
+	pushl %eax
+	popfl			# if we are on a straight 486DX, SX, or
+	pushfl			# 487SX we can't change it
+	popl %eax
+	xorl %ecx,%eax
+	andl $0x200000,%eax
+	je is486
+isnew:	pushl %ecx		# restore original EFLAGS
+	popfl
+	/* get processor type */
+	movl $1, %eax		# Use the CPUID instruction to 
+	.byte 0x0f, 0xa2	# check the processor type
+	movb %al, %cl		# save reg for future use
+	andb $0x0f,%ah		# mask processor family
+	movb %ah, _x86
+	andb $0xf0, %eax	# mask model
+	shrb $4, %al
+	movb %al, _x86_model
+	andb $0x0f, %cl		# mask mask revision
+	movb %cl, _x86_mask
+	movl %edx, _x86_capability
+	/* get vendor info */
+	xorl %eax, %eax			# call CPUID with 0 -> return vendor ID
+	.byte 0x0f, 0xa2		# CPUID
+	movl %ebx, _x86_vendor_id	# lo 4 chars
+	movl %edx, _x86_vendor_id+4	# next 4 chars
+	movl %ecx, _x86_vendor_id+8	# last 4 chars
+
+	movl %cr0,%eax		# 486+
+	andl $0x80000011,%eax	# Save PG,PE,ET
+	orl $0x50022,%eax	# set AM, WP, NE and MP
+	jmp 2f
+is486:	pushl %ecx		# restore original EFLAGS
+	popfl
+	movl %cr0,%eax		# 486
+	andl $0x80000011,%eax	# Save PG,PE,ET
+	orl $0x50022,%eax	# set AM, WP, NE and MP
+	jmp 2f
+is386:	pushl %ecx		# restore original EFLAGS
+	popfl
+	movl %cr0,%eax		# 386
+	andl $0x80000011,%eax	# Save PG,PE,ET
+	orl $2,%eax		# set MP
+2:	movl %eax,%cr0
+	call check_x87
+	call setup_paging
+	lgdt gdt_descr
+	lidt idt_descr
+	ljmp $(KERNEL_CS),$1f
+1:	movl $(KERNEL_DS),%eax	# reload all the segment registers
+	mov %ax,%ds		# after changing gdt.
+	mov %ax,%es
+	mov %ax,%fs
+	mov %ax,%gs
+	lss stack_start,%esp
+	xorl %eax,%eax
+	lldt %ax
+	pushl %eax		# These are the parameters to main :-)
+	pushl %eax
+	pushl %eax
+	cld			# gcc2 wants the direction flag cleared at all times
+	call _start_kernel
+L6:
+	jmp L6			# main should never return here, but
+				# just in case, we know what happens.
+
+/*
+ * We depend on ET to be correct. This checks for 287/387.
+ */
+check_x87:
+	movb $0,_hard_math
+	clts
+	fninit
+	fstsw %ax
+	cmpb $0,%al
+	je 1f
+	movl %cr0,%eax		/* no coprocessor: have to set bits */
+	xorl $4,%eax		/* set EM */
+	movl %eax,%cr0
+	ret
+.align 2
+1:	movb $1,_hard_math
+	.byte 0xDB,0xE4		/* fsetpm for 287, ignored by 387 */
+	ret
+
+/*
+ *  setup_idt
+ *
+ *  sets up a idt with 256 entries pointing to
+ *  ignore_int, interrupt gates. It doesn't actually load
+ *  idt - that can be done only after paging has been enabled
+ *  and the kernel moved to 0xC0000000. Interrupts
+ *  are enabled elsewhere, when we can be relatively
+ *  sure everything is ok.
+ */
+setup_idt:
+	lea ignore_int,%edx
+	movl $(KERNEL_CS << 16),%eax
+	movw %dx,%ax		/* selector = 0x0010 = cs */
+	movw $0x8E00,%dx	/* interrupt gate - dpl=0, present */
+
+	lea _idt,%edi
+	mov $256,%ecx
+rp_sidt:
+	movl %eax,(%edi)
+	movl %edx,4(%edi)
+	addl $8,%edi
+	dec %ecx
+	jne rp_sidt
+	ret
+
+
+/*
+ * Setup_paging
+ *
+ * This routine sets up paging by setting the page bit
+ * in cr0. The page tables are set up, identity-mapping
+ * the first 4MB.  The rest are initialized later.
+ *
+ * (ref: added support for up to 32mb, 17Apr92)  -- Rik Faith
+ * (ref: update, 25Sept92)  -- croutons@crunchy.uucp 
+ * (ref: 92.10.11 - Linus Torvalds. Corrected 16M limit - no upper memory limit)
+ */
+.align 2
+setup_paging:
+	movl $1024*2,%ecx		/* 2 pages - swapper_pg_dir+1 page table */
+	xorl %eax,%eax
+	movl $_swapper_pg_dir,%edi	/* swapper_pg_dir is at 0x1000 */
+	cld;rep;stosl
+/* Identity-map the kernel in low 4MB memory for ease of transition */
+	movl $_pg0+7,_swapper_pg_dir		/* set present bit/user r/w */
+/* But the real place is at 0xC0000000 */
+	movl $_pg0+7,_swapper_pg_dir+3072	/* set present bit/user r/w */
+	movl $_pg0+4092,%edi
+	movl $0x03ff007,%eax		/*  4Mb - 4096 + 7 (r/w user,p) */
+	std
+1:	stosl			/* fill the page backwards - more efficient :-) */
+	subl $0x1000,%eax
+	jge 1b
+	cld
+	movl $_swapper_pg_dir,%eax
+	movl %eax,%cr3			/* cr3 - page directory start */
+	movl %cr0,%eax
+	orl $0x80000000,%eax
+	movl %eax,%cr0		/* set paging (PG) bit */
+	ret			/* this also flushes the prefetch-queue */
+
+/*
+ * page 0 is made non-existent, so that kernel NULL pointer references get
+ * caught. Thus the swapper page directory has been moved to 0x1000
+ *
+ * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte,
+ * with the introduction of the compressed boot code.  Theoretically,
+ * the original design of overlaying the startup code with the swapper
+ * page directory is still possible --- it would reduce the size of the kernel
+ * by 2-3k.  This would be a good thing to do at some point.....
+ */
+.org 0x1000
+_swapper_pg_dir:
+/*
+ * The page tables are initialized to only 4MB here - the final page
+ * tables are set up later depending on memory size.
+ */
+.org 0x2000
+_pg0:
+
+.org 0x3000
+_empty_bad_page:
+
+.org 0x4000
+_empty_bad_page_table:
+
+.org 0x5000
+_empty_zero_page:
+
+.org 0x6000
+/*
+ * floppy_track_buffer is used to buffer one track of floppy data: it
+ * has to be separate from the tmp_floppy area, as otherwise a single-
+ * sector read/write can mess it up. It can contain one full cylinder (sic) of
+ * data (36*2*512 bytes).
+ */
+_floppy_track_buffer:
+	.fill 512*2*MAX_BUFFER_SECTORS,1,0
+	
+stack_start:
+	.long _init_user_stack+4096
+	.long KERNEL_DS
+
+/* This is the default interrupt "handler" :-) */
+int_msg:
+	.asciz "Unknown interrupt\n"
+.align 2
+ignore_int:
+	cld
+	pushl %eax
+	pushl %ecx
+	pushl %edx
+	push %ds
+	push %es
+	push %fs
+	movl $(KERNEL_DS),%eax
+	mov %ax,%ds
+	mov %ax,%es
+	mov %ax,%fs
+	pushl $int_msg
+	call _printk
+	popl %eax
+	pop %fs
+	pop %es
+	pop %ds
+	popl %edx
+	popl %ecx
+	popl %eax
+	iret
+
+/*
+ * The interrupt descriptor table has room for 256 idt's
+ */
+.align 4
+.word 0
+idt_descr:
+	.word 256*8-1		# idt contains 256 entries
+	.long 0xc0000000+_idt
+
+.align 4
+_idt:
+	.fill 256,8,0		# idt is uninitialized
+
+.align 4
+.word 0
+gdt_descr:
+	.word (8+2*NR_TASKS)*8-1
+	.long 0xc0000000+_gdt
+
+/*
+ * This gdt setup gives the kernel a 1GB address space at virtual
+ * address 0xC0000000 - space enough for expansion, I hope.
+ */
+.align 4
+_gdt:
+	.quad 0x0000000000000000	/* NULL descriptor */
+	.quad 0x0000000000000000	/* not used */
+	.quad 0xc0c39a000000ffff	/* 0x10 kernel 1GB code at 0xC0000000 */
+	.quad 0xc0c392000000ffff	/* 0x18 kernel 1GB data at 0xC0000000 */
+	.quad 0x00cbfa000000ffff	/* 0x23 user   3GB code at 0x00000000 */
+	.quad 0x00cbf2000000ffff	/* 0x2b user   3GB data at 0x00000000 */
+	.quad 0x0000000000000000	/* not used */
+	.quad 0x0000000000000000	/* not used */
+	.fill 2*NR_TASKS,8,0		/* space for LDT's and TSS's etc */
diff -u --recursive --new-file v1.1.75/linux/arch/i386/traps.c linux/arch/i386/traps.c
--- v1.1.75/linux/arch/i386/traps.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/traps.c	Mon Jan  2 15:20:20 1995
@@ -0,0 +1,310 @@
+/*
+ *  linux/arch/i386/traps.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
+ * to mainly kill the offending process (probably by giving it a signal,
+ * but possibly by killing it outright if necessary).
+ */
+#include <linux/head.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/config.h>
+#include <linux/timer.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+
+asmlinkage int system_call(void);
+asmlinkage void lcall7(void);
+struct desc_struct default_ldt;
+
+static inline void console_verbose(void)
+{
+	extern int console_loglevel;
+	console_loglevel = 15;
+}
+
+#define DO_ERROR(trapnr, signr, str, name, tsk) \
+asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+{ \
+	tsk->tss.error_code = error_code; \
+	tsk->tss.trap_no = trapnr; \
+	if (signr == SIGTRAP && current->flags & PF_PTRACED) \
+		current->blocked &= ~(1 << (SIGTRAP-1)); \
+	send_sig(signr, tsk, 1); \
+	die_if_kernel(str,regs,error_code); \
+}
+
+#define get_seg_byte(seg,addr) ({ \
+register unsigned char __res; \
+__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
+	:"=a" (__res):"0" (seg),"m" (*(addr))); \
+__res;})
+
+#define get_seg_long(seg,addr) ({ \
+register unsigned long __res; \
+__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \
+	:"=a" (__res):"0" (seg),"m" (*(addr))); \
+__res;})
+
+#define _fs() ({ \
+register unsigned short __res; \
+__asm__("mov %%fs,%%ax":"=a" (__res):); \
+__res;})
+
+void page_exception(void);
+
+asmlinkage void divide_error(void);
+asmlinkage void debug(void);
+asmlinkage void nmi(void);
+asmlinkage void int3(void);
+asmlinkage void overflow(void);
+asmlinkage void bounds(void);
+asmlinkage void invalid_op(void);
+asmlinkage void device_not_available(void);
+asmlinkage void double_fault(void);
+asmlinkage void coprocessor_segment_overrun(void);
+asmlinkage void invalid_TSS(void);
+asmlinkage void segment_not_present(void);
+asmlinkage void stack_segment(void);
+asmlinkage void general_protection(void);
+asmlinkage void page_fault(void);
+asmlinkage void coprocessor_error(void);
+asmlinkage void reserved(void);
+asmlinkage void alignment_check(void);
+
+/*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err)
+{
+	int i;
+	unsigned long esp;
+	unsigned short ss;
+
+	esp = (unsigned long) &regs->esp;
+	ss = KERNEL_DS;
+	if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3)
+		return;
+	if (regs->cs & 3) {
+		esp = regs->esp;
+		ss = regs->ss;
+	}
+	console_verbose();
+	printk("%s: %04lx\n", str, err & 0xffff);
+	printk("EIP:    %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
+	printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
+		regs->eax, regs->ebx, regs->ecx, regs->edx);
+	printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
+		regs->esi, regs->edi, regs->ebp, esp);
+	printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   ss: %04x\n",
+		regs->ds, regs->es, regs->fs, regs->gs, ss);
+	store_TR(i);
+	if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
+		printk("Corrupted stack page\n");
+	printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ",
+		current->comm, current->pid, 0xffff & i, current->kernel_stack_page);
+	for(i=0;i<5;i++)
+		printk("%08lx ", get_seg_long(ss,(i+(unsigned long *)esp)));
+	printk("\nCode: ");
+	for(i=0;i<20;i++)
+		printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
+	printk("\n");
+	do_exit(SIGSEGV);
+}
+
+DO_ERROR( 0, SIGFPE,  "divide error", divide_error, current)
+DO_ERROR( 3, SIGTRAP, "int3", int3, current)
+DO_ERROR( 4, SIGSEGV, "overflow", overflow, current)
+DO_ERROR( 5, SIGSEGV, "bounds", bounds, current)
+DO_ERROR( 6, SIGILL,  "invalid operand", invalid_op, current)
+DO_ERROR( 7, SIGSEGV, "device not available", device_not_available, current)
+DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current)
+DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math)
+DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
+DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present, current)
+DO_ERROR(12, SIGBUS,  "stack segment", stack_segment, current)
+DO_ERROR(15, SIGSEGV, "reserved", reserved, current)
+DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
+
+asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
+{
+	int signr = SIGSEGV;
+
+	if (regs->eflags & VM_MASK) {
+		handle_vm86_fault((struct vm86_regs *) regs, error_code);
+		return;
+	}
+	die_if_kernel("general protection",regs,error_code);
+	switch (get_seg_byte(regs->cs, (char *)regs->eip)) {
+		case 0xCD: /* INT */
+		case 0xF4: /* HLT */
+		case 0xFA: /* CLI */
+		case 0xFB: /* STI */
+			signr = SIGILL;
+	}
+	current->tss.error_code = error_code;
+	current->tss.trap_no = 13;
+	send_sig(signr, current, 1);	
+}
+
+asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
+{
+	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
+	printk("You probably have a hardware problem with your RAM chips\n");
+}
+
+asmlinkage void do_debug(struct pt_regs * regs, long error_code)
+{
+	if (regs->eflags & VM_MASK) {
+		handle_vm86_debug((struct vm86_regs *) regs, error_code);
+		return;
+	}
+	if (current->flags & PF_PTRACED)
+		current->blocked &= ~(1 << (SIGTRAP-1));
+	send_sig(SIGTRAP, current, 1);
+	current->tss.trap_no = 1;
+	current->tss.error_code = error_code;
+	if ((regs->cs & 3) == 0) {
+		/* If this is a kernel mode trap, then reset db7 and allow us to continue */
+		__asm__("movl %0,%%db7"
+			: /* no output */
+			: "r" (0));
+		return;
+	}
+	die_if_kernel("debug",regs,error_code);
+}
+
+/*
+ * Allow the process which triggered the interrupt to recover the error
+ * condition.
+ *  - the status word is saved in the cs selector.
+ *  - the tag word is saved in the operand selector.
+ *  - the status word is then cleared and the tags all set to Empty.
+ *
+ * This will give sufficient information for complete recovery provided that
+ * the affected process knows or can deduce the code and data segments
+ * which were in force when the exception condition arose.
+ *
+ * Note that we play around with the 'TS' bit to hopefully get
+ * the correct behaviour even in the presence of the asynchronous
+ * IRQ13 behaviour
+ */
+void math_error(void)
+{
+	struct i387_hard_struct * env;
+
+	clts();
+	if (!last_task_used_math) {
+		__asm__("fnclex");
+		return;
+	}
+	env = &last_task_used_math->tss.i387.hard;
+	send_sig(SIGFPE, last_task_used_math, 1);
+	last_task_used_math->tss.trap_no = 16;
+	last_task_used_math->tss.error_code = 0;
+	__asm__ __volatile__("fnsave %0":"=m" (*env));
+	last_task_used_math = NULL;
+	stts();
+	env->fcs = (env->swd & 0x0000ffff) | (env->fcs & 0xffff0000);
+	env->fos = env->twd;
+	env->swd &= 0xffff3800;
+	env->twd = 0xffffffff;
+}
+
+asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
+{
+	ignore_irq13 = 1;
+	math_error();
+}
+
+/*
+ *  'math_state_restore()' saves the current math information in the
+ * old math state array, and gets the new ones from the current task
+ *
+ * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+ * Don't touch unless you *really* know how it works.
+ */
+asmlinkage void math_state_restore(void)
+{
+	__asm__ __volatile__("clts");
+	if (last_task_used_math == current)
+		return;
+	timer_table[COPRO_TIMER].expires = jiffies+50;
+	timer_active |= 1<<COPRO_TIMER;	
+	if (last_task_used_math)
+		__asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
+	else
+		__asm__("fnclex");
+	last_task_used_math = current;
+	if (current->used_math) {
+		__asm__("frstor %0": :"m" (current->tss.i387));
+	} else {
+		__asm__("fninit");
+		current->used_math=1;
+	}
+	timer_active &= ~(1<<COPRO_TIMER);
+}
+
+#ifndef CONFIG_MATH_EMULATION
+
+asmlinkage void math_emulate(long arg)
+{
+  printk("math-emulation not enabled and no coprocessor found.\n");
+  printk("killing %s.\n",current->comm);
+  send_sig(SIGFPE,current,1);
+  schedule();
+}
+
+#endif /* CONFIG_MATH_EMULATION */
+
+void trap_init(void)
+{
+	int i;
+	struct desc_struct * p;
+
+	set_call_gate(&default_ldt,lcall7);
+	set_trap_gate(0,&divide_error);
+	set_trap_gate(1,&debug);
+	set_trap_gate(2,&nmi);
+	set_system_gate(3,&int3);	/* int3-5 can be called from all */
+	set_system_gate(4,&overflow);
+	set_system_gate(5,&bounds);
+	set_trap_gate(6,&invalid_op);
+	set_trap_gate(7,&device_not_available);
+	set_trap_gate(8,&double_fault);
+	set_trap_gate(9,&coprocessor_segment_overrun);
+	set_trap_gate(10,&invalid_TSS);
+	set_trap_gate(11,&segment_not_present);
+	set_trap_gate(12,&stack_segment);
+	set_trap_gate(13,&general_protection);
+	set_trap_gate(14,&page_fault);
+	set_trap_gate(15,&reserved);
+	set_trap_gate(16,&coprocessor_error);
+	set_trap_gate(17,&alignment_check);
+	for (i=18;i<48;i++)
+		set_trap_gate(i,&reserved);
+	set_system_gate(0x80,&system_call);
+/* set up GDT task & ldt entries */
+	p = gdt+FIRST_TSS_ENTRY;
+	set_tss_desc(p, &init_task.tss);
+	p++;
+	set_ldt_desc(p, &default_ldt, 1);
+	p++;
+	for(i=1 ; i<NR_TASKS ; i++) {
+		p->a=p->b=0;
+		p++;
+		p->a=p->b=0;
+		p++;
+	}
+/* Clear NT, so that we won't have troubles with that later on */
+	__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
+	load_TR(0);
+	load_ldt(0);
+}
diff -u --recursive --new-file v1.1.75/linux/drivers/block/MAKEDEV.ide1 linux/drivers/block/MAKEDEV.ide1
--- v1.1.75/linux/drivers/block/MAKEDEV.ide1	Thu Jan  1 02:00:00 1970
+++ linux/drivers/block/MAKEDEV.ide1	Sun Jan  1 16:28:19 1995
@@ -0,0 +1,24 @@
+#!/bin/sh
+makedev () {
+        rm -f /dev/$1
+        echo mknod /dev/$1 $2 $3 $4 &&
+             mknod /dev/$1 $2 $3 $4 &&
+        chown $5 /dev/$1 &&
+        chmod $6 /dev/$1
+}
+
+# Create /dev/hdc*
+makedev hdc b 22 0 root:$disk 660
+for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+do
+	makedev hdc$part b 22 `expr 0 + $part` root:$disk 660
+done
+echo " "
+
+# Create /dev/hdd*
+makedev hdd b 22 64 root:$disk 660
+for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+do
+	makedev hdd$part b 22 `expr 64 + $part` root:$disk 660
+done
+
diff -u --recursive --new-file v1.1.75/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v1.1.75/linux/drivers/block/Makefile	Fri Jul  8 11:36:03 1994
+++ linux/drivers/block/Makefile	Sun Jan  1 16:28:19 1995
@@ -59,6 +59,11 @@
 SRCS := $(SRCS) hd.c
 endif
 
+ifdef CONFIG_BLK_DEV_IDE
+OBJS := ide.o $(OBJS)
+SRCS := ide.c $(SRCS)
+endif
+
 ifdef CONFIG_BLK_DEV_XD
 OBJS := $(OBJS) xd.o
 SRCS := $(SRCS) xd.c
diff -u --recursive --new-file v1.1.75/linux/drivers/block/README.ide linux/drivers/block/README.ide
--- v1.1.75/linux/drivers/block/README.ide	Thu Jan  1 02:00:00 1970
+++ linux/drivers/block/README.ide	Sun Jan  1 19:49:19 1995
@@ -0,0 +1,181 @@
+README.ide -- Information regarding ide.c and ide-cd.c
+================================================================================
+Supported by:  mlord@bnr.ca           -- disks, interfaces, probing
+               snyder@fnald0.fnal.gov -- cdroms, ATAPI, audio
+
+(see description later on below for handling BIG IDE drives with >1024 cyls).
+
+Major features of ide.c & ide-cd.c:
+
+	- support for up to two IDE interfaces on one or two IRQs
+	- support for any mix of up to four disk and/or cdrom drives
+	- support for reading IDE ATAPI cdrom drives (NEC, MITSUMI, VERSA)
+	- support for audio functions on FX400,NEC-260 cdrom drives (others?)
+	- auto-detection of interfaces, drives, IRQs, and disk geometries
+	- support for BIOSs which report "more than 16 heads" on disk drives
+	- uses LBA (slightly faster) on disk drives which support it
+	- support for lots of fancy (E)IDE drive functions with hdparm utility
+	- optional (compile time) support for 32-bit VLB data transfers
+	- support for IDE multiple (block) mode (same as hd.c)
+	- support for interrupt unmasking during I/O (better than hd.c)
+	- auto detection/use of multiple (block) mode settings from BIOS
+	- improved handshaking and error detection/recovery
+	- can co-exist with hd.c to control only the secondary interface
+
+Under construction:
+
+	- support for interface speed selection on jumperless interfaces
+	- improved detection of non-standard IDE ATAPI cdrom drives
+
+To access devices on the second interface, device entries must first be
+created in /dev for them.  To create such entries, simply run the included
+shell script:   MAKEDEV.ide1
+
+ide.c automatically probes for the primary and secondary interfaces,
+for the drives/geometries attached to those interfaces, and for the
+IRQ numbers being used by the interfaces (normally IRQ14 & IRQ15).
+
+The primary and secondary interfaces may share a single IRQ if necessary,
+at a slight performance penalty, whether on separate cards or a single VLB card.
+
+Drives are normally found by auto-probing and/or examining the CMOS/BIOS data.
+For really weird situations, the apparent (fdisk) geometry can also be specified
+on the kernel "command line" using LILO.  The format of such lines is:   
+
+	hdx=cyls,heads,sects,wpcom,irq
+or	hdx=cdrom
+
+where hdx can be any of {hda,hdb,hdc,hdd}, or simply hd, for the "next" drive
+in sequence.  Only the first three parameters are required (cyls,heads,sects),
+and wpcom is ignored for IDE drives.
+
+	Example:  hdc=1050,32,64 hdd=cdrom
+
+If an irq number is given, it will apply to both drives on the same interface,
+either {hda,hdb} or {hdc,hdd}.  The results of successful auto-probing may
+override the physical geometry/irq specified, though the "original" geometry
+is retained as the "logical" geometry for partitioning purposes (fdisk).
+
+Courtesy of Scott Snyder, the driver now supports ATAPI cdrom drives
+such as the NEC-260 and the new MITSUMI triple/quad speed drives.
+Such drives will be identified at boot time, as hda,hdb,hdc or hdd,
+just like a harddisk.
+
+If for some reason your cdrom drive is *not* found at boot time, you can force
+the probe to look harder by supplying a kernel command line parameter
+via LILO, such as:  hdc=cdrom
+
+For example, a GW2000 system might have a harddrive on the primary
+interface (/dev/hda) and an IDE cdrom drive on the secondary interface
+(/dev/hdc).  To mount a CD in the cdrom drive, one would use something like:
+
+	ln -sf /dev/hdc /dev/cdrom
+	mkdir /cd
+	mount /dev/cdrom /cd -t iso9660 -o ro,block=2048
+
+Please pass on any feedback on the cdrom stuff to the author & maintainer,
+Scott Snyder (snyder@fnald0.fnal.gov).
+
+Note that present, the kernel is unable to execute demand-paged binaries
+directly off of the cdrom (due to the different block size).
+
+The hdparm.c program for controlling various IDE features is now packaged
+separately.  Look for it on popular linux FTP sites.
+
+mlord@bnr.ca
+snyder@fnald0.fnal.gov
+================================================================================
+
+How To Use *Big* IDE drives with Linux/DOS
+------------------------------------------
+All IDE drives larger than 504MB ("528Meg") use a "physical" geometry which
+has more than 1024 cylinders.  This presents two problems to most systems:
+
+	1. The INT13 interface to the BIOS only allows 10-bits for cylinder
+	addresses, giving a limit of 1024cyls for programs which use it.
+
+	2. The physical geometry fields of the disk partition table only
+	allows 10-bits for cylinder addresses, giving a similar limit of 1024
+	cyls for operating systems that do not use the "sector count" fields
+	instead of the physical Cyl/Head/Sect (CHS) geometry fields.
+
+Neither of these limitations affects Linux itself, as it (1) does not use the
+BIOS for disk access, and it (2) is clever enough to use the "sector count"
+fields of the partition table instead of the physical CHS geometry fields.
+
+	a) Most folks use LILO to load linux.  LILO uses the INT13 interface
+	to the BIOS to load the kernel at boot time.  Therefore, LILO can only
+	load linux if the files it needs (usually just the kernel images) are
+	located below the magic 1024 cylinder "boundary".
+
+	b) Many folks also like to have bootable DOS partitions on their
+	drive(s).  DOS also uses the INT13 interface to the BIOS, not only
+	for booting, but also for operation after booting.  Therefore, DOS
+	can normally only access partitions which are contained entirely below
+	the magic 1024 cylinder "boundary".
+
+There are at least seven commonly used schemes for kludging DOS to work
+around this "limitation".  In the long term, the problem is being solved
+by introduction of an alternative BIOS interface that does not have the
+same limitations as the INT13 interface.  New versions of DOS are expected
+to detect and use this interface in systems whose BIOS provides it.
+
+But in the present day, alternative solutions are necessary.
+
+The most popular solution in newer systems is to have the BIOS shift bits
+between the cylinder and head number fields.  This is activated by entering
+a translated logical geometry into the BIOS/CMOS setup for the drive.
+Thus, if the drive has a geometry of 2100/16/63 (CHS), then the BIOS could
+present a "logical" geometry of 525/64/63 by "shifting" two bits from the
+cylinder number into the head number field for purposes of the partition table, CMOS setup, and INT13 interfaces.  Linux kernels 1.1.39 and higher detect and
+"handle" this translation automatically, making this a rather painless solution
+for the 1024 cyls problem.  If for some reason Linux gets confused (unlikely),
+then use the kernel command line parameters to pass the *logical* geometry,
+as in:  hda=525,64,63
+
+If the BIOS does not support this form of drive translation, then several
+options remain, listed below in order of increasing popularity:
+
+	- rewrite LILO to bypass the BIOS and talk directly to the drive
+	- boot from a floppy disk instead of the hard drive (takes 10 seconds)
+	- use a partition below the 1024 cyl boundary to hold the linux
+	boot files (kernel images and /boot directory), and place the rest
+	of linux anywhere else on the drive.  These files can reside in a DOS
+	partition, or in a tailor-made linux boot partition.
+
+If you cannot use drive translation, *and* your BIOS also restricts you to
+entering no more than 1024 cylinders in the geometry field in the CMOS setup,
+then you'll have to set it to 1024.  As of v3.5 of this driver, Linux will
+automatically determine the *real* number of cylinders for fdisk to use,
+allowing easy access to the full disk capacity.
+
+Regardless of what you do, all DOS partitions *must* be contained entirely
+within the first 1024 logical cylinders.  For a 1Gig WD disk drive, here's
+a good "half and half" partitioning scheme to start with:
+
+	geometry = 2100/16/63
+	/dev/hda1 from cyl    1 to  992		dos
+	/dev/hda2 from cyl  993 to 1023		swap
+	/dev/hda3 from cyl 1024 to 2100		linux
+
+After installing slackware (or whatever), boot from floppy and mount the dos
+partition under /dos, and then move the /boot directory to /dos/boot,
+and move the /vmlinuz kernel file into /dos/boot.  Then create a symlink
+to put it back where the filesystem standard wants it:  ln -s /dos/boot /boot
+Finally, edit /etc/lilo.conf and change the reference to /vmlinuz to point
+at /boot/vmlinuz and then re-run lilo.  Have Fun.  :)
+
+If you "don't do DOS", then partition as you please, but remember to create
+a small partition to hold the /boot directory (and vmlinuz) as described above
+such that it all lies within the first 1024 cylinders.
+
+Western Digital now ships a "DiskManager 6.03" diskette with all of their big
+hard drives.  Burn it!  That idiotic piece of garbage isn't even universally
+compatible with DOS, let alone other operating systems like Linux.  Eventually
+some kind person will kludge Linux to work with it, but at present the two
+are completely incompatible.  If you have this version of DiskManager on your
+hard disk already, it can be exterminated at the expense of all data on the
+drive (back it up elsewhere), by using the "DM" command from the diskette
+as follows:   DM /Y-
+
+mlord@bnr.ca
diff -u --recursive --new-file v1.1.75/linux/drivers/block/blk.h linux/drivers/block/blk.h
--- v1.1.75/linux/drivers/block/blk.h	Thu Dec  1 19:15:03 1994
+++ linux/drivers/block/blk.h	Sun Jan  1 16:28:19 1995
@@ -30,16 +30,25 @@
  * These will have to be changed to be aware of different buffer
  * sizes etc.. It actually needs a major cleanup.
  */
+#ifdef IDE_DRIVER
+#define SECTOR_MASK ((BLOCK_SIZE >> 9) - 1)
+#else
 #define SECTOR_MASK (blksize_size[MAJOR_NR] &&     \
 	blksize_size[MAJOR_NR][MINOR(CURRENT->dev)] ? \
 	((blksize_size[MAJOR_NR][MINOR(CURRENT->dev)] >> 9) - 1) :  \
 	((BLOCK_SIZE >> 9)  -  1))
+#endif /* IDE_DRIVER */
 
 #define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
 
-extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end);
 extern unsigned long cdu31a_init(unsigned long mem_start, unsigned long mem_end);
 extern unsigned long mcd_init(unsigned long mem_start, unsigned long mem_end);
+#ifdef CONFIG_BLK_DEV_HD
+extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end);
+#endif
+#ifdef CONFIG_BLK_DEV_IDE
+extern unsigned long ide_init(unsigned long mem_start, unsigned long mem_end);
+#endif
 #ifdef CONFIG_SBPCD
 extern unsigned long sbpcd_init(unsigned long, unsigned long);
 #endif CONFIG_SBPCD
@@ -64,14 +73,19 @@
   case BLKROGET: { int __err = verify_area(VERIFY_WRITE, (void *) (where), sizeof(long)); \
 		   if (!__err) put_fs_long(0!=is_read_only(dev),(long *) (where)); return __err; }
 		 
-#ifdef MAJOR_NR
+#if defined(MAJOR_NR) || defined(IDE_DRIVER)
 
 /*
- * Add entries as needed. Currently the only block devices
- * supported are hard-disks and floppies.
+ * Add entries as needed.
  */
 
-#if (MAJOR_NR == MEM_MAJOR)
+#ifdef IDE_DRIVER
+
+#define DEVICE_NR(device)	(MINOR(device) >> PARTN_BITS)
+#define DEVICE_ON(device)	/* nothing */
+#define DEVICE_OFF(device)	/* nothing */
+
+#elif (MAJOR_NR == MEM_MAJOR)
 
 /* ram disk */
 #define DEVICE_NAME "ramdisk"
@@ -187,9 +201,9 @@
 #define DEVICE_ON(device)
 #define DEVICE_OFF(device)
 
-#endif
+#endif /* MAJOR_NR == whatever */
 
-#if (MAJOR_NR != SCSI_TAPE_MAJOR)
+#if (MAJOR_NR != SCSI_TAPE_MAJOR) && !defined(IDE_DRIVER)
 
 #ifndef CURRENT
 #define CURRENT (blk_dev[MAJOR_NR].current_request)
@@ -219,23 +233,46 @@
 
 #define SET_INTR(x) (DEVICE_INTR = (x))
 
-#endif
+#endif /* DEVICE_TIMEOUT */
+
 static void (DEVICE_REQUEST)(void);
 
+#ifdef DEVICE_INTR
+#define CLEAR_INTR SET_INTR(NULL)
+#else
+#define CLEAR_INTR
+#endif
+
+#define INIT_REQUEST \
+	if (!CURRENT) {\
+		CLEAR_INTR; \
+		return; \
+	} \
+	if (MAJOR(CURRENT->dev) != MAJOR_NR) \
+		panic(DEVICE_NAME ": request list destroyed"); \
+	if (CURRENT->bh) { \
+		if (!CURRENT->bh->b_lock) \
+			panic(DEVICE_NAME ": block not locked"); \
+	}
+
+#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) && !defined(IDE_DRIVER) */
+
 /* end_request() - SCSI devices have their own version */
 
 #if ! SCSI_MAJOR(MAJOR_NR)
 
-static void end_request(int uptodate)
-{
-	struct request * req;
+#ifdef IDE_DRIVER
+static void end_request(byte uptodate, byte hwif) {
+	struct request *req = ide_cur_rq[HWIF];
+#else
+static void end_request(int uptodate) {
+	struct request *req = CURRENT;
+#endif /* IDE_DRIVER */
 	struct buffer_head * bh;
 
-	req = CURRENT;
 	req->errors = 0;
 	if (!uptodate) {
-		printk(DEVICE_NAME " I/O error\n");
-		printk("dev %04lX, sector %lu\n",
+		printk("end_request: I/O error, dev %04lX, sector %lu\n",
 		       (unsigned long)req->dev, req->sector);
 		req->nr_sectors--;
 		req->nr_sectors &= ~SECTOR_MASK;
@@ -259,34 +296,19 @@
 			return;
 		}
 	}
+#ifdef IDE_DRIVER
+	ide_cur_rq[HWIF] = NULL;
+#else
 	DEVICE_OFF(req->dev);
 	CURRENT = req->next;
+#endif /* IDE_DRIVER */
 	if (req->sem != NULL)
 		up(req->sem);
 	req->dev = -1;
 	wake_up(&wait_for_request);
 }
-#endif
-
-#ifdef DEVICE_INTR
-#define CLEAR_INTR SET_INTR(NULL)
-#else
-#define CLEAR_INTR
-#endif
-
-#define INIT_REQUEST \
-	if (!CURRENT) {\
-		CLEAR_INTR; \
-		return; \
-	} \
-	if (MAJOR(CURRENT->dev) != MAJOR_NR) \
-		panic(DEVICE_NAME ": request list destroyed"); \
-	if (CURRENT->bh) { \
-		if (!CURRENT->bh->b_lock) \
-			panic(DEVICE_NAME ": block not locked"); \
-	}
+#endif /* ! SCSI_MAJOR(MAJOR_NR) */
 
-#endif
+#endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */
 
-#endif
-#endif
+#endif /* _BLK_H */
diff -u --recursive --new-file v1.1.75/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v1.1.75/linux/drivers/block/genhd.c	Mon May  2 14:56:30 1994
+++ linux/drivers/block/genhd.c	Sun Jan  1 16:28:19 1995
@@ -14,6 +14,7 @@
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
+#include <linux/major.h>
 
 struct gendisk *gendisk_head = NULL;
 
@@ -22,6 +23,19 @@
 extern void rd_load(void);
 extern int ramdisk_size;
 
+static char minor_name (struct gendisk *hd, int minor)
+{
+	char base_name = (hd->major == IDE1_MAJOR) ? 'c' : 'a';
+	return base_name + (minor >> hd->minor_shift);
+}
+
+static void add_partition (struct gendisk *hd, int minor, int start, int size)
+{
+	hd->part[minor].start_sect = start;
+	hd->part[minor].nr_sects   = size;
+	printk(" %s%c%d", hd->major_name, minor_name(hd, minor),
+		minor & ((1 << hd->minor_shift) - 1));
+}
 /*
  * Create devices for each logical partition in an extended partition.
  * The logical partitions form a linked list, with each entry being
@@ -61,13 +75,9 @@
 		 * Process the first entry, which should be the real
 		 * data partition.
 		 */
-			if (p->sys_ind == EXTENDED_PARTITION ||
-			    !(hd->part[current_minor].nr_sects = p->nr_sects))
+			if (p->sys_ind == EXTENDED_PARTITION || !p->nr_sects)
 				goto done;  /* shouldn't happen */
-			hd->part[current_minor].start_sect = this_sector + p->start_sect;
-			printk(" %s%c%d", hd->major_name,
-				'a'+(current_minor >> hd->minor_shift),
-				mask & current_minor);
+			add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
 			current_minor++;
 			p++;
 		/*
@@ -104,19 +114,28 @@
 		printk("Partition check:\n");
 	first_time = 0;
 	first_sector = hd->part[MINOR(dev)].start_sect;
+
+	/*
+	 * This is a kludge to allow the partition check to be
+	 * skipped for specific drives (ie. IDE cd-rom drives)
+	 */
+	if ((int)first_sector == -1) {
+		hd->part[MINOR(dev)].start_sect = 0;
+		return;
+	}
+
 	if (!(bh = bread(dev,0,1024))) {
 		printk("  unable to read partition table of device %04x\n",dev);
 		return;
 	}
-	printk("  %s%c:", hd->major_name, 'a'+(minor >> hd->minor_shift));
-	current_minor += 4;  /* first "extra" minor */
+	printk("  %s%c:", hd->major_name, minor_name(hd, minor));
+	current_minor += 4;  /* first "extra" minor (for extended partitions) */
 	if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
 		p = (struct partition *) (0x1BE + bh->b_data);
 		for (i=1 ; i<=4 ; minor++,i++,p++) {
-			if (!(hd->part[minor].nr_sects = p->nr_sects))
+			if (!p->nr_sects)
 				continue;
-			hd->part[minor].start_sect = first_sector + p->start_sect;
-			printk(" %s%c%d", hd->major_name,'a'+(minor >> hd->minor_shift), i);
+			add_partition(hd, minor, first_sector+p->start_sect, p->nr_sects);
 			if ((current_minor & 0x3f) >= 60)
 				continue;
 			if (p->sys_ind == EXTENDED_PARTITION) {
@@ -136,11 +155,7 @@
 					break;
 				if (!(p->start_sect && p->nr_sects))
 					continue;
-				hd->part[current_minor].start_sect = p->start_sect;
-				hd->part[current_minor].nr_sects = p->nr_sects;
-				printk(" %s%c%d", hd->major_name,
-					'a'+(current_minor >> hd->minor_shift),
-					current_minor & mask);
+				add_partition(hd, current_minor, p->start_sect, p->nr_sects);
 			}
 		}
 	} else
diff -u --recursive --new-file v1.1.75/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v1.1.75/linux/drivers/block/hd.c	Sat Nov 26 18:36:04 1994
+++ linux/drivers/block/hd.c	Sun Jan  1 16:28:19 1995
@@ -1,5 +1,5 @@
 /*
- *  linux/kernel/hd.c
+ *  linux/drivers/block/hd.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
@@ -836,14 +836,6 @@
 		case BLKRRPART: /* Re-read partition tables */
 			return revalidate_hddisk(inode->i_rdev, 1);
 
-		case HDIO_SETUNMASKINTR:	/* obsolete */
-			printk("hd: obsolete syscall: HDIO_SETUNMASKINTR\n");
-			if (!arg)  return -EINVAL;
-			err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
-			if (err)
-				return err;
-			arg = get_fs_long((long *) arg);
-			/* drop into HDIO_SET_UNMASKINTR */
 		case HDIO_SET_UNMASKINTR:
 			if (!suser()) return -EACCES;
 			if ((arg > 1) || (MINOR(inode->i_rdev) & 0x3F))
@@ -867,14 +859,6 @@
 			put_fs_long(mult_count[dev], (long *) arg);
 			return 0;
 
-		case HDIO_SETMULTCOUNT:		/* obsolete */
-			printk("hd: obsolete syscall: HDIO_SETMULTCOUNT\n");
-			if (!arg)  return -EINVAL;
-			err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
-			if (err)
-				return err;
-			arg = get_fs_long((long *) arg);
-			/* drop into HDIO_SET_MULTCOUNT */
 		case HDIO_SET_MULTCOUNT:
 			if (!suser()) return -EACCES;
 			if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
diff -u --recursive --new-file v1.1.75/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v1.1.75/linux/drivers/block/ide-cd.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/block/ide-cd.c	Sun Jan  1 16:28:19 1995
@@ -0,0 +1,1347 @@
+/*
+ * linux/drivers/block/ide-cd.c  (ALPHA)
+ *
+ * 1.00  Oct 31, 1994 -- Initial version.
+ * 1.01  Nov  2, 1994 -- Fixed problem with starting request in
+ *                       cdrom_check_status.
+ * 1.03  Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks)
+ * (from mlord)       -- minor changes to cdrom_setup()
+ *                    -- renamed ide_dev_s to ide_dev_t, enable irq on command
+ * 2.00  Nov 27, 1994 -- Generalize packet command interface;
+ *                       add audio ioctls.
+ * 2.01  Dec  3, 1994 -- Rework packet command interface to handle devices
+ *                       which send an interrupt when ready for a command.
+ * 2.02  Dec 11, 1994 -- Cache the TOC in the driver.
+ *                       Don't use SCMD_PLAYAUDIO_TI; it's not included
+ *                       in the current version of ATAPI.
+ *                       Try to use LBA instead of track or MSF addressing
+ *                       when possible.
+ *                       Don't wait for READY_STAT.
+ *
+ * ATAPI cd-rom driver.  To be used with ide.c.
+ *
+ * Copyright (C) 1994  scott snyder  <snyder@fnald0.fnal.gov>
+ */
+
+#include <linux/cdrom.h>
+
+#define BLOCKS_PER_FRAME (CD_FRAMESIZE / 512)
+
+#define OUT_WORDS(b,n)  outsw (IDE_PORT (HD_DATA, dev->hwif), (b), (n))
+#define IN_WORDS(b,n)   insw  (IDE_PORT (HD_DATA, dev->hwif), (b), (n))
+
+/* special command codes for strategy routine. */
+#define PACKET_COMMAND 4315
+
+#define WIN_PACKETCMD 0xa0  /* Send a packet command. */
+
+/* Some ATAPI command opcodes (just like SCSI).
+   (Some other cdrom-specific codes are in cdrom.h.) */
+#define TEST_UNIT_READY         0x00
+#define REQUEST_SENSE           0x03
+#define START_STOP              0x1b
+#define ALLOW_MEDIUM_REMOVAL    0x1e
+#define READ_10                 0x28
+#define MODE_SENSE_10           0x5a
+#define MODE_SELECT_10          0x55
+
+struct packet_command {
+  char *buffer;
+  int buflen;
+  int stat;
+  unsigned char c[12];
+};
+
+
+struct atapi_request_sense {
+  unsigned char error_code : 7;
+  unsigned char valid      : 1;
+  byte reserved1;
+  unsigned char sense_key  : 4;
+  unsigned char reserved2  : 1;
+  unsigned char ili        : 1;
+  unsigned char reserved3  : 2;
+  byte info[4];
+  byte sense_len;
+  byte command_info[4];
+  byte asc;
+  byte ascq;
+  byte fru;
+  byte sense_key_specific[3];
+};
+
+/* We want some additional flags for cd-rom drives.
+   To save space in the ide_dev_t struct, use one of the fields which
+   doesn't make sense for cd-roms -- `bios_sect'. */
+
+struct ide_cd_flags {
+  unsigned drq_interrupt : 1; /* Device sends an interrupt when ready
+                                 for a packet command. */
+  unsigned no_playaudio12: 1; /* The PLAYAUDIO12 command is not supported. */
+
+  unsigned media_changed : 1; /* Driver has noticed a media change. */
+  unsigned toc_valid     : 1; /* Saved TOC information is current. */
+  unsigned reserved : 4;
+};
+
+#define CDROM_FLAGS(dev) ((struct ide_cd_flags *)&((dev)->bios_sect))
+
+
+/* Space to hold the disk TOC. */
+
+#define MAX_TRACKS 99
+struct atapi_toc_header {
+  unsigned short toc_length;
+  byte first_track;
+  byte last_track;
+};
+
+struct atapi_toc_entry {
+  byte reserved1;
+  unsigned control : 4;
+  unsigned adr     : 4;
+  byte track;
+  byte reserved2;
+  unsigned lba;
+};
+
+struct atapi_toc {
+  struct atapi_toc_header hdr;
+  struct atapi_toc_entry  ent[MAX_TRACKS+1];
+};
+
+
+static struct atapi_toc *cdrom_toc[2][MAX_DRIVES];
+
+
+
+/****************************************************************************
+ * Generic packet command support routines.
+ */
+
+/* Returns 0 if the request should be continued.
+   Returns 1 if the request was ended. */
+static int cdrom_decode_status (ide_dev_t *dev, int good_stat, int *stat_ret)
+{
+  struct request *rq = ide_cur_rq[dev->hwif];
+  int stat, err;
+
+  /* Check for errors. */
+  stat = GET_STAT (dev->hwif);
+  *stat_ret = stat;
+
+  if (OK_STAT (stat, good_stat, BAD_RW_STAT))
+    return 0;
+
+  /* Got an error. */
+  err = IN_BYTE (HD_ERROR, dev->hwif);
+
+  /* Check for tray open */
+  if ((err & 0xf0) == 0x20)
+    {
+      struct packet_command *pc;
+      CDROM_FLAGS (dev)->media_changed = 1;
+      CDROM_FLAGS (dev)->toc_valid = 0;
+
+      /* Fail the request if this is a read command. */
+      if (rq->cmd == READ)
+        {
+          printk ("%s : tray open\n", dev->name);
+          end_request (0, dev->hwif);
+        }
+
+      else
+        {
+          /* Otherwise, it's some other packet command.
+             Print an error message to the syslog.
+             Exception: don't print anything if this is a read subchannel
+             command.  This is because workman constantly polls the drive
+             with this command, and we don't want to uselessly fill up
+             the syslog. */
+          pc = (struct packet_command *)rq->buffer;
+          if (pc->c[0] != SCMD_READ_SUBCHANNEL)
+            printk ("%s : tray open\n", dev->name);
+
+          /* Set the error flag and complete the request. */
+          pc->stat = 1;
+          end_request (1, dev->hwif);
+        }
+    }
+
+  /* Check for media change. */
+  else if ((err & 0xf0) == 0x60)
+    {
+      CDROM_FLAGS (dev)->media_changed = 1;
+      CDROM_FLAGS (dev)->toc_valid = 0;
+      printk ("%s: media changed\n", dev->name);
+
+      /* We're going to retry this command.
+         But be sure to give up if we've retried too many times. */
+      if ((++rq->errors > ERROR_MAX))
+        {
+          end_request (0, dev->hwif);
+        }
+    }
+
+  /* Don't attempt to retry if this was a packet command. */
+  else if (rq->cmd == PACKET_COMMAND)
+    {
+      struct packet_command *pc = (struct packet_command *)rq->buffer;
+      dump_status (dev->hwif, "packet command error", stat);
+      pc->stat = 1;  /* signal error */
+      end_request (1, dev->hwif);
+    }
+
+  /* If there were other errors, go to the default handler. */
+  else if ((err & ~ABRT_ERR) != 0)
+    {
+      ide_error (dev, "cdrom_read_intr", stat);
+    }
+
+  /* Else, abort if we've racked up too many retries. */
+  else if ((++rq->errors > ERROR_MAX))
+    {
+      end_request (0, dev->hwif);
+    }
+
+  /* Retry, or handle the next request. */
+  DO_REQUEST;
+  return 1;
+}
+
+
+/* Set up the device registers for transferring a packet command on DEV,
+   expecting to later transfer XFERLEN bytes.  This should be followed
+   by a call to cdrom_transfer_packet_command; however, if this is a
+   drq_interrupt device, one must wait for an interrupt first. */
+static int cdrom_start_packet_command (ide_dev_t *dev, int xferlen)
+{
+  /* Wait for the controller to be idle. */
+  if (wait_stat (dev, 0, BUSY_STAT, WAIT_READY)) return 1;
+
+  /* Set up the controller registers. */
+  OUT_BYTE (0, HD_FEATURE);
+  OUT_BYTE (0, HD_NSECTOR);
+  OUT_BYTE (0, HD_SECTOR);
+
+  OUT_BYTE (xferlen & 0xff, HD_LCYL);
+  OUT_BYTE (xferlen >> 8  , HD_HCYL);
+  OUT_BYTE (dev->ctl, HD_CMD);
+  OUT_BYTE (WIN_PACKETCMD, HD_COMMAND); /* packet command */
+
+  return 0;
+}
+
+
+/* Send a packet command to DEV described by CMD_BUF and CMD_LEN.
+   The device registers must have already been prepared
+   by cdrom_start_packet_command. */
+static int cdrom_transfer_packet_command (ide_dev_t *dev,
+                                          char *cmd_buf, int cmd_len)
+{
+  if (CDROM_FLAGS (dev)->drq_interrupt)
+    {
+      /* Here we should have been called after receiving an interrupt
+         from the device.  DRQ should how be set. */
+      int stat_dum;
+
+      /* Check for errors. */
+      if (cdrom_decode_status (dev, DRQ_STAT, &stat_dum)) return 1;
+    }
+  else
+    {
+      /* Otherwise, we must wait for DRQ to get set. */
+      if (wait_stat (dev, DRQ_STAT, BAD_STAT, WAIT_READY)) return 1;
+    }
+
+  /* Send the command to the device. */
+  OUT_WORDS (cmd_buf, cmd_len/2);
+
+  return 0;
+}
+
+
+
+/****************************************************************************
+ * Block read functions.
+ */
+
+static int cdrom_start_read (ide_dev_t *dev, unsigned int block);
+
+
+/*
+ * Interrupt routine to read the final status from a transfer.
+ */
+static void cdrom_read_intr_2 (ide_dev_t *dev)
+{
+  int stat;
+  struct request *rq = ide_cur_rq[dev->hwif];
+
+  stat = GET_STAT (dev->hwif);
+
+  if (OK_STAT (stat, 0, BAD_STAT))
+    {
+      if (rq->current_nr_sectors <= 0)
+        {
+          end_request (1, dev->hwif);
+        }
+
+      if (rq->current_nr_sectors > 0)
+        {
+          cdrom_start_read (dev, rq->sector);
+          return;
+        }
+    }
+  else
+    ide_error (dev, "cdrom_read_intr_2", stat);
+
+  DO_REQUEST;
+}
+
+
+/*
+ * Interrupt routine.  Called when a read request has completed.
+ */
+static void cdrom_read_intr (ide_dev_t *dev)
+{
+  int stat_dum, len;
+  struct request *rq = ide_cur_rq[dev->hwif];
+
+  /* Check for errors. */
+  if (cdrom_decode_status (dev, DRQ_STAT, &stat_dum)) return;
+
+  /* Error bit not set.
+     Read the device registers to see how much data is waiting. */
+  len = IN_BYTE (HD_LCYL, dev->hwif) + 256 * IN_BYTE (HD_HCYL, dev->hwif);
+
+  if (len != CD_FRAMESIZE)
+    {
+      printk ("cdrom_read_intr: funny value for read length %d\n", len);
+      if (len > CD_FRAMESIZE) len = CD_FRAMESIZE;
+    }
+
+  IN_WORDS (rq->buffer, len/2);
+
+  rq->current_nr_sectors -= BLOCKS_PER_FRAME;
+  rq->nr_sectors -= BLOCKS_PER_FRAME;
+  rq->sector += BLOCKS_PER_FRAME;
+  rq->buffer += CD_FRAMESIZE;
+
+  /* Wait for another interrupt with the final status. */
+  ide_handler[dev->hwif] = cdrom_read_intr_2;
+}
+
+
+/*
+ * Routine to send a read packet command to the drive.
+ * This is usually called directly from cdrom_start_read.
+ * However, for drq_interrupt devices, it is called from an interrupt
+ * when the drive is ready to accept the command.
+ */
+static int cdrom_start_read_continuation (ide_dev_t *dev)
+{
+  struct packet_command pc;
+  struct request *rq = ide_cur_rq[dev->hwif];
+
+  /* Set up the command */
+  memset (&pc.c, 0, sizeof (pc.c));
+  pc.c[0] = READ_10;
+  pc.c[8] = 1;  /* lsb of transfer length */
+
+  /* Write the sector address into the command image. */
+  {
+    union {
+      struct {unsigned char b0, b1, b2, b3;} b;
+      struct {unsigned long l0;} l;
+    } conv;
+    conv.l.l0 = rq->sector / BLOCKS_PER_FRAME;
+    pc.c[2] = conv.b.b3;
+    pc.c[3] = conv.b.b2;
+    pc.c[4] = conv.b.b1;
+    pc.c[5] = conv.b.b0;
+  }
+
+  if (cdrom_transfer_packet_command (dev, pc.c, sizeof (pc.c)))
+    return 1;
+
+  /* Set up our interrupt handler and return. */
+  ide_handler[dev->hwif] = cdrom_read_intr;
+
+  return 0;
+}
+
+
+/*
+ * Start a read request from the CD-ROM.
+ * Returns 0 if the request was started successfully,
+ *  1 if there was an error and we should either retry or move on to the
+ *  next request.
+ */
+static int cdrom_start_read (ide_dev_t *dev, unsigned int block)
+{
+  struct request *rq = ide_cur_rq[dev->hwif];
+
+  if (rq->cmd == READ &&
+      (rq->current_nr_sectors != BLOCKS_PER_FRAME ||
+       (rq->sector & (BLOCKS_PER_FRAME-1)) != 0))
+        {
+          printk ("cdrom_start_read: funny request 0x%lx 0x%lx\n",
+                  rq->current_nr_sectors, rq->sector);
+          end_request (0, dev->hwif);
+          return 1;
+        }
+
+  if (cdrom_start_packet_command (dev, CD_FRAMESIZE))
+    return 1;
+
+  if (CDROM_FLAGS (dev)->drq_interrupt)
+    ide_handler[dev->hwif] = (void (*)(ide_dev_t *))cdrom_start_read_continuation;
+  else
+    {
+      if (cdrom_start_read_continuation (dev))
+        return 1;
+    }
+
+  return 0;
+}
+
+
+
+/****************************************************************************
+ * Execute all other packet commands.
+ */
+
+static void cdrom_pc_intr (ide_dev_t *dev)
+{
+  int ireason, len, stat, thislen;
+  struct request *rq = ide_cur_rq[dev->hwif];
+  struct packet_command *pc = (struct packet_command *)rq->buffer;
+
+  /* Check for errors. */
+  if (cdrom_decode_status (dev, 0, &stat)) return;
+
+  /* Read the interrupt reason and the transfer length. */
+  ireason = IN_BYTE (HD_NSECTOR, dev->hwif);
+  len = IN_BYTE (HD_LCYL, dev->hwif) + 256 * IN_BYTE (HD_HCYL, dev->hwif);
+
+  /* If DRQ is clear, the command has completed.
+     Complain if we still have data left to transfer. */
+  if ((stat & DRQ_STAT) == 0)
+    {
+      if (pc->buflen == 0)
+        end_request (1, dev->hwif);
+      else
+        {
+          printk ("%s: cdrom_pc_intr: data underrun %d\n",
+                  dev->name, pc->buflen);
+          pc->stat = 1;
+          end_request (1, dev->hwif);
+        }
+      DO_REQUEST;
+      return;
+    }
+
+  /* Figure out how much data to transfer. */
+  thislen = pc->buflen;
+  if (thislen < 0) thislen = -thislen;
+  if (thislen > len) thislen = len;
+
+  /* The drive wants to be written to. */
+  if ((ireason & 3) == 0)
+    {
+      /* Check that we want to write. */
+      if (pc->buflen > 0)
+        {
+          printk ("%s: cdrom_pc_intr: Drive wants to transfer data the wrong way!\n",
+                  dev->name);
+          pc->stat = 1;
+          thislen = 0;
+        }
+
+      /* Transfer the data. */
+      OUT_WORDS (pc->buffer, thislen / 2);
+
+      /* If we haven't moved enough data to satisfy the drive,
+         add some padding. */
+      while (len > thislen)
+        {
+          short dum = 0;
+          OUT_WORDS (&dum, 1);
+          len -= 2;
+        }
+
+      /* Keep count of how much data we've moved. */
+      pc->buffer += thislen;
+      pc->buflen += thislen;
+    }
+
+  /* Same drill for reading. */
+  else if ((ireason & 3) == 2)
+    {
+      /* Check that we want to read. */
+      if (pc->buflen < 0)
+        {
+          printk ("%s: cdrom_pc_intr: Drive wants to transfer data the wrong way!\n",
+                  dev->name);
+          pc->stat = 1;
+          thislen = 0;
+        }
+
+      /* Transfer the data. */
+      IN_WORDS (pc->buffer, thislen / 2);
+
+      /* If we haven't moved enough data to satisfy the drive,
+         add some padding. */
+      while (len > thislen)
+        {
+          short dum = 0;
+          IN_WORDS (&dum, 1);
+          len -= 2;
+        }
+
+      /* Keep count of how much data we've moved. */
+      pc->buffer += thislen;
+      pc->buflen -= thislen;
+    }
+
+  else
+    {
+      printk ("%s: cdrom_pc_intr: The drive appears confused (ireason = 0x%2x)\n",
+              dev->name, ireason);
+      pc->stat = 1;
+    }
+
+  /* Now we wait for another interrupt. */
+  ide_handler[dev->hwif] = cdrom_pc_intr;
+}
+
+
+static int cdrom_do_pc_continuation (ide_dev_t *dev)
+{
+  struct request *rq = ide_cur_rq[dev->hwif];
+  struct packet_command *pc = (struct packet_command *)rq->buffer;
+
+  if (cdrom_transfer_packet_command (dev, pc->c, sizeof (pc->c)))
+    return 1;
+
+  /* Set up our interrupt handler and return. */
+  ide_handler[dev->hwif] = cdrom_pc_intr;
+
+  return 0;
+}
+
+
+static int cdrom_do_packet_command (ide_dev_t *dev)
+{
+  int len;
+  struct request *rq = ide_cur_rq[dev->hwif];
+  struct packet_command *pc = (struct packet_command *)rq->buffer;
+
+  len = pc->buflen;
+  if (len < 0) len = -len;
+
+  pc->stat = 0;
+
+  if (cdrom_start_packet_command (dev, len))
+    return 1;
+
+  if (CDROM_FLAGS (dev)->drq_interrupt)
+    ide_handler[dev->hwif] = (void (*)(ide_dev_t *))cdrom_do_pc_continuation;
+  else
+    {
+      if (cdrom_do_pc_continuation (dev))
+        return 1;
+    }
+
+  return 0;
+}
+
+
+static
+int cdrom_queue_packet_command (ide_dev_t *dev, struct packet_command *pc)
+{
+  unsigned long flags;
+  struct request req, **p, **pfirst;
+  struct semaphore sem = MUTEX_LOCKED;
+  int major = ide_major[dev->hwif];
+
+  req.dev = MKDEV (major, (dev->select.b.drive) << PARTN_BITS);
+  req.cmd = PACKET_COMMAND;
+  req.errors = 0;
+  req.sector = 0;
+  req.nr_sectors = 0;
+  req.current_nr_sectors = 0;
+  req.buffer = (char *)pc;
+  req.sem = &sem;
+  req.bh = NULL;
+  req.bhtail = NULL;
+  req.next = NULL;
+
+  save_flags (flags);
+  cli ();
+
+  p = &blk_dev[major].current_request;
+  pfirst = p;
+  while ((*p) != NULL)
+    {
+      p = &((*p)->next);
+    }
+  *p = &req;
+  if (p == pfirst)
+    blk_dev[major].request_fn ();
+
+  restore_flags (flags);
+
+  down (&sem);
+
+  if (pc->stat != 0)
+    return -EIO;
+  else
+    return 0;
+}
+
+
+
+/****************************************************************************
+ * cdrom driver request routine.
+ */
+
+static int do_rw_cdrom (ide_dev_t *dev, unsigned long block)
+{
+  struct request *rq = ide_cur_rq[dev->hwif];
+
+  if (rq -> cmd == PACKET_COMMAND)
+    return cdrom_do_packet_command (dev);
+
+  if (rq -> cmd != READ)
+    {
+      printk ("ide-cd: bad cmd %d\n", rq -> cmd);
+      end_request (0, dev->hwif);
+      return 1;
+    }
+
+  if (rq->cmd == READ)
+    {
+      /* This can happen if there was an I/O error on the previous
+         buffer in this request. */
+      if ((rq->nr_sectors & (BLOCKS_PER_FRAME-1)) == BLOCKS_PER_FRAME-1 &&
+          (rq->sector & (BLOCKS_PER_FRAME-1)) == 1 &&
+          (rq->current_nr_sectors & (BLOCKS_PER_FRAME-1)) == 0)
+        {
+          rq->nr_sectors &= (BLOCKS_PER_FRAME-1);
+          rq->sector = (rq->sector+BLOCKS_PER_FRAME) & (BLOCKS_PER_FRAME-1);
+        }
+    }
+
+  return cdrom_start_read (dev, block);
+}
+
+
+
+/****************************************************************************
+ * ioctl handling.
+ */
+
+static inline
+void byte_swap_word (unsigned short *x)
+{
+  char *c = (char *)x;
+  char d = c[0];
+  c[0] = c[1];
+  c[1] = d;
+}
+
+
+static inline
+void byte_swap_long (unsigned *x)
+{
+  char *c = (char *)x;
+  char d = c[0];
+  c[0] = c[3];
+  c[3] = d;
+  d = c[1];
+  c[1] = c[2];
+  c[2] = d;
+}
+
+
+static
+int bin2bcd (int x)
+{
+  return (x%10) | ((x/10) << 4);
+}
+
+
+static inline
+void lba_to_msf (int lba, byte *m, byte *s, byte *f)
+{
+  lba += CD_BLOCK_OFFSET;
+  lba &= 0xffffff;  /* negative lbas use only 24 bits */
+  *m = lba / (CD_SECS * CD_FRAMES);
+  lba %= (CD_SECS * CD_FRAMES);
+  *s = lba / CD_FRAMES;
+  *f = lba % CD_FRAMES;
+}
+
+
+static inline
+int msf_to_lba (byte m, byte s, byte f)
+{
+  return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET;
+}
+
+
+static void
+cdrom_check_status (ide_dev_t  *dev)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.c[0] = TEST_UNIT_READY;
+
+  (void) cdrom_queue_packet_command (dev, &pc);
+}
+
+
+static int
+cdrom_request_sense (ide_dev_t *dev, struct atapi_request_sense *reqbuf)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.c[0] = REQUEST_SENSE;
+  pc.c[4] = sizeof (*reqbuf);
+  pc.buffer = (char *)reqbuf;
+  pc.buflen = sizeof (*reqbuf);
+
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+#if 0
+/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
+static int
+cdrom_lockdoor (ide_dev_t *dev, int lockflag)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.c[0] = ALLOW_MEDIUM_REMOVAL;
+  pc.c[4] = (lockflag != 0);
+  return cdrom_queue_packet_command (dev, &pc);
+}
+#endif
+
+
+/* Eject the disk if EJECTFLAG is 0.
+   If EJECTFLAG is 1, try to reload the disk. */
+static int
+cdrom_eject (ide_dev_t *dev, int ejectflag)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.c[0] = START_STOP;
+  pc.c[4] = 2 + (ejectflag != 0);
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+static int
+cdrom_pause (ide_dev_t *dev, int pauseflag)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.c[0] = SCMD_PAUSE_RESUME;
+  pc.c[8] = !pauseflag;
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+static int
+cdrom_startstop (ide_dev_t *dev, int startflag)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.c[0] = START_STOP;
+  pc.c[1] = 1;
+  pc.c[4] = startflag;
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+static int
+cdrom_read_tocentry (ide_dev_t *dev, int trackno, int msf_flag,
+                     char *buf, int buflen)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.buffer =  buf;
+  pc.buflen = buflen;
+  pc.c[0] = SCMD_READ_TOC;
+  pc.c[6] = trackno;
+  pc.c[7] = (buflen >> 8);
+  pc.c[8] = (buflen & 0xff);
+  if (msf_flag) pc.c[1] = 2;
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+/* Try to read the entire TOC for the disk into our internal buffer. */
+static int
+cdrom_read_toc (ide_dev_t *dev)
+{
+  int stat, ntracks, i;
+  struct atapi_toc *toc = cdrom_toc[dev->hwif][dev->select.b.drive];
+
+  if (toc == NULL)
+    {
+      /* Try to allocate space. */
+      toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc),
+                                          GFP_KERNEL);
+      cdrom_toc[dev->hwif][dev->select.b.drive] = toc;
+    }
+
+  if (toc == NULL)
+    {
+      printk ("%s: No cdrom TOC buffer!\n", dev->name);
+      return -EIO;
+    }
+
+  /* Check to see if the existing data is still valid.
+     If it is, just return. */
+  if (CDROM_FLAGS (dev)->toc_valid)
+    cdrom_check_status (dev);
+
+  if (CDROM_FLAGS (dev)->toc_valid) return 0;
+
+  /* First read just the header, so we know how long the TOC is. */
+  stat = cdrom_read_tocentry (dev, 0, 0, (char *)toc,
+                              sizeof (struct atapi_toc_header) +
+                              sizeof (struct atapi_toc_entry));
+  if (stat) return stat;
+
+  ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
+  if (ntracks <= 0) return -EIO;
+  if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS;
+
+  /* Now read the whole schmeer. */
+  stat = cdrom_read_tocentry (dev, 0, 0, (char *)toc,
+                              sizeof (struct atapi_toc_header) +
+                              (ntracks+1) * sizeof (struct atapi_toc_entry));
+  if (stat) return stat;
+  byte_swap_word (&toc->hdr.toc_length);
+  for (i=0; i<=ntracks; i++)
+    byte_swap_long (&toc->ent[i].lba);
+
+  /* Remember that we've read this stuff. */
+  CDROM_FLAGS (dev)->toc_valid = 1;
+
+  return 0;
+}
+
+
+static int
+cdrom_read_subchannel (ide_dev_t *dev,
+                       char *buf, int buflen)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.buffer =  buf;
+  pc.buflen = buflen;
+  pc.c[0] = SCMD_READ_SUBCHANNEL;
+  pc.c[2] = 0x40;  /* request subQ data */
+  pc.c[3] = 0x01;  /* Format 1: current position */
+  pc.c[7] = (buflen >> 8);
+  pc.c[8] = (buflen & 0xff);
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+/* modeflag: 0 = current, 1 = changable mask, 2 = default, 3 = saved */
+static int
+cdrom_mode_sense (ide_dev_t *dev, int pageno, int modeflag,
+                  char *buf, int buflen)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.buffer =  buf;
+  pc.buflen = buflen;
+  pc.c[0] = MODE_SENSE_10;
+  pc.c[2] = pageno | (modeflag << 6);
+  pc.c[7] = (buflen >> 8);
+  pc.c[8] = (buflen & 0xff);
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+static int
+cdrom_mode_select (ide_dev_t *dev, char *buf, int buflen)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.buffer =  buf;
+  pc.buflen = - buflen;
+  pc.c[0] = MODE_SELECT_10;
+  pc.c[1] = 0x10;
+  pc.c[7] = (buflen >> 8);
+  pc.c[8] = (buflen & 0xff);
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+static int
+cdrom_play_lba_range_play12 (ide_dev_t *dev, int lba_start, int lba_end)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.c[0] = SCMD_PLAYAUDIO12;
+  *(int *)(&pc.c[2]) = lba_start;
+  *(int *)(&pc.c[6]) = lba_end - lba_start;
+  byte_swap_long ((int *)(&pc.c[2]));
+  byte_swap_long ((int *)(&pc.c[6]));
+
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+static int
+cdrom_play_lba_range_msf (ide_dev_t *dev, int lba_start, int lba_end)
+{
+  struct packet_command pc;
+
+  memset (&pc, 0, sizeof (pc));
+
+  pc.c[0] = SCMD_PLAYAUDIO_MSF;
+  lba_to_msf (lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
+  lba_to_msf (lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
+
+  pc.c[3] = bin2bcd (pc.c[3]);
+  pc.c[4] = bin2bcd (pc.c[4]);
+  pc.c[5] = bin2bcd (pc.c[5]);
+  pc.c[6] = bin2bcd (pc.c[6]);
+  pc.c[7] = bin2bcd (pc.c[7]);
+  pc.c[8] = bin2bcd (pc.c[8]);
+
+  return cdrom_queue_packet_command (dev, &pc);
+}
+
+
+/* Play audio starting at LBA LBA_START and finishing with the
+   LBA before LBA_END. */
+static int
+cdrom_play_lba_range (ide_dev_t *dev, int lba_start, int lba_end)
+{
+  /* This is rather annoying.
+     My NEC-260 won't recognize group 5 commands such as PLAYAUDIO12;
+     the only way to get it to play more than 64k of blocks at once
+     seems to be the PLAYAUDIO_MSF command.  However, the parameters
+     the NEC 260 wants for the PLAYMSF command are incompatible with
+     the new version of the spec.
+
+     So what i'll try is this.  First try for PLAYAUDIO12.  If it works,
+     great.  Otherwise, if the drive reports an illegal command code,
+     try PLAYAUDIO_MSF using the NEC 260-style bcd parameters. */
+
+  if (CDROM_FLAGS (dev)->no_playaudio12)
+    return cdrom_play_lba_range_msf (dev, lba_start, lba_end);
+  else
+    {
+      int stat, stat2;
+      struct atapi_request_sense reqbuf;
+
+      stat = cdrom_play_lba_range_play12 (dev, lba_start, lba_end);
+      if (stat == 0) return 0;
+
+      /* It failed.  Try to find out why. */
+      stat2 = cdrom_request_sense (dev, &reqbuf);
+      if (stat2) return stat;
+
+      if (reqbuf.sense_key == 0x05 && reqbuf.asc == 0x20)
+        {
+          /* The drive didn't recognize the command.
+             Retry with the MSF variant. */
+          printk ("%s: Drive does not support PLAYAUDIO12; "
+                  "trying PLAYAUDIO_MSF\n", dev->name);
+          CDROM_FLAGS (dev)->no_playaudio12 = 1;
+          return cdrom_play_lba_range_msf (dev, lba_start, lba_end);
+        }
+
+      /* Failed for some other reason.  Give up. */
+      return stat;
+    }
+}
+
+
+static
+int cdrom_get_toc_entry (ide_dev_t *dev, int track,
+                         struct atapi_toc_entry **ent)
+{
+  int stat, ntracks;
+  struct atapi_toc *toc;
+
+  /* Make sure our saved TOC is valid. */
+  stat = cdrom_read_toc (dev);
+  if (stat) return stat;
+
+  toc = cdrom_toc[dev->hwif][dev->select.b.drive];
+
+  /* Check validity of requested track number. */
+  ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
+  if (track == CDROM_LEADOUT)
+    *ent = &toc->ent[ntracks];
+  else if (track < toc->hdr.first_track ||
+           track > toc->hdr.last_track)
+    return -EINVAL;
+  else
+    *ent = &toc->ent[track - toc->hdr.first_track];
+
+  return 0;
+}
+
+
+static int ide_cdrom_ioctl (ide_dev_t *dev, struct inode *inode,
+                        struct file *file, unsigned int cmd, unsigned long arg)
+{
+  switch (cmd)
+    {
+    case CDROMEJECT:
+      return cdrom_eject (dev, 0);
+
+    case CDROMPAUSE:
+      return cdrom_pause (dev, 1);
+
+    case CDROMRESUME:
+      return cdrom_pause (dev, 0);
+
+    case CDROMSTART:
+      return cdrom_startstop (dev, 1);
+
+    case CDROMSTOP:
+      return cdrom_startstop (dev, 0);
+
+    case CDROMPLAYMSF:
+      {
+        struct cdrom_msf msf;
+        int stat, lba_start, lba_end;
+
+        stat = verify_area (VERIFY_READ, (void *)arg, sizeof (msf));
+        if (stat) return stat;
+
+        memcpy_fromfs (&msf, (void *) arg, sizeof(msf));
+
+        lba_start = msf_to_lba (msf.cdmsf_min0, msf.cdmsf_sec0,
+                                msf.cdmsf_frame0);
+        lba_end = msf_to_lba (msf.cdmsf_min1, msf.cdmsf_sec1,
+                              msf.cdmsf_frame1) + 1;
+
+        if (lba_end <= lba_start) return -EINVAL;
+
+        return cdrom_play_lba_range (dev, lba_start, lba_end);
+      }
+
+    /* Like just about every other Linux cdrom driver, we ignore the
+       index part of the request here. */
+    case CDROMPLAYTRKIND:
+      {
+        int stat, lba_start, lba_end;
+        struct cdrom_ti ti;
+        struct atapi_toc_entry *first_toc, *last_toc;
+
+        stat = verify_area (VERIFY_READ, (void *)arg, sizeof (ti));
+        if (stat) return stat;
+
+        memcpy_fromfs (&ti, (void *) arg, sizeof(ti));
+
+        stat = cdrom_get_toc_entry (dev, ti.cdti_trk0, &first_toc);
+        if (stat) return stat;
+        stat = cdrom_get_toc_entry (dev, ti.cdti_trk1, &last_toc);
+        if (stat) return stat;
+
+        if (ti.cdti_trk1 != CDROM_LEADOUT) ++last_toc;
+        lba_start = first_toc->lba;
+        lba_end   = last_toc->lba;
+
+        if (lba_end <= lba_start) return -EINVAL;
+
+        return cdrom_play_lba_range (dev, lba_start, lba_end);
+      }
+
+    case CDROMREADTOCHDR:
+      {
+        int stat;
+        struct cdrom_tochdr tochdr;
+        struct atapi_toc *toc;
+
+        stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (tochdr));
+        if (stat) return stat;
+
+        /* Make sure our saved TOC is valid. */
+        stat = cdrom_read_toc (dev);
+        if (stat) return stat;
+
+        toc = cdrom_toc[dev->hwif][dev->select.b.drive];
+        tochdr.cdth_trk0 = toc->hdr.first_track;
+        tochdr.cdth_trk1 = toc->hdr.last_track;
+
+        memcpy_tofs ((void *) arg, &tochdr, sizeof (tochdr));
+
+        return stat;
+      }
+
+    case CDROMREADTOCENTRY:
+      {
+        int stat;
+        struct cdrom_tocentry tocentry;
+        struct atapi_toc_entry *toce;
+
+        stat = verify_area (VERIFY_READ, (void *) arg, sizeof (tocentry));
+        if (stat) return stat;
+        stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (tocentry));
+        if (stat) return stat;
+
+        memcpy_fromfs (&tocentry, (void *) arg, sizeof (tocentry));
+
+        stat = cdrom_get_toc_entry (dev, tocentry.cdte_track, &toce);
+        if (stat) return stat;
+
+        tocentry.cdte_ctrl = toce->control;
+        tocentry.cdte_adr  = toce->adr;
+
+        if (tocentry.cdte_format == CDROM_MSF)
+          {
+            /* convert to MSF */
+            lba_to_msf (toce->lba,
+                        &tocentry.cdte_addr.msf.minute,
+                        &tocentry.cdte_addr.msf.second,
+                        &tocentry.cdte_addr.msf.frame);
+          }
+        else
+          tocentry.cdte_addr.lba = toce->lba;
+
+        memcpy_tofs ((void *) arg, &tocentry, sizeof (tocentry));
+
+        return stat;
+      }
+
+    case CDROMSUBCHNL:
+      {
+        char buffer[16];
+        int stat, abs_lba, rel_lba;
+        struct cdrom_subchnl subchnl;
+
+        stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (subchnl));
+        if (stat) return stat;
+        stat = verify_area (VERIFY_READ, (void *) arg, sizeof (subchnl));
+        if (stat) return stat;
+
+        memcpy_fromfs (&subchnl, (void *) arg, sizeof (subchnl));
+
+        stat = cdrom_read_subchannel (dev, buffer, sizeof (buffer));
+        if (stat) return stat;
+
+        abs_lba = *(int *)&buffer[8];
+        rel_lba = *(int *)&buffer[12];
+        byte_swap_long (&abs_lba);
+        byte_swap_long (&rel_lba);
+
+        if (subchnl.cdsc_format == CDROM_MSF)
+          {
+            lba_to_msf (abs_lba,
+                        &subchnl.cdsc_absaddr.msf.minute,
+                        &subchnl.cdsc_absaddr.msf.second,
+                        &subchnl.cdsc_absaddr.msf.frame);
+            lba_to_msf (rel_lba,
+                        &subchnl.cdsc_reladdr.msf.minute,
+                        &subchnl.cdsc_reladdr.msf.second,
+                        &subchnl.cdsc_reladdr.msf.frame);
+          }
+        else
+          {
+            subchnl.cdsc_absaddr.lba = abs_lba;
+            subchnl.cdsc_reladdr.lba = rel_lba;
+          }
+
+        subchnl.cdsc_audiostatus = buffer[1];
+        subchnl.cdsc_ctrl = buffer[5] & 0xf;
+        subchnl.cdsc_trk = buffer[6];
+        subchnl.cdsc_ind = buffer[7];
+
+        memcpy_tofs ((void *) arg, &subchnl, sizeof (subchnl));
+
+        return stat;
+      }
+
+    case CDROMVOLCTRL:
+      {
+        struct cdrom_volctrl volctrl;
+        char buffer[24], mask[24];
+        int stat;
+
+        stat = verify_area (VERIFY_READ, (void *) arg, sizeof (volctrl));
+        if (stat) return stat;
+        memcpy_fromfs (&volctrl, (void *) arg, sizeof (volctrl));
+
+        stat = cdrom_mode_sense (dev, 0x0e, 0, buffer, sizeof (buffer));
+        if (stat) return stat;
+        stat = cdrom_mode_sense (dev, 0x0e, 1, mask  , sizeof (buffer));
+        if (stat) return stat;
+
+        buffer[1] = buffer[2] = 0;
+
+        buffer[17] = volctrl.channel0 & mask[17];
+        buffer[19] = volctrl.channel1 & mask[19];
+        buffer[21] = volctrl.channel2 & mask[21];
+        buffer[23] = volctrl.channel3 & mask[23];
+
+        return cdrom_mode_select (dev, buffer, sizeof (buffer));
+      }
+
+#ifdef TEST
+    case 0x1234:
+      {
+        int stat;
+        struct packet_command pc;
+
+        memset (&pc, 0, sizeof (pc));
+
+        stat = verify_area (VERIFY_READ, (void *) arg, sizeof (pc.c));
+        if (stat) return stat;
+        memcpy_fromfs (&pc.c, (void *) arg, sizeof (pc.c));
+
+        return cdrom_queue_packet_command (dev, &pc);
+      }
+
+    case 0x1235:
+      {
+        int stat;
+        struct atapi_request_sense reqbuf;
+
+        stat = verify_area (VERIFY_WRITE, (void *) arg, sizeof (reqbuf));
+        if (stat) return stat;
+
+        stat = cdrom_request_sense (dev, &reqbuf);
+
+        memcpy_tofs ((void *) arg, &reqbuf, sizeof (reqbuf));
+
+        return stat;
+      }
+#endif
+
+    default:
+      return -EPERM;
+    }
+
+}
+
+
+
+/****************************************************************************
+ * Other driver requests (open, close, check media change).
+ */
+
+static int cdrom_check_media_change (ide_dev_t *dev)
+{
+  int retval;
+
+  cdrom_check_status (dev);
+
+  retval = CDROM_FLAGS (dev)->media_changed;
+  CDROM_FLAGS (dev)->media_changed = 0;
+
+  return retval;
+}
+
+
+static int
+cdrom_open (struct inode *ip, struct file *fp, ide_dev_t *dev)
+{
+  /* no write access */
+  if (fp->f_mode & 2) return -EROFS;
+
+#if 0 /* With this, one cannot eject a disk with workman */
+  /* If this is the first open, lock the door. */
+  if (dev->usage == 1)
+    (void) cdrom_lockdoor (dev, 1);
+#endif
+
+  /* Should check that there's a disk in the drive? */
+  return 0;
+}
+
+
+/*
+ * Close down the device.  Invalidate all cached blocks.
+ */
+
+static void
+cdrom_release (struct inode *inode, struct file *file, ide_dev_t *dev)
+{
+  if (dev->usage == 0)
+    {
+      invalidate_buffers (inode->i_rdev);
+
+#if 0
+      /* Unlock the door. */
+      (void) cdrom_lockdoor (dev, 0);
+#endif
+    }
+}
+
+
+
+/****************************************************************************
+ * Device initialization.
+ */
+
+static void cdrom_setup (ide_dev_t *dev)
+{
+  /* Just guess at capacity for now. */
+  ide_capacity[dev->hwif][dev->select.b.drive] = 0x1fffff;
+
+  ide_blksizes[dev->hwif][dev->select.b.drive << PARTN_BITS] = CD_FRAMESIZE;
+
+  dev->special.all = 0;
+
+  CDROM_FLAGS (dev)->media_changed = 0;
+  CDROM_FLAGS (dev)->toc_valid     = 0;
+
+  CDROM_FLAGS (dev)->no_playaudio12 = 0;
+  CDROM_FLAGS (dev)->drq_interrupt = ((dev->id->config & 0x0060) == 0x20);
+
+  cdrom_toc[dev->hwif][dev->select.b.drive] = NULL;
+}
+
+
+
+
+/*
+ * TODO:
+ *  Retrieve and interpret extended ATAPI error codes.
+ *  Transfer multiple sectors at once.
+ *  Read actual disk capacity.
+ *  Support demand-paged executables (1k block sizes?).
+ *  Multisession support.
+ *  Direct reading of audio data.
+ *  Eject-on-dismount.
+ *  Lock door while there's a mounted volume.
+ */
+
diff -u --recursive --new-file v1.1.75/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v1.1.75/linux/drivers/block/ide.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/block/ide.c	Sun Jan  1 19:49:19 1995
@@ -0,0 +1,2163 @@
+/*
+ *  linux/drivers/block/ide.c	Version 3.5  December 30, 1994
+ *
+ *  Copyright (C) 1994  Linus Torvalds & authors (see below)
+ */
+
+/*
+ * This is the dual IDE interface driver, as evolved from hd.c.  
+ * It supports up to two IDE interfaces, on one or two IRQs (usually 14 & 15).
+ * There can be up to two drives per interface, as per the ATA-2 spec.
+ *
+ * Primary   i/f: ide0: major=3;  (hda)         minor=0, (hdb)         minor=64
+ * Secondary i/f: ide1: major=22; (hdc or hd1a) minor=0, (hdd or hd1b) minor=64
+ *
+ *  From hd.c:
+ *  |
+ *  | It traverses the request-list, using interrupts to jump between functions.
+ *  | As nearly all functions can be called within interrupts, we may not sleep.
+ *  | Special care is recommended.  Have Fun!
+ *  |
+ *  | modified by Drew Eckhardt to check nr of hd's from the CMOS.
+ *  |
+ *  | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ *  | in the early extended-partition checks and added DM partitions.
+ *  |
+ *  | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI).
+ *  |
+ *  | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
+ *  | and general streamlining by Mark Lord (mlord@bnr.ca).
+ *
+ *  October, 1994 -- Complete line-by-line overhaul for linux 1.3.x, by:
+ *
+ *	Mark Lord	(mlord@bnr.ca)			(IDE Perf.Pkg)
+ *	Delman Lee	(delman@mipg.upenn.edu)		("Mr. atdisk2")
+ *	Petri Mattila	(ptjmatti@kruuna.helsinki.fi)	(EIDE stuff)
+ *	Scott Snyder	(snyder@fnald0.fnal.gov)	(ATAPI IDE cd-rom)
+ *
+ *  This was a rewrite of just about everything from hd.c, though some original
+ *  code is still sprinkled about.  Think of it as a major evolution, with 
+ *  inspiration from lots of linux users, esp.  hamish@zot.apana.org.au
+ *
+ *  Version 1.0 ALPHA	initial code, primary i/f working okay
+ *  Version 1.1 ALPHA	fixes for dual i/f
+ *  Version 1.2 ALPHA	first serious attempt at sharing irqs
+ *  Version 1.3 BETA	dual i/f on shared irq tested & working!
+ *  Version 1.4 BETA	added auto probing for irq(s)
+ *  Version 1.5 BETA	added ALPHA (untested) support for IDE cd-roms,
+ *			fixed hd.c coexistance bug, other minor stuff
+ *  Version 1.6 BETA	fix link error when cd-rom not configured
+ *  Version 2.0 BETA	lots of minor fixes; remove annoying messages; ...
+ *  Version 2.2 BETA	fixed reset_drives; major overhaul of autoprobing
+ *  Version 2.3 BETA	set DEFAULT_UNMASK_INTR to 0 again; cosmetic changes
+ *  Version 2.4 BETA	added debounce on reading of drive status reg,
+ *			added config flags to remove unwanted features
+ *  Version 2.5 BETA	fixed problem with leftover phantom IRQ after probe,
+ *			allow "set_geometry" even when in LBA (as per spec(?)),
+ *			assorted miscellaneous tweaks.
+ *  Version 2.6 BETA	more config flag stuff, another probing tweak,
+ *  (not released)	multmode now defaults to status quo from boot time,
+ *			moved >16heads check to init time, rearranged reset code
+ *			added HDIO_DRIVE_CMD, removed standby/xfermode stuff
+ *			hopefully fixed ATAPI probing code, added hdx=cdrom
+ *  Version 2.7 BETA	fixed invocation of cdrom_setup()
+ *  Version 2.8 BETA	fixed compile error for DISK_RECOVERY_TIME>0
+ *			fixed incorrect drive selection in DO_DRIVE_CMD (Bug!)
+ *  Version 2.9 BETA	more work on ATAPI CDROM recognition
+ *  (not released)	changed init order so partition checks go in sequence
+ *  Version 3.0 BETA	included ide-cd.c update from Steve with Mitsumi fixes
+ *			attempt to fix byte-swap problem with Mitsumi id_info
+ *			ensure drives on second i/f get initialized on boot
+ *			preliminary compile-time support for 32bit IDE i/f chips
+ *			added check_region() and snarf_region() to probes
+ *  Version 3.1 BETA	ensure drives on *both* i/f get initialized on boot
+ *			fix byte-swap problem with Mitsumi id_info
+ *			changed ide_timermask into ide_timerbit
+ *			get rid of unexpected interrupts after probing
+ *			don't wait for READY_STAT on cdrom drives
+ *  Version 3.2 BETA	Ooops.. mistakenly left VLB_32BIT_IDE on by default
+ *			new ide-cd.c from Scott
+ *  Version 3.3 BETA	fix compiling with PROBE_FOR_IRQS==0
+ *  (sent to Linus)	tweak in do_probe() to fix Delman's DRDY problem
+ *  Version 3.4 BETA	removed "444" debug message
+ *  (sent to Linus)
+ *  Version 3.5		correct the bios_cyl field if it's too small
+ *			 (to help fdisk with brain-dead BIOSs)
+ *
+ *  In progress:  special 32-bit controller-type detection & support
+ */
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/hdreg.h>
+#include <linux/genhd.h>
+#include <linux/config.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/major.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+
+/*****************************************************************************
+ * IDE driver configuration options (play with these as desired):
+ */
+
+#undef	REALLY_SLOW_IO			/* define if ide ports are very slow */
+#undef	REALLY_FAST_IO			/* define if ide ports are perfect */
+#undef	INITIAL_MULT_COUNT		/* define to override status quo */
+
+#ifndef VLB_32BIT_IDE			/* 0 for safety, 1 for 32-bit chipset:*/
+#define VLB_32BIT_IDE		0	/*   Winbond 83759F or OPTi 82C621 */
+#endif
+#ifndef DISK_RECOVERY_TIME		/* min. delay between IO for hardware */
+#define DISK_RECOVERY_TIME	0	/*  that needs it. */
+#endif
+#ifndef OK_TO_RESET_CONTROLLER		/* needed for good error recovery */
+#define OK_TO_RESET_CONTROLLER	1	/* 0 for use with AH2372A/B interface */
+#endif
+#ifndef SUPPORT_TWO_INTERFACES		/* 1 to support one/two interfaces */
+#define SUPPORT_TWO_INTERFACES	1	/* 0 for a smaller, faster kernel */
+#endif
+#ifndef OPTIMIZE_IRQS			/* 1 for slightly faster code */
+#define OPTIMIZE_IRQS		1	/* 0 to reduce kernel size */
+#endif
+#ifndef SUPPORT_SHARING_IRQ		/* 1 to allow two IDE i/f on one IRQ */
+#define SUPPORT_SHARING_IRQ	1	/* 0 to reduce kernel size */
+#endif
+#ifndef FANCY_STATUS_DUMPS		/* 1 for human-readable drive errors */
+#define FANCY_STATUS_DUMPS	1	/* 0 to reduce kernel size */
+#endif
+#define PROBE_FOR_IRQS		1	/* 0 to force use of defaults below */
+#define DEFAULT_IDE0_IRQ	14	/* in case irq-probe fails */
+#define DEFAULT_IDE1_IRQ	15	/* in case irq-probe fails */
+/*
+ *  "No user-serviceable parts" beyond this point  :)
+ ******************************************************************************
+ */
+
+/*
+ * Need to change these elsewhere in the kernel (someday)
+ */
+#ifndef IDE0_TIMER
+#define	IDE0_TIMER		HD_TIMER
+#define IDE1_TIMER		HD_TIMER2
+#endif
+
+#define IDE_DRIVE_CMD		99	/* some local magic */
+
+/*
+ * Ensure that various configuration flags have compatible settings
+ */
+#ifdef REALLY_SLOW_IO
+#undef REALLY_FAST_IO
+#endif
+#ifdef CONFIG_BLK_DEV_HD
+#undef  SUPPORT_TWO_INTERFACES
+#define SUPPORT_TWO_INTERFACES	0
+#endif	/* CONFIG_BLK_DEV_HD */
+#if SUPPORT_TWO_INTERFACES
+#define HWIF			hwif
+#define DEV_HWIF		(dev->hwif)
+#else
+#undef	OPTIMIZE_IRQS
+#define	OPTIMIZE_IRQS		0
+#undef	SUPPORT_SHARING_IRQ
+#define	SUPPORT_SHARING_IRQ	0
+#ifdef CONFIG_BLK_DEV_HD
+#define HWIF			1
+#else
+#define HWIF			0
+#endif	/* CONFIG_BLK_DEV_HD */
+#define DEV_HWIF		HWIF
+#endif	/* SUPPORT_TWO_INTERFACES */
+
+/*
+ * Definitions for accessing IDE controller registers
+ */
+typedef unsigned char		byte;	/* used everywhere */
+#define IDE_PORT(p,hwif) ((p)^((hwif)<<7)) /* IDE0: p^0x00 , IDE1: p^0x80 */
+
+#ifdef REALLY_FAST_IO
+#define OUT_BYTE(b,p)		outb((b),IDE_PORT(p,DEV_HWIF))
+#define IN_BYTE(p,hwif)		(byte)inb(IDE_PORT(p,hwif))
+#else
+#define OUT_BYTE(b,p)		outb_p((b),IDE_PORT(p,DEV_HWIF))
+#define IN_BYTE(p,hwif)		(byte)inb_p(IDE_PORT(p,hwif))
+#endif /* REALLY_FAST_IO */
+
+#if VLB_32BIT_IDE
+#define OUT_SECTORS(b,n)	outsl(IDE_PORT(HD_DATA,DEV_HWIF),(b),(n)<<7)
+#define IN_SECTORS(b,n)		insl(IDE_PORT(HD_DATA,DEV_HWIF),(b),(n)<<7)
+#else
+#define OUT_SECTORS(b,n)	outsw(IDE_PORT(HD_DATA,DEV_HWIF),(b),(n)<<8)
+#define IN_SECTORS(b,n)		insw(IDE_PORT(HD_DATA,DEV_HWIF),(b),(n)<<8)
+#endif	/* VLB_32BIT_IDE */
+
+#define GET_ERR(hwif)		IN_BYTE(HD_ERROR,hwif)
+#define GET_STAT(hwif)		IN_BYTE(HD_STATUS,hwif)
+#define OK_STAT(stat,good,bad)	(((stat)&((good)|(bad)))==(good))
+#define BAD_RW_STAT		(BUSY_STAT   | ERR_STAT  | WRERR_STAT)
+#define BAD_STAT		(BAD_RW_STAT | DRQ_STAT)
+#define DRIVE_READY		(READY_STAT  | SEEK_STAT)
+#define DATA_READY		(DRIVE_READY | DRQ_STAT)
+
+/*
+ * Some more useful definitions
+ */
+#define BIOS_SECTORS(dev)	(dev->bios_head*dev->bios_sect*dev->bios_cyl)
+#define HD_NAME		"hd"	/* the same for both i/f;  see also genhd.c */
+#define PARTN_BITS	6	/* number of minor dev bits for partitions */
+#define PARTN_MASK	((1<<PARTN_BITS)-1)	/* a useful bit mask */
+#define MAX_DRIVES	2	/* per interface; 2 assumed by lots of code */
+
+/*
+ * Timeouts for various operations:
+ */
+#define	WAIT_DRQ	3	/* 30msec - spec allows up to 20ms */
+#define WAIT_READY	3	/* 30msec - should be instantaneous */
+#define	WAIT_PIDENTIFY	50	/* 500msec - should be less than 3ms (?) */
+#define	WAIT_WORSTCASE	3000	/* 30sec  - worst case when spinning up */
+#define	WAIT_CMD	1000	/* 10sec  - maximum wait for an IRQ to happen */
+
+/*
+ * Now for the data we need to maintain per-device:  ide_dev_t
+ *
+ * For fast indexing, sizeof(ide_dev_t) = 32 = power_of_2;
+ * Everything is carefully aligned on appropriate boundaries,
+ *  and several fields are placed for optimal (gcc) access.
+ */
+typedef enum {disk, cdrom} dev_type;
+
+typedef union {
+	unsigned all			: 8;	/* all of the bits together */
+	struct {
+		unsigned set_geometry	: 1;	/* respecify drive geometry */
+		unsigned recalibrate	: 1;	/* seek to cyl 0      */
+		unsigned set_multmode	: 1;	/* set multmode count */
+		unsigned reserved	: 5;	/* unused */
+		} b;
+	} special_t;
+
+typedef union {
+	unsigned all			: 8;	/* all of the bits together */
+	struct {
+		unsigned head		: 4;	/* always zeros here */
+		unsigned drive		: 1;	/* drive number */
+		unsigned bit5		: 1;	/* always 1 */
+		unsigned lba		: 1;	/* LBA instead of CHS */
+		unsigned bit7		: 1;	/* always 1 */
+	} b;
+	} select_t;
+
+typedef struct {
+	byte     hwif;			/* first field gets very fast access */
+	byte     unmask;		/* pretty quick access to this also */
+	dev_type type		: 1;	/* disk or cdrom (or tape, floppy..) */
+	unsigned present	: 1;	/* drive is physically present */
+	unsigned keep_settings  : 1;	/* restore settings after drive reset */
+	unsigned busy		: 1;	/* mutex for ide_open, revalidate_.. */
+	unsigned reserved0	: 4;	/* unused */
+	special_t special;		/* special action flags */
+	select_t  select;		/* basic drive/head select reg value */
+	byte mult_count, reserved1, reserved2;
+	byte usage, mult_req, wpcom, ctl;
+	byte head, sect, bios_head, bios_sect;
+	unsigned short cyl, bios_cyl;
+	const char *name;
+	struct hd_driveid *id;
+	struct wait_queue *wqueue;
+	} ide_dev_t;
+
+/*
+ * Stuff prefixed by "ide_" is indexed by the IDE interface number: 0 or 1
+ */
+static const byte	ide_major    [2] = {IDE0_MAJOR,IDE1_MAJOR};
+static byte		ide_irq      [2] = {DEFAULT_IDE0_IRQ,DEFAULT_IDE1_IRQ};
+static struct hd_struct	ide_hd       [2][MAX_DRIVES<<PARTN_BITS] = {{{0,0},},};
+static int		ide_sizes    [2][MAX_DRIVES<<PARTN_BITS] = {{0,},};
+static int		ide_blksizes [2][MAX_DRIVES<<PARTN_BITS] = {{0,},};
+static unsigned long	ide_capacity [2][MAX_DRIVES] = {{0,},};
+static ide_dev_t	ide_dev      [2][MAX_DRIVES] = {{{0,},},};
+static ide_dev_t	*ide_cur_dev [2] = {NULL,NULL};
+static void		(*ide_handler[2])(ide_dev_t *) = {NULL,NULL};
+static struct request	*ide_cur_rq  [2] = {NULL,NULL}; /* current request */
+static struct request	ide_write_rq [2];  /* copy of *ide_cur_rq for WRITEs */
+static const int	ide_timer    [2] = {IDE0_TIMER,IDE1_TIMER};
+static const int	ide_timerbit[2] = {(1<<IDE0_TIMER),(1<<IDE1_TIMER)};
+static const char	*ide_name    [2] = {"ide0", "ide1"};
+static const char	*ide_devname [2][MAX_DRIVES] = /* for printk()'s */
+	{{HD_NAME "a", HD_NAME "b"}, {HD_NAME "c", HD_NAME "d"}};
+static const char	*unsupported = " not supported by this kernel\n";
+
+#if SUPPORT_SHARING_IRQ
+static byte		sharing_single_irq = 0;	/* for two i/f on one IRQ */
+static volatile byte 	current_hwif = 0;	/* for two i/f on one IRQ */
+#endif /* SUPPORT_SHARING_IRQ */
+
+/*
+ * This structure is used to register our block device(s) with the kernel:
+ */
+static void ide0_geninit(void), ide1_geninit(void);
+static struct gendisk	ide_gendisk  [2] =
+	{{
+		IDE0_MAJOR,	/* major number */	
+		HD_NAME,	/* same as below; see genhd.c before changing */
+		PARTN_BITS,	/* minor_shift (to extract minor number) */
+		1 << PARTN_BITS,/* max_p (number of partitions per real) */
+		MAX_DRIVES,	/* maximum number of real drives */
+		ide0_geninit,	/* init function */
+		ide_hd[0],	/* hd_struct */
+		ide_sizes[0],	/* block sizes */
+		0,		/* nr_real (number of drives present) */
+		ide_dev[0],	/* ptr to internal data structure */
+		NULL		/* next */
+	},{
+		IDE1_MAJOR,	/* major number */	
+		HD_NAME,	/* same as above; see genhd.c before changing */
+		PARTN_BITS,	/* minor_shift (to extract minor number) */
+		1 << PARTN_BITS,/* max_p (number of partitions per real) */
+		MAX_DRIVES,	/* maximum number of real drives */
+		ide1_geninit,	/* init function */
+		ide_hd[1],	/* hd_struct */
+		ide_sizes[1],	/* block sizes */
+		0,		/* nr_real (number of drives present) */
+		ide_dev[1],	/* ptr to internal data structure */
+		NULL		/* next */
+	}};
+
+/*
+ * One final include file, which references some of the data/defns from above
+ */
+#define	IDE_DRIVER	/* "parameter" for blk.h */
+#include "blk.h"
+
+/*
+ * For really screwy hardware (hey, at least it *can* be used with Linux!
+ */
+#if (DISK_RECOVERY_TIME > 0)
+static unsigned long	ide_lastreq[] = {0,0}; /* completion time of last I/O */
+#define SET_DISK_RECOVERY_TIMER  ide_lastreq[DEV_HWIF] = read_timer();
+static unsigned long read_timer(void)
+{
+	unsigned long t, flags;
+	int i;
+
+	save_flags(flags);
+	cli();
+	t = jiffies * 11932;
+    	outb_p(0, 0x43);
+	i = inb_p(0x40);
+	i |= inb(0x40) << 8;
+	restore_flags(flags);
+	return (t - i);
+}
+#else
+#define SET_DISK_RECOVERY_TIMER	/* nothing */
+#endif /* DISK_RECOVERY_TIME */
+
+/*
+ * The heart of the driver, referenced from lots of other routines:
+ */
+static void do_request (byte hwif);
+#define DO_REQUEST {SET_DISK_RECOVERY_TIMER do_request(DEV_HWIF);}
+
+/*
+ * This is a macro rather than an inline to permit better gcc code.
+ * Caller MUST do sti() before invoking WAIT_STAT() (for jiffies to work).
+ *
+ * This route should get fixed to not hog the cpu during extra long waits..
+ * That could be done by busy-waiting for the first jiffy or two, and then
+ * setting a timer to wake up at half second intervals thereafter,
+ * until WAIT_WORSTCASE is achieved, before timing out.
+ */
+#define WAIT_STAT(dev,good,bad,timeout,msg,label)			\
+{									\
+	byte stat;							\
+	udelay(1);	/* spec allows drive 400ns to assert "BUSY" */	\
+	if (GET_STAT(DEV_HWIF) & BUSY_STAT) {				\
+		unsigned long timer = jiffies + timeout;		\
+		do {							\
+			if ((GET_STAT(DEV_HWIF) & BUSY_STAT) == 0)	\
+				break;					\
+		} while (timer > jiffies);				\
+	}								\
+	udelay(1);	/* spec allows 400ns for status to stabilize */	\
+	if (!OK_STAT(stat=GET_STAT(DEV_HWIF), good, bad)) {		\
+		ide_error(dev, msg " error", stat);			\
+		goto label;						\
+	}								\
+}
+
+/*
+ * This should get invoked on every exit path from the driver.
+ */
+static inline void start_ide_timer (byte hwif)
+{
+	if (ide_handler[HWIF] != NULL) {  	/* waiting for an irq? */
+		timer_table[ide_timer[HWIF]].expires = jiffies + WAIT_CMD;
+		timer_active |= ide_timerbit[HWIF];
+	}
+}
+
+static void do_ide_reset (ide_dev_t *dev)
+{
+	byte tmp;
+	unsigned long timer, flags;
+
+	save_flags(flags);
+	sti();
+	for (tmp = 0; tmp < MAX_DRIVES; tmp++) {
+		ide_dev_t *rdev = &ide_dev[DEV_HWIF][tmp];
+		rdev->special.b.set_geometry = 1;
+		rdev->special.b.recalibrate  = 1;
+		rdev->special.b.set_multmode = 0;
+		if (OK_TO_RESET_CONTROLLER)
+			rdev->mult_count = 0;
+		if (!rdev->keep_settings) {
+			rdev->mult_req = 0;
+			rdev->unmask = 0;
+		}
+		if (rdev->mult_req != rdev->mult_count)
+			rdev->special.b.set_multmode = 1;
+	}
+
+#if OK_TO_RESET_CONTROLLER
+	cli();
+	OUT_BYTE(dev->ctl|6,HD_CMD);	/* set nIEN, set SRST */
+	udelay(10);			/* more than enough time */
+	OUT_BYTE(dev->ctl|2,HD_CMD);	/* clear SRST */
+	udelay(10);			/* more than enough time */
+	sti();				/* needed for jiffies */
+	for (timer = jiffies + WAIT_WORSTCASE; timer > jiffies;) {
+		if ((GET_STAT(DEV_HWIF) & BUSY_STAT) == 0)
+			break;
+	}
+	printk("%s: do_ide_reset: ", ide_name[DEV_HWIF]);
+	/* ATAPI devices usually do *not* assert READY after a reset */
+	if (!OK_STAT(tmp=GET_STAT(DEV_HWIF), 0, BUSY_STAT)) {
+		printk("timed out, status=0x%02x\n", tmp);
+	} else  {
+		if ((tmp = GET_ERR(DEV_HWIF)) == 1)
+			printk("success\n");
+		else {
+			printk("%s: ", ide_devname[DEV_HWIF][0]);
+			switch (tmp & 0x7f) {
+				case 1: printk("passed");
+					break;
+				case 2: printk("formatter device error");
+					break;
+				case 3: printk("sector buffer error");
+					break;
+				case 4: printk("ECC circuitry error");
+					break;
+				case 5: printk("controlling MPU error");
+					break;
+				default:printk("error (0x%02x?)", tmp);
+			}
+			if (tmp & 0x80)
+				printk("; %s: error", ide_devname[DEV_HWIF][1]);
+			printk("\n");
+		}
+	}
+#endif	/* OK_TO_RESET_CONTROLLER */
+	restore_flags(flags);
+}
+
+/*
+ * Clean up after success/failure of an explicit (ioctl) drive cmd
+ */
+static void end_drive_cmd (ide_dev_t *dev, byte stat, byte err)
+{
+	unsigned long flags;
+	struct request *rq = ide_cur_rq[DEV_HWIF];
+	byte *args = (byte *) rq->buffer;
+
+	rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+	if (args) {
+		args[0] = stat;
+		args[1] = err;
+		args[2] = IN_BYTE(HD_NSECTOR,DEV_HWIF);
+	}
+	save_flags(flags);
+	cli();
+	up(rq->sem);
+	ide_cur_rq[DEV_HWIF] = NULL;
+	restore_flags(flags);
+}
+
+/*
+ * Error reporting, in human readable form (luxurious, but a memory hog).
+ */
+static byte dump_status (byte hwif, const char *msg, byte stat)
+{
+	unsigned long flags;
+	byte err = 0;
+	ide_dev_t *dev = ide_cur_dev[HWIF];
+	const char *name = dev ? dev->name : ide_name[HWIF];
+
+	save_flags (flags);
+	sti();
+	printk("%s: %s: status=0x%02x", name, msg, stat);
+#if FANCY_STATUS_DUMPS
+	if (dev && dev->type == disk) {
+		printk(" { ");
+		if (stat & BUSY_STAT)
+			printk("Busy ");
+		else {
+			if (stat & READY_STAT)	printk("DriveReady ");
+			if (stat & WRERR_STAT)	printk("WriteFault ");
+			if (stat & SEEK_STAT)	printk("SeekComplete ");
+			if (stat & DRQ_STAT)	printk("DataRequest ");
+			if (stat & ECC_STAT)	printk("CorrectedError ");
+			if (stat & INDEX_STAT)	printk("Index ");
+			if (stat & ERR_STAT)	printk("Error ");
+		}
+		printk("}");
+	}
+#endif	/* FANCY_STATUS_DUMPS */
+	printk("\n");
+	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
+		err = GET_ERR(HWIF);
+		printk("%s: %s: error=0x%02x", name, msg, err);
+#if FANCY_STATUS_DUMPS
+		if (dev && dev->type == disk) {
+			printk(" { ");
+			if (err & BBD_ERR)	printk("BadSector ");
+			if (err & ECC_ERR)	printk("UncorrectableError ");
+			if (err & ID_ERR)	printk("SectorIdNotFound ");
+			if (err & ABRT_ERR)	printk("DriveStatusError ");
+			if (err & TRK0_ERR)	printk("TrackZeroNotFound ");
+			if (err & MARK_ERR)	printk("AddrMarkNotFound ");
+			printk("}");
+			if (err & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
+				byte cur = IN_BYTE(HD_CURRENT,HWIF);
+				if (cur & 0x40) {	/* using LBA? */
+					printk(", LBAsect=%ld", (unsigned long)
+					 ((cur&0xf)<<24)
+					 |(IN_BYTE(HD_HCYL,HWIF)<<16)
+					 |(IN_BYTE(HD_LCYL,HWIF)<<8)
+					 | IN_BYTE(HD_SECTOR,HWIF));
+				} else {
+					printk(", CHS=%d/%d/%d",
+					 (IN_BYTE(HD_HCYL,HWIF)<<8) +
+					  IN_BYTE(HD_LCYL,HWIF),
+					  cur & 0xf,
+					  IN_BYTE(HD_SECTOR,HWIF));
+				}
+				if (ide_cur_rq[HWIF])
+					printk(", sector=%ld", ide_cur_rq[HWIF]->sector);
+			}
+		}
+#endif	/* FANCY_STATUS_DUMPS */
+		printk("\n");
+	}
+	restore_flags (flags);
+	return err;
+}
+
+/*
+ * ide_error() takes action based on the error returned by the controller.
+ */
+#define ERROR_MAX	8	/* Max read/write errors per sector */
+#define ERROR_RESET	3	/* Reset controller every 4th retry */
+#define ERROR_RECAL	1	/* Recalibrate every 2nd retry */
+static void ide_error (ide_dev_t *dev, const char *msg, byte stat)
+{
+	struct request *rq;
+	byte err;
+
+	err = dump_status(DEV_HWIF, msg, stat);
+	if ((rq = ide_cur_rq[DEV_HWIF]) == NULL || dev == NULL)
+		return;
+	if (rq->cmd == IDE_DRIVE_CMD) {	/* never retry an explicit DRIVE_CMD */
+		end_drive_cmd(dev, stat, err);
+		return;
+	}
+	if (dev->type == disk && (stat & ERR_STAT)) {
+		/* err has different meaning on cdrom */
+		if (err & BBD_ERR)		/* retries won't help this! */
+			rq->errors = ERROR_MAX;
+		else if (err & TRK0_ERR)	/* help it find track zero */
+			rq->errors |= ERROR_RECAL;
+	}
+	if ((stat & DRQ_STAT) && rq->cmd == READ) {
+		int i = dev->mult_count ? dev->mult_count<<8 : 1<<8;
+		while (i-- > 0)			/* try to flush data */
+			(void) IN_BYTE(HD_DATA, dev->hwif);
+	}
+	if (GET_STAT(dev->hwif) & (BUSY_STAT|DRQ_STAT))
+		rq->errors |= ERROR_RESET;	/* Mmmm.. timing problem */
+
+	if (rq->errors >= ERROR_MAX)
+		end_request(0, DEV_HWIF);
+	else {
+		if ((rq->errors & ERROR_RESET) == ERROR_RESET)
+			do_ide_reset(dev);
+		else if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
+			dev->special.b.recalibrate = 1;
+		++rq->errors;
+	}
+}
+
+static void read_intr (ide_dev_t *dev)
+{
+	byte stat;
+	int i;
+	unsigned int msect, nsect;
+	struct request *rq;
+
+	if (!OK_STAT(stat=GET_STAT(DEV_HWIF),DATA_READY,BAD_RW_STAT)) {
+		sti();
+		ide_error(dev, "read_intr", stat);
+		DO_REQUEST;
+		return;
+	}
+	msect = dev->mult_count;
+read_next:
+	rq = ide_cur_rq[DEV_HWIF];
+	if (msect) {
+		if ((nsect = rq->current_nr_sectors) > msect)
+			nsect = msect;
+		msect -= nsect;
+	} else
+		nsect = 1;
+	IN_SECTORS(rq->buffer,nsect);
+#ifdef DEBUG
+	printk("%s:  read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n",
+		dev->name, rq->sector, rq->sector+nsect-1,
+		(unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
+#endif
+	rq->sector += nsect;
+	rq->buffer += nsect<<9;
+	rq->errors = 0;
+	i = (rq->nr_sectors -= nsect);
+	if ((rq->current_nr_sectors -= nsect) <= 0)
+		end_request(1, DEV_HWIF);
+	if (i > 0) {
+		if (msect)
+			goto read_next;
+		ide_handler[DEV_HWIF] = &read_intr;
+		return;
+	}
+	/* (void) GET_STAT(DEV_HWIF); */	/* hd.c did this */
+	DO_REQUEST;
+}
+
+static void write_intr (ide_dev_t *dev)
+{
+	byte stat;
+	int i;
+	struct request *rq = ide_cur_rq[DEV_HWIF];
+
+	if (OK_STAT(stat=GET_STAT(DEV_HWIF),DRIVE_READY,BAD_RW_STAT)) {
+#ifdef DEBUG
+		printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n",
+			dev->name, rq->sector, (unsigned long) rq->buffer,
+			rq->nr_sectors-1);
+#endif
+		if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) {
+			rq->sector++;
+			rq->buffer += 512;
+			rq->errors = 0;
+			i = --rq->nr_sectors;
+			--rq->current_nr_sectors;
+			if (rq->current_nr_sectors <= 0)
+				end_request(1, DEV_HWIF);
+			if (i > 0) {
+				ide_handler[DEV_HWIF] = &write_intr;
+				OUT_SECTORS(rq->buffer,1);
+				return;
+			}
+			DO_REQUEST;
+			return;
+		}
+	}
+	sti();
+	ide_error(dev, "write_intr", stat);
+	DO_REQUEST;
+}
+
+static void multwrite (ide_dev_t *dev)
+{
+	struct request *rq = &ide_write_rq[DEV_HWIF];
+	unsigned int mcount = dev->mult_count;
+
+	do {
+		unsigned int nsect = rq->current_nr_sectors;
+		if (nsect > mcount)
+			nsect = mcount;
+		mcount -= nsect;
+
+		OUT_SECTORS(rq->buffer,nsect);
+#ifdef DEBUG
+		printk("%s: multwrite: sector %ld, buffer=0x%08lx, count=%d, remaining=%ld\n",
+			dev->name, rq->sector, (unsigned long) rq->buffer,
+			nsect, rq->nr_sectors - nsect);
+#endif
+		if ((rq->nr_sectors -= nsect) <= 0)
+			break;
+		if ((rq->current_nr_sectors -= nsect) == 0) {
+			if ((rq->bh = rq->bh->b_reqnext) != NULL) {
+				rq->current_nr_sectors = rq->bh->b_size>>9;
+				rq->buffer             = rq->bh->b_data;
+			} else {
+				panic("%s: buffer list corrupted\n", dev->name);
+				break;
+			}
+		} else {
+			rq->buffer += nsect << 9;
+		}
+	} while (mcount);
+}
+
+static void multwrite_intr (ide_dev_t *dev)
+{
+	byte stat;
+	int i;
+	struct request *rq = &ide_write_rq[DEV_HWIF];
+
+	if (OK_STAT(stat=GET_STAT(DEV_HWIF),DRIVE_READY,BAD_RW_STAT)) {
+		if (stat & DRQ_STAT) {
+			if (rq->nr_sectors) {
+				if (dev->mult_count)
+					multwrite(dev);
+				ide_handler[DEV_HWIF] = &multwrite_intr;
+				return;
+			}
+		} else {
+			if (!rq->nr_sectors) {	/* all done? */
+				rq = ide_cur_rq[DEV_HWIF];
+				for (i = rq->nr_sectors; i > 0;){
+					i -= rq->current_nr_sectors;
+					end_request(1, DEV_HWIF);
+				}
+				DO_REQUEST;
+				return;
+			}
+		}
+	}
+	sti();
+	ide_error(dev, "multwrite_intr", stat);
+	DO_REQUEST;
+}
+
+/*
+ * Issue a simple drive command
+ * The drive must be selected beforehand.
+ */
+static inline void ide_cmd(ide_dev_t *dev, byte cmd, byte nsect,
+				void (*handler)(ide_dev_t *dev))
+{
+	OUT_BYTE(dev->ctl,HD_CMD);
+	OUT_BYTE(nsect,HD_NSECTOR);
+	OUT_BYTE(cmd,HD_COMMAND);
+	ide_handler[DEV_HWIF] = handler;
+}
+
+static void set_multmode_intr (ide_dev_t *dev)
+{
+	byte stat = GET_STAT(DEV_HWIF);
+
+	sti();
+	if (!OK_STAT(stat,READY_STAT,BAD_STAT)) {
+		dev->mult_req = dev->mult_count = 0;
+		dev->special.b.recalibrate = 1;
+		(void) dump_status(DEV_HWIF, "set_multmode", stat);
+	} else {
+		if ((dev->mult_count = dev->mult_req))
+			printk ("  %s: enabled %d-sector multiple mode\n",
+				dev->name, dev->mult_count);
+		else
+			printk ("  %s: disabled multiple mode\n", dev->name);
+	}
+	DO_REQUEST;
+}
+
+static void set_geometry_intr (ide_dev_t *dev)
+{
+	byte stat = GET_STAT(DEV_HWIF);
+
+	sti();
+	if (!OK_STAT(stat,READY_STAT,BAD_STAT))
+		ide_error(dev, "set_geometry_intr", stat);
+	DO_REQUEST;
+}
+
+static void recal_intr (ide_dev_t *dev)
+{
+	byte stat = GET_STAT(DEV_HWIF);
+
+	sti();
+	if (!OK_STAT(stat,READY_STAT,BAD_STAT))
+		ide_error(dev, "recal_intr", stat);
+	DO_REQUEST;
+}
+
+static void drive_cmd_intr (ide_dev_t *dev)
+{
+	byte stat = GET_STAT(DEV_HWIF);
+
+	sti();
+	if (!OK_STAT(stat,READY_STAT,BAD_STAT))
+		ide_error(dev, "drive_cmd", stat); /* calls end_drive_cmd() */
+	else
+		end_drive_cmd (dev, stat, GET_ERR(DEV_HWIF));
+	DO_REQUEST;
+}
+
+static void timer_expiry (byte hwif)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+
+	if (ide_handler[HWIF] == NULL || (timer_active & ide_timerbit[HWIF])) {
+		/* The drive must have responded just as the timer expired */
+		sti();
+		printk("%s: marginal timeout\n", ide_name[HWIF]);
+	} else {
+		ide_handler[HWIF] = NULL;
+		disable_irq(ide_irq[HWIF]);
+		sti();
+		ide_error(ide_cur_dev[HWIF], "timeout", GET_STAT(HWIF));
+		do_request(HWIF);
+#if SUPPORT_SHARING_IRQ
+		if (sharing_single_irq)	/* this line is indeed necessary */
+			hwif = current_hwif;
+#endif /* SUPPORT_SHARING_IRQ */
+		cli();
+		start_ide_timer(HWIF);
+		enable_irq(ide_irq[HWIF]);
+	}
+	restore_flags(flags);
+}
+
+static void ide0_timer_expiry (void)		/* invoked from sched.c */
+{
+	timer_expiry (0);
+}
+
+static void ide1_timer_expiry (void)		/* invoked from sched.c */
+{
+	timer_expiry (1);
+}
+
+static int do_special (ide_dev_t *dev)
+{
+	special_t *s = &dev->special;
+#ifdef DEBUG
+	printk("%s: do_special: 0x%02x\n", dev->name, s->all);
+#endif
+	if (s->b.set_geometry) {
+		s->b.set_geometry = 0;
+		if (dev->type == disk) {
+			OUT_BYTE(dev->sect,HD_SECTOR);
+			OUT_BYTE(dev->cyl,HD_LCYL);
+			OUT_BYTE(dev->cyl>>8,HD_HCYL);
+			OUT_BYTE(((dev->head-1)|dev->select.all)&0xBF,HD_CURRENT);
+			ide_cmd(dev, WIN_SPECIFY, dev->sect, &set_geometry_intr);
+		}
+	} else if (s->b.recalibrate) {
+		s->b.recalibrate = 0;
+		if (dev->type == disk)
+			ide_cmd(dev,WIN_RESTORE,dev->sect,&recal_intr);
+	} else if (s->b.set_multmode) {
+		if (dev->id && dev->id->max_multsect && dev->type == disk) {
+			if (dev->mult_req > dev->id->max_multsect)
+				dev->mult_req = dev->id->max_multsect;
+			if (dev->mult_req != dev->mult_count)
+				ide_cmd(dev,WIN_SETMULT,dev->mult_req,&set_multmode_intr);
+		} else {
+			dev->mult_req = 0;
+			printk("%s: multmode not supported by this device\n", dev->name);
+		}
+		s->b.set_multmode = 0;
+	} else {
+		if (s->all) {
+			printk("%s: bad special flag: 0x%02x\n", dev->name, s->all);
+			s->all = 0;
+		}
+	}
+	return (ide_handler[DEV_HWIF] == NULL) ? 1 : 0;
+}
+
+#ifdef CONFIG_BLK_DEV_IDECD
+static byte wait_stat (ide_dev_t *dev, byte good, byte bad, unsigned long timeout)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	sti();
+	WAIT_STAT(dev, good, bad, timeout, "status", error);
+	restore_flags(flags);
+	return 0;
+error:
+	restore_flags(flags);
+	return 1;
+}
+
+#include "ide-cd.c"
+#endif	/* CONFIG_BLK_DEV_IDECD */
+
+static inline int do_rw_disk (ide_dev_t *dev, struct request *rq, unsigned long block)
+{
+	OUT_BYTE(dev->ctl,HD_CMD);
+	OUT_BYTE(rq->nr_sectors,HD_NSECTOR);
+	if (dev->select.b.lba) {
+#ifdef DEBUG
+		printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",
+			dev->name, (rq->cmd==READ)?"read":"writ", 
+			block, rq->nr_sectors, (unsigned long) rq->buffer);
+#endif
+		OUT_BYTE(block,HD_SECTOR);
+		OUT_BYTE(block>>=8,HD_LCYL);
+		OUT_BYTE(block>>=8,HD_HCYL);
+		OUT_BYTE(((block>>8)&0x0f)|dev->select.all,HD_CURRENT);
+	} else {
+		unsigned int sect,head,cyl,track;
+		track = block / dev->sect;
+		sect  = block % dev->sect + 1;
+		OUT_BYTE(sect,HD_SECTOR);
+		head  = track % dev->head;
+		cyl   = track / dev->head;
+		OUT_BYTE(cyl,HD_LCYL);
+		OUT_BYTE(cyl>>8,HD_HCYL);
+		OUT_BYTE(head|dev->select.all,HD_CURRENT);
+#ifdef DEBUG
+		printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n",
+			dev->name, (rq->cmd==READ)?"read":"writ", cyl,
+			head, sect, rq->nr_sectors, (unsigned long) rq->buffer);
+#endif
+	}
+	if (rq->cmd == READ) {
+		OUT_BYTE(dev->mult_count ? WIN_MULTREAD : WIN_READ, HD_COMMAND);
+		ide_handler[DEV_HWIF] = &read_intr;
+		return 0;
+	}
+	if (rq->cmd == WRITE) {
+		OUT_BYTE(dev->wpcom,HD_PRECOMP);	/* for ancient drives */
+		OUT_BYTE(dev->mult_count ? WIN_MULTWRITE : WIN_WRITE, HD_COMMAND);
+		WAIT_STAT(dev, DATA_READY, BAD_RW_STAT, WAIT_DRQ, "DRQ", error);
+		if (!dev->unmask)
+			cli();
+		if (dev->mult_count) {
+			ide_write_rq[DEV_HWIF] = *rq; /* scratchpad */
+			multwrite(dev);
+			ide_handler[DEV_HWIF] = &multwrite_intr;
+		} else {
+			OUT_SECTORS(rq->buffer,1);
+			ide_handler[DEV_HWIF] = &write_intr;
+		}
+		return 0;
+	}
+#ifdef IDE_DRIVE_CMD
+	if (rq->cmd == IDE_DRIVE_CMD) {
+		byte *args = rq->buffer;
+		if (args) {
+			OUT_BYTE(args[2],HD_FEATURE);
+			ide_cmd(dev, args[0], args[1], &drive_cmd_intr);
+			printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x\n",
+			 dev->name, args[0], args[1], args[2]);
+			return 0;
+		} else {
+#ifdef DEBUG
+			printk("%s: DRIVE_CMD (null)\n", dev->name);
+#endif
+			end_drive_cmd(dev,GET_STAT(DEV_HWIF),GET_ERR(DEV_HWIF));
+			return 1;
+		}
+	}
+#endif	/* IDE_DRIVE_CMD */
+	printk("%s: bad command: %d\n", dev->name, rq->cmd);
+	end_request(0, DEV_HWIF);
+error:
+	return 1;
+}
+
+/*
+ * The driver enables interrupts as much as possible.  In order to do this,
+ * (a) the device-interrupt is always masked before entry, and
+ * (b) the timeout-interrupt is always disabled before entry.
+ *
+ * Interrupts are still masked (by default) whenever we are exchanging
+ * data/cmds with a drive, because some drives seem to have very poor
+ * tolerance for latency during I/O.  For devices which don't suffer from
+ * this problem (most don't), the ide_dev[][].unmask flag can be set to permit
+ * other interrupts during data/cmd transfers by using the "hdparm" utility.
+ */
+static void do_request (byte hwif)
+{
+	unsigned int minor, drive;
+	unsigned long block, blockend;
+	struct request *rq;
+	ide_dev_t *dev;
+repeat:
+	sti();
+#if SUPPORT_SHARING_IRQ
+	current_hwif = hwif;	/* used *only* when sharing_single_irq==1 */
+#endif /* SUPPORT_SHARING_IRQ */
+	if ((rq = ide_cur_rq[HWIF]) == NULL) {
+		rq = blk_dev[ide_major[HWIF]].current_request;
+		if ((rq == NULL) || (rq->dev < 0)) {
+#if SUPPORT_SHARING_IRQ
+			if (sharing_single_irq) {
+				if ((dev = ide_cur_dev[hwif])) /* disable irq */
+					OUT_BYTE(dev->ctl|2,HD_CMD);
+				rq = blk_dev[ide_major[hwif^=1]].current_request;
+				if ((rq != NULL) && (rq->dev >= 0))
+					goto repeat;
+			}
+#endif /* SUPPORT_SHARING_IRQ */
+			return;
+		}
+		blk_dev[ide_major[HWIF]].current_request = rq->next;
+		ide_cur_rq[HWIF] = rq;
+	}
+#ifdef DEBUG
+	printk("%s: do_request: current=0x%08lx\n",ide_name[HWIF],(unsigned long)rq);
+#endif
+	minor = MINOR(rq->dev);
+	drive = minor >> PARTN_BITS;
+	ide_cur_dev[HWIF] = dev = &ide_dev[HWIF][drive];
+	if ((MAJOR(rq->dev) != ide_major[HWIF]) || (drive >= MAX_DRIVES)) {
+		printk("%s: bad device number: 0x%04x\n", ide_name[HWIF], rq->dev);
+		end_request(0, HWIF);
+		goto repeat;
+	}
+	if (rq->bh && !rq->bh->b_lock) {
+		printk("%s: block not locked\n", ide_name[HWIF]);
+		end_request(0, HWIF);
+		goto repeat;
+	}
+	block    = rq->sector;
+	blockend = block + rq->nr_sectors;
+	if ((blockend < block) || (blockend > ide_hd[HWIF][minor].nr_sects)) {
+		printk("%s: bad access: block=%ld, count=%ld\n",
+			dev->name, block, rq->nr_sectors);
+		end_request(0, HWIF);
+		goto repeat;
+	}
+	block += ide_hd[HWIF][minor].start_sect;
+#if (DISK_RECOVERY_TIME > 0)
+	while ((read_timer() - ide_lastreq[HWIF]) < DISK_RECOVERY_TIME);
+#endif
+	OUT_BYTE(dev->select.all,HD_CURRENT);
+#ifdef CONFIG_BLK_DEV_IDECD
+	WAIT_STAT(dev, (dev->type == cdrom) ? 0 : READY_STAT,
+		BUSY_STAT|DRQ_STAT, WAIT_READY, "DRDY", repeat);
+#else
+	WAIT_STAT(dev, READY_STAT, BUSY_STAT|DRQ_STAT, WAIT_READY, "DRDY", repeat);
+#endif	/* CONFIG_BLK_DEV_IDECD */
+	if (!dev->special.all) {
+#ifdef CONFIG_BLK_DEV_IDECD
+		if (dev->type == disk) {
+#endif	/* CONFIG_BLK_DEV_IDECD */
+			if (do_rw_disk(dev, rq, block))
+				goto repeat;
+#ifdef CONFIG_BLK_DEV_IDECD
+		} else {
+			if (do_rw_cdrom(dev, block))
+				goto repeat;
+		}
+#endif	/* CONFIG_BLK_DEV_IDECD */
+	} else {
+		if (do_special(dev))
+			goto repeat;
+	}
+}
+
+/*
+ * This is a macro rather than an inline function to
+ * prevent gcc from over-optimizing accesses to current_hwif,
+ * which may have a different value on exit from do_request().
+ */
+#define DO_IDE_REQUEST(hwif)			\
+{						\
+	if (ide_handler[hwif] == NULL) {	\
+		disable_irq(ide_irq[hwif]);	\
+		do_request(hwif);		\
+		cli();				\
+		start_ide_timer(hwif);		\
+		enable_irq(ide_irq[hwif]);	\
+	}					\
+}
+
+#if SUPPORT_TWO_INTERFACES
+static void do_ide0_request (void)	/* invoked with cli() */
+{
+	DO_IDE_REQUEST(0);
+}
+
+static void do_ide1_request (void)	/* invoked with cli() */
+{
+	DO_IDE_REQUEST(1);
+}
+#else
+#define do_ide1_request	do_ide0_request
+static void do_ide0_request (void)	/* invoked with cli() */
+{
+	DO_IDE_REQUEST(HWIF);
+}
+#endif	/* SUPPORT_TWO_INTERFACES */
+
+#if SUPPORT_SHARING_IRQ
+static void do_shared_request (void)	/* invoked with cli() */
+{
+	DO_IDE_REQUEST(current_hwif);
+}
+#endif /* SUPPORT_SHARING_IRQ */
+
+/*
+ * There's nothing really useful we can do with an unexpected interrupt,
+ * other than reading the status register (to clear it), and logging it.
+ * There should be no way that an irq can happen before we're ready for it,
+ * so we needn't worry much about losing an "important" interrupt here.
+ *
+ * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
+ * drive enters "idle", "standby", or "sleep" mode, so if the status looks
+ * "good", we just ignore the interrupt completely.
+ */
+static void unexpected_intr (byte hwif)
+{
+	byte stat;
+
+	if (!OK_STAT(stat=GET_STAT(HWIF), DRIVE_READY, BAD_STAT))
+		(void) dump_status(HWIF, "unexpected_intr", stat);
+#if SUPPORT_SHARING_IRQ
+	if (sharing_single_irq) {
+		if (!OK_STAT(stat=GET_STAT(hwif^1), DRIVE_READY, BAD_STAT))
+			(void) dump_status(hwif^1, "unexpected_intr", stat);
+	}
+#endif /* SUPPORT_SHARING_IRQ */
+}
+
+/*
+ * This is a macro rather than an inline function to
+ * prevent gcc from over-optimizing accesses to current_hwif,
+ * which may have a different value on exit from handler().
+ */
+#define IDE_INTR(hwif)					\
+{							\
+	ide_dev_t *dev;					\
+	void (*handler)(ide_dev_t *);			\
+							\
+	timer_active &= ~ide_timerbit[hwif];		\
+	if ((handler = ide_handler[hwif]) != NULL) {	\
+		ide_handler[hwif] = NULL;		\
+		dev = ide_cur_dev[hwif];		\
+		if (dev->unmask)			\
+			sti();				\
+		handler(dev);				\
+	} else						\
+		unexpected_intr(hwif);			\
+	cli();						\
+	start_ide_timer(hwif);				\
+}
+
+#if OPTIMIZE_IRQS
+
+/* entry point for all interrupts on ide0 when sharing_single_irq==0 */
+static void ide0_intr (int irq)
+{
+	IDE_INTR(0);
+}
+
+/* entry point for all interrupts on ide1 when sharing_single_irq==0 */
+static void ide1_intr (int irq)
+{
+	IDE_INTR(1);
+}
+
+#else	/* OPTIMIZE_IRQS */
+
+#define ide0_intr	ide_intr
+#define ide1_intr	ide_intr
+
+/* entry point for all interrupts when sharing_single_irq==0 */
+static void ide_intr (int irq)
+{
+#if SUPPORT_TWO_INTERFACES
+	byte hwif = (irq != ide_irq[0]);
+#endif	/* SUPPORT_TWO_INTERFACES */
+	IDE_INTR(HWIF);
+}
+
+#endif	/* OPTIMIZE_IRQS */
+
+#if SUPPORT_SHARING_IRQ
+/* entry point for all interrupts on ide0/ide1 when sharing_single_irq==1 */
+static void ide_shared_intr (int irq)
+{
+	IDE_INTR(current_hwif);
+}
+#endif /* SUPPORT_SHARING_IRQ */
+
+static ide_dev_t *get_info_ptr (int i_rdev)
+{
+	unsigned int drive = DEVICE_NR(i_rdev);
+	ide_dev_t *dev;
+
+	if (drive < MAX_DRIVES) {
+		switch (MAJOR(i_rdev)) {
+			case IDE0_MAJOR:	dev = &ide_dev[0][drive];
+						if (dev->present) return dev;
+						break;
+			case IDE1_MAJOR:	dev = &ide_dev[1][drive];
+						if (dev->present) return dev;
+						break;
+		}
+	}
+	return NULL;
+}
+
+static int ide_open(struct inode * inode, struct file * filp)
+{
+	ide_dev_t *dev;
+	unsigned long flags;
+
+	if ((dev = get_info_ptr(inode->i_rdev)) == NULL)
+		return -ENODEV;
+	save_flags(flags);
+	cli();
+	while (dev->busy)
+		sleep_on(&dev->wqueue);
+	dev->usage++;
+	restore_flags(flags);
+#ifdef CONFIG_BLK_DEV_IDECD
+	if (dev->type == cdrom)
+		return cdrom_open (inode, filp, dev);
+#endif	/* CONFIG_BLK_DEV_IDECD */
+	return 0;
+}
+
+/*
+ * Releasing a block device means we sync() it, so that it can safely
+ * be forgotten about...
+ */
+static void ide_release(struct inode * inode, struct file * file)
+{
+	ide_dev_t *dev;
+
+	if ((dev = get_info_ptr(inode->i_rdev)) != NULL) {
+		sync_dev(inode->i_rdev);
+		dev->usage--;
+#ifdef CONFIG_BLK_DEV_IDECD
+		if (dev->type == cdrom)
+			cdrom_release (inode, file, dev);
+#endif	/* CONFIG_BLK_DEV_IDECD */
+	}
+}
+
+/*
+ * This routine is called to flush all partitions and partition tables
+ * for a changed disk, and then re-read the new partition table.
+ * If we are revalidating a disk because of a media change, then we
+ * enter with usage == 0.  If we are using an ioctl, we automatically have
+ * usage == 1 (we need an open channel to use an ioctl :-), so this
+ * is our limit.
+ */
+static int revalidate_disk(int i_rdev)
+{
+	unsigned int i, major, start, drive = DEVICE_NR(i_rdev);
+	ide_dev_t *dev;
+	struct gendisk *gd;
+	long flags;
+
+	if ((dev = get_info_ptr(i_rdev)) == NULL)
+		return -ENODEV;
+
+	save_flags(flags);
+	cli();
+	if (dev->busy || (dev->usage > 1)) {
+		restore_flags(flags);
+		return -EBUSY;
+	};
+	dev->busy = 1;
+	restore_flags(flags);
+
+	gd    = &ide_gendisk[DEV_HWIF];
+	major = ide_major[DEV_HWIF] << 8;
+	start = drive << PARTN_BITS;
+
+	for (i = 0; i < (1<<PARTN_BITS); i++) {
+		unsigned int minor = start + i;
+		sync_dev           (major | minor);
+		invalidate_inodes  (major | minor);
+		invalidate_buffers (major | minor);
+		gd->part[minor].start_sect = 0;
+		gd->part[minor].nr_sects   = 0;
+	};
+
+	gd->part[start].nr_sects = ide_capacity[DEV_HWIF][drive];
+	resetup_one_dev(gd, drive);
+
+	dev->busy = 0;
+	wake_up(&dev->wqueue);
+	return 0;
+}
+
+/*
+ * This function issues a specific IDE drive command onto the
+ * tail of the request queue, and waits for it to be completed.
+ * If arg is NULL, it goes through all the motions,
+ * but without actually sending a command to the drive.
+ */
+static int do_drive_cmd(int dev, char *args)
+{
+	unsigned long flags;
+	unsigned int major = MAJOR(dev);
+	struct request rq, *cur_rq;
+	struct blk_dev_struct *bdev;
+	struct semaphore sem = MUTEX_LOCKED;
+
+	/* build up a special request, and add it to the queue */
+	rq.buffer = args;
+	rq.cmd = IDE_DRIVE_CMD;
+	rq.errors = 0;
+	rq.sector = 0;
+	rq.nr_sectors = 0;
+	rq.current_nr_sectors = 0;
+	rq.sem = &sem;
+	rq.bh = NULL;
+	rq.bhtail = NULL;
+	rq.next = NULL;
+	rq.dev = dev;
+	bdev = &blk_dev[major];
+
+	save_flags(flags);
+	cli();
+	cur_rq = bdev->current_request;
+	if (cur_rq == NULL) {			/* empty request list? */
+		bdev->current_request = &rq;	/* service ours immediately */
+		bdev->request_fn();
+	} else {
+		while (cur_rq->next != NULL)	/* find end of request list */
+			cur_rq = cur_rq->next;
+		cur_rq->next = &rq;		/* add rq to the end */
+	}
+
+	down(&sem);				/* wait for it to be serviced */
+	restore_flags(flags);
+	return rq.errors ? -EIO : 0;		/* return -EIO if errors */
+}
+
+static int write_fs_long (unsigned long useraddr, long value)
+{
+	int err;
+
+	if (NULL == (long *)useraddr)
+		return -EINVAL;
+	if ((err = verify_area(VERIFY_WRITE, (long *)useraddr, sizeof(long))))
+		return err;
+	put_fs_long((unsigned)value, (long *) useraddr);
+	return 0;
+}
+
+static int ide_ioctl (struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	struct hd_geometry *loc = (struct hd_geometry *) arg;
+	int err;
+	ide_dev_t *dev;
+	unsigned long flags;
+
+	if (!inode || !inode->i_rdev)
+		return -EINVAL;
+	if ((dev = get_info_ptr(inode->i_rdev)) == NULL)
+		return -ENODEV;
+	switch (cmd) {
+		case HDIO_GETGEO:
+			if (!loc || dev->type != disk) return -EINVAL;
+			err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
+			if (err) return err;
+			put_fs_byte(dev->bios_head,
+				(char *) &loc->heads);
+			put_fs_byte(dev->bios_sect,
+				(char *) &loc->sectors);
+			put_fs_word(dev->bios_cyl,
+				(short *) &loc->cylinders);
+			put_fs_long((unsigned)ide_hd[DEV_HWIF][MINOR(inode->i_rdev)].start_sect,
+				(long *) &loc->start);
+			return 0;
+
+		case BLKFLSBUF:
+			if(!suser()) return -EACCES;
+			fsync_dev(inode->i_rdev);
+			invalidate_buffers(inode->i_rdev);
+			return 0;
+
+		case BLKRASET:
+			if(!suser()) return -EACCES;
+			if(arg > 0xff) return -EINVAL;
+			read_ahead[MAJOR(inode->i_rdev)] = arg;
+			return 0;
+
+		case BLKRAGET:
+			return write_fs_long(arg, read_ahead[MAJOR(inode->i_rdev)]);
+
+         	case BLKGETSIZE:   /* Return device size */
+			return write_fs_long(arg, ide_hd[DEV_HWIF][MINOR(inode->i_rdev)].nr_sects);
+		case BLKRRPART: /* Re-read partition tables */
+			return revalidate_disk(inode->i_rdev);
+
+                case HDIO_GET_KEEPSETTINGS:
+			return write_fs_long(arg, dev->keep_settings);
+
+                case HDIO_GET_UNMASKINTR:
+			return write_fs_long(arg, dev->unmask);
+
+                case HDIO_GET_MULTCOUNT:
+			return write_fs_long(arg, dev->mult_count);
+
+		case HDIO_GET_IDENTITY:
+			if (!arg || (MINOR(inode->i_rdev) & PARTN_MASK))
+				return -EINVAL;
+			if (dev->id == NULL)
+				return -ENOMSG;
+			err = verify_area(VERIFY_WRITE, (char *)arg, sizeof(*dev->id));
+			if (err) return err;
+			memcpy_tofs((char *)arg, (char *)dev->id, sizeof(*dev->id));
+			return 0;
+
+		case HDIO_SET_KEEPSETTINGS:
+			if (!suser()) return -EACCES;
+			if ((arg > 1) || (MINOR(inode->i_rdev) & PARTN_MASK))
+				return -EINVAL;
+			save_flags(flags);
+			cli();
+			dev->keep_settings = arg;
+			restore_flags(flags);
+			return 0;
+
+		case HDIO_SET_UNMASKINTR:
+			if (!suser()) return -EACCES;
+			if ((arg > 1) || (MINOR(inode->i_rdev) & PARTN_MASK))
+				return -EINVAL;
+			save_flags(flags);
+			cli();
+			dev->unmask = arg;
+			restore_flags(flags);
+			return 0;
+
+		case HDIO_SET_MULTCOUNT:
+			if (!suser()) return -EACCES;
+			if (MINOR(inode->i_rdev) & PARTN_MASK)
+				return -EINVAL;
+			if ((dev->id == NULL) || (arg > dev->id->max_multsect))
+				return -EINVAL;
+			save_flags(flags);
+			cli();
+			if (dev->special.b.set_multmode) {
+				restore_flags(flags);
+				return -EBUSY;
+			}
+			dev->mult_req = arg;
+			dev->special.b.set_multmode = 1;
+			restore_flags(flags);
+			do_drive_cmd (inode->i_rdev, NULL);
+			return (dev->mult_count == arg) ? 0 : -EIO;
+
+#ifdef IDE_DRIVE_CMD
+		case HDIO_DRIVE_CMD:
+		{
+			unsigned long args;
+
+			if (NULL == (long *) arg)
+				err = do_drive_cmd(inode->i_rdev,NULL);
+			else {
+				if (!(err = verify_area(VERIFY_WRITE,(long *)arg,sizeof(long))))
+				{
+					args = get_fs_long((long *)arg);
+					err = do_drive_cmd(inode->i_rdev,(char *)&args);
+					put_fs_long(args,(long *)arg);
+				}
+			}
+			return err;
+		}
+#endif /* IDE_DRIVE_CMD */
+
+		RO_IOCTLS(inode->i_rdev, arg);
+
+		default:
+#ifdef CONFIG_BLK_DEV_IDECD
+			if (dev->type == cdrom)
+				return ide_cdrom_ioctl(dev, inode, file, cmd, arg);
+#endif /* CONFIG_BLK_DEV_IDECD */
+			return -EPERM;
+	}
+}
+
+#ifdef CONFIG_BLK_DEV_IDECD
+static int ide_check_media_change (dev_t full_dev)
+{
+	ide_dev_t *dev;
+
+	if ((dev = get_info_ptr(full_dev)) == NULL)
+		return -ENODEV;
+	if (dev->type != cdrom)
+		return 0;
+	return cdrom_check_media_change (dev);
+}
+#endif	/* CONFIG_BLK_DEV_IDECD */
+
+
+static void fixstring (byte *s, int bytecount, int byteswap)
+{
+	byte *p, *end = &s[bytecount &= ~1];	/* bytecount must be even */
+
+	if (byteswap) {
+		/* convert from big-endian to little-endian */
+		for (p = end ; p != s;) {
+			unsigned short *pp = (unsigned short *) (p -= 2);
+			*pp = (*pp >> 8) | (*pp << 8);
+		}
+	}
+	p = s;
+
+	/* strip leading blanks */
+	while (s != end && *s == ' ')
+		++s;
+
+	/* compress internal blanks and strip trailing blanks */
+	while (s != end && *s) {
+		if (*s++ != ' ' || (s != end && *s && *s != ' '))
+			*p++ = *(s-1);
+	}
+
+	/* wipe out trailing garbage */
+	while (p != end)
+		*p++ = '\0';
+}
+
+static unsigned long fix_lba_capacity (struct hd_driveid *id)
+{
+	unsigned long lba_sects   = id->lba_capacity;
+	unsigned long chs_sects   = id->cyls * id->heads * id->sectors;
+	unsigned long _15_percent = chs_sects / 10;
+
+	/* perform a rough sanity check on lba_sects:  within 15% is "okay" */
+	if ((lba_sects - chs_sects) < _15_percent)
+		return lba_sects;
+
+	/* some drives have the word order reversed */
+	lba_sects = (lba_sects << 16) | (lba_sects >> 16);
+	if ((lba_sects - chs_sects) < _15_percent)
+		return (id->lba_capacity = lba_sects);
+
+	/* play it safe and assume lba capacity is the same as chs capacity */
+	return chs_sects;
+}
+
+static unsigned long probe_mem_start;	/* used by drive/irq probing routines */
+
+static void do_identify (ide_dev_t *dev)
+{
+	int bswap;
+	struct hd_driveid *id;
+	unsigned long capacity, check;
+
+	id = dev->id = (struct hd_driveid *) probe_mem_start; /* kmalloc() */
+	probe_mem_start += 512;
+	IN_SECTORS(id,1);	/* read 512 bytes of id info */
+	sti();
+
+	/*
+	 * Everything except ATAPI seems to use big-endian string ordering,
+	 * whereas the NEC and Vertos ATAPI drives both use little-endian.
+	 * Latest reports indicate that some Mitsumi ATAPI use big-endian.
+	 */
+	bswap = (id->config & 0x8000) ? 0 : 1;
+	if (bswap && id->model[0] == 'F' && id->model[1] == 'X')
+		bswap = 0; 
+	fixstring (id->serial_no, sizeof(id->serial_no), bswap);
+	fixstring (id->fw_rev,    sizeof(id->fw_rev),    bswap);
+	fixstring (id->model,     sizeof(id->model),     bswap);
+
+	/*
+	 * Check for ATAPI device (such as an NEC-260 IDE cdrom drive)
+	 */
+	if (id->config & 0x8000) {
+#ifdef CONFIG_BLK_DEV_IDECD
+		byte type = (id->config >> 8) & 0x0f;
+#endif	/* CONFIG_BLK_DEV_IDECD */
+		printk("%s: %s, ATAPI,", dev->name, id->model);
+#ifdef CONFIG_BLK_DEV_IDECD
+		if (type == 0 || type == 5)
+			printk(" CDROM drive\n");
+		else
+			printk(" UNKNOWN device\n");
+		dev->type = cdrom;	/* until we do it "correctly" above */
+		dev->present = 1;
+#else
+		printk(unsupported);
+#endif	/* CONFIG_BLK_DEV_IDECD */
+		return;
+	}
+	/*
+	 * for Quantum drives, and also for drives not known to the BIOS:
+	 */
+	dev->special.b.set_geometry = 1;
+
+	/*
+	 * Gather up the geometry info.
+	 */
+	dev->type = disk;
+	if (!dev->present) {
+		dev->present = 1;
+		dev->cyl     = dev->bios_cyl  = id->cyls;
+		dev->head    = dev->bios_head = id->heads;
+		dev->sect    = dev->bios_sect = id->sectors; 
+	}
+	capacity = BIOS_SECTORS(dev);	/* default value */
+	if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads
+	 && (id->cur_heads <= 16) && id->cur_sectors)
+	{
+		/*
+		 * Extract the physical drive geometry for our use.
+		 * Note that we purposely do *not* update the bios info.
+		 * This way, programs that use it (like fdisk) will 
+		 * still have the same logical view as the BIOS does,
+		 * which keeps the partition table from being screwed.
+		 *
+		 * An exception to this is the cylinder count,
+		 * which we reexamine later on to correct for 1024 limitations.
+		 */
+		dev->cyl  = id->cur_cyls;
+		dev->head = id->cur_heads;
+		dev->sect = id->cur_sectors;
+		capacity  = dev->cyl * dev->head * dev->sect;
+
+		/* check for word-swapped "capacity" field in id information */
+		check = (id->cur_capacity0 << 16) | id->cur_capacity1;
+		if (check == capacity)		/* was it swapped? */
+			*((int *)&id->cur_capacity0) = capacity; /* fix it */
+	}
+	if (id->capability & 2) {	/* use LBA if the drive supports it */
+		capacity  = fix_lba_capacity(id);
+		dev->select.b.lba = 1;
+		if (!dev->head || dev->head > 16) {
+			dev->cyl  = id->cyls;	/* WIN_SPECIFY needs a valid */
+			dev->head = id->heads;	/*  geometry or it fails.  */
+			dev->sect = id->sectors; 
+		}
+	}
+	/* Correct the number of cyls if the bios value is too small */
+	if (dev->sect == dev->bios_sect && dev->head == dev->bios_head) {
+		if (dev->cyl > dev->bios_cyl) {
+			dev->bios_cyl = dev->cyl;
+			if (!(id->capability & 2))	/* if NOT using LBA */
+				capacity = BIOS_SECTORS(dev);
+		}
+	}
+
+	ide_capacity[DEV_HWIF][dev->select.b.drive] = capacity;
+	printk ("%s: %.40s, %ldMB w/%dKB Cache, %sCHS=%d/%d/%d",
+	 dev->name, id->model, capacity/2048L, id->buf_size/2,
+	 dev->select.b.lba ? "LBA, " : "",
+	 dev->bios_cyl, dev->bios_head, dev->bios_sect);
+	if (id->max_multsect) {
+		/*
+		 * Keep current multiplemode setting, if any (from DOS/BIOS):
+		 */
+		if ((id->multsect_valid & 1) && id->multsect)
+			dev->mult_count = id->multsect;	/* current setting */
+#ifdef INITIAL_MULT_COUNT
+		if (INITIAL_MULT_COUNT <= id->max_multsect)
+			dev->mult_req = INITIAL_MULT_COUNT;
+		else
+			dev->mult_req = id->max_multsect;
+#else	/* use existing setting from DOS/BIOS: */
+		if (dev->mult_count <= id->max_multsect) /* valid? */
+			dev->mult_req = dev->mult_count; /* keep it */
+#endif	/* INITIAL_MULT_COUNT */
+		if (dev->mult_req != dev->mult_count)
+			dev->special.b.set_multmode = 1;
+		printk(", Mult=%d/%d", dev->mult_req, id->max_multsect);
+	}
+	printk("\n");
+}
+
+static void delay_10ms (void)
+{
+	unsigned long timer = jiffies + 2;
+	while (timer > jiffies);
+}
+
+/*
+ * This routine has the difficult job of finding a drive if it exists,
+ * without getting hung up if it doesn't exist, and without leaving any IRQs
+ * dangling to haunt us later.  The last point actually occured in v2.3, and
+ * is the reason for the slightly complex exit sequence.  If a drive is "known"
+ * to exist (from CMOS or kernel parameters), but does not respond right away,
+ * the probe will "hang in there" for the maximum wait time (about 30 seconds).
+ * Otherwise, it will exit much more quickly.
+ *
+ * Returns 1 if device present but not identified.  Returns 0 otherwise.
+ */
+static int do_probe (ide_dev_t *dev, byte probe_cmd)
+{
+	unsigned int rc = 0;
+	unsigned long timer, timeout;
+#if PROBE_FOR_IRQS
+	unsigned int irqs = 0;
+	static byte okstat, irq_probed[2] = {0,0};
+#endif	/* PROBE_FOR_IRQS */
+
+#ifdef CONFIG_BLK_DEV_IDECD
+	if (dev->present) {
+		if ((dev->type == disk) ^ (probe_cmd == WIN_IDENTIFY))
+			return 1;		/* pointless to probe */
+	}
+#endif	/* CONFIG_BLK_DEV_IDECD */
+#if DEBUG
+	printk("probing for %s: present=%d, type=%s, probetype=%s\n",
+		dev->name, dev->present, dev->type ? "cdrom":"disk",
+		(probe_cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
+#endif
+	OUT_BYTE(dev->select.all,HD_CURRENT);	/* select target drive */
+	delay_10ms();				/* wait for BUSY_STAT */
+	if (IN_BYTE(HD_CURRENT,DEV_HWIF) != dev->select.all && !dev->present)
+		return 0;     /* no i/f present: avoid killing ethernet cards */
+	timeout = WAIT_WORSTCASE;
+	okstat  = READY_STAT;
+#ifdef CONFIG_BLK_DEV_IDECD
+	if (probe_cmd == WIN_PIDENTIFY) {
+		timeout = WAIT_PIDENTIFY;
+		okstat  = 0;
+	}
+#endif	/* CONFIG_BLK_DEV_IDECD */
+	if (!OK_STAT(GET_STAT(DEV_HWIF),okstat,BUSY_STAT) && !dev->present) {
+#ifdef CONFIG_BLK_DEV_IDECD
+		if (probe_cmd == WIN_IDENTIFY)	/* get rid of this line? */
+#endif	/* CONFIG_BLK_DEV_IDECD */
+			goto done_probe;        /* no drive present */ 
+	}
+	OUT_BYTE(dev->ctl|2,HD_CMD);		/* disable device irq */
+#if PROBE_FOR_IRQS
+	if (!irq_probed[DEV_HWIF]) {		/* already probed for IRQ? */
+		irqs = probe_irq_on();		/* start monitoring irqs */
+		OUT_BYTE(dev->ctl,HD_CMD);	/* enable device irq */
+	}
+#endif	/* PROBE_FOR_IRQS */
+	OUT_BYTE(probe_cmd,HD_COMMAND);		/* ask drive for ID */
+	delay_10ms();				/* wait for BUSY_STAT */
+	for (timer = jiffies + timeout; timer > jiffies;) {
+		if ((IN_BYTE(HD_ALTSTATUS,DEV_HWIF) & BUSY_STAT) == 0) {
+			delay_10ms();		/* wait for IRQ & DATA_READY */
+			if (OK_STAT(GET_STAT(DEV_HWIF),DATA_READY,BAD_RW_STAT)){
+				cli();			/* some sys need this */
+				do_identify(dev);	/* drive returned ID */
+			} else
+				rc = 1;			/* drive refused ID */
+#if PROBE_FOR_IRQS
+			if (!irq_probed[DEV_HWIF]) {
+				irqs = probe_irq_off(irqs);  /* end probe */
+				if (irqs > 0) {
+					irq_probed[DEV_HWIF] = 1;
+					ide_irq[DEV_HWIF] = irqs;
+				} else
+					printk("%s: IRQ probe failed (%d)\n", dev->name, irqs);
+			}
+#endif	/* PROBE_FOR_IRQS */
+			goto done_probe;
+		}
+	}
+	/* dev->present = 0; */			/* it ain't there */
+#if PROBE_FOR_IRQS
+	if (!irq_probed[DEV_HWIF])
+		(void) probe_irq_off(irqs);  	/* stop probing */
+#endif	/* PROBE_FOR_IRQS */
+done_probe:
+	OUT_BYTE(dev->ctl|2,HD_CMD);		/* disable device irq */
+	delay_10ms();
+	(void) GET_STAT(DEV_HWIF);		/* ensure drive irq is clear */
+	if (dev->select.b.drive == 1) {
+		OUT_BYTE(0xa0,HD_CURRENT);	/* exit with drive0 selected */
+		delay_10ms();
+		OUT_BYTE(dev->ctl|2,HD_CMD);	/* disable device irq */
+		delay_10ms();
+		(void) GET_STAT(DEV_HWIF);	/* ensure drive irq is clear */
+	}
+	return rc;
+}
+
+static byte probe_drive (ide_dev_t *dev)
+{
+	if (do_probe(dev, WIN_IDENTIFY)) {
+#ifdef CONFIG_BLK_DEV_IDECD
+		if (do_probe(dev, WIN_PIDENTIFY))
+#endif	/* CONFIG_BLK_DEV_IDECD */
+		if (dev->present) {
+			if (dev->type == disk) {
+				printk ("%s: non-IDE device, CHS=%d/%d/%d\n",
+				 dev->name, dev->cyl, dev->head, dev->sect);
+			}
+#ifdef CONFIG_BLK_DEV_IDECD
+			else if (dev->type == cdrom) {
+				printk("%s: ATAPI cdrom (?)\n", dev->name);
+			}
+#endif	/* CONFIG_BLK_DEV_IDECD */
+			else {
+				dev->present = 0;	/* nuke it */
+			}
+		}
+	}
+	if (!dev->present)
+		return 0;	/* drive not found */
+#ifdef CONFIG_BLK_DEV_IDECD
+	if (dev->type == cdrom)
+		cdrom_setup(dev);
+#endif	/* CONFIG_BLK_DEV_IDECD */
+	if (dev->type == disk && !dev->select.b.lba) {
+		if (!dev->head || dev->head > 16) {
+			printk("%s: cannot handle disk with %d physical heads\n",
+			 dev->name, dev->head);
+			dev->present = 0;
+		}
+	}
+	return 1;	/* drive found */
+}
+
+static void probe_hw_for_drives (byte hwif)
+{
+	ide_dev_t *devs = &ide_dev[HWIF][0];	/* for convenience */
+
+	if (check_region(IDE_PORT(HD_DATA,HWIF),8)
+	 || check_region(IDE_PORT(HD_CMD,HWIF),1))
+	{
+		if (devs[0].present || devs[1].present)
+			printk("ERROR: ");
+		printk("%s: port(s) already in use\n", ide_name[HWIF]);
+		devs[0].present = 0;
+		devs[1].present = 0;
+	} else {
+		unsigned long flags;
+		save_flags(flags);
+		sti();	/* needed for jiffies and irq probing */
+
+		/* second drive can only exist if first drive was present */
+		if (probe_drive(&devs[0]) || devs[1].present)
+			(void) probe_drive(&devs[1]);
+#if PROBE_FOR_IRQS
+		(void) probe_irq_off(probe_irq_on()); /* clear dangling irqs */
+#endif	/* PROBE_FOR_IRQS */
+		if (devs[0].present || devs[1].present) {
+			snarf_region(IDE_PORT(HD_DATA,HWIF),8);
+			snarf_region(IDE_PORT(HD_CMD,HWIF),1);
+		}
+		restore_flags(flags);
+	}
+}
+
+static int next_drive = 0;	/* used by the ide_setup() routines below */
+
+void ide_setup(char *str, int *ints)
+{
+	ide_dev_t *dev;
+	const char *p[] = {"cyls","heads","sects","wpcom","irq"};
+	int i, hwif, drive = next_drive++;
+#ifdef CONFIG_BLK_DEV_HD
+	extern void hd_setup(char *, int *);
+
+	if (drive < 2) {
+		hd_setup (str, ints);
+		return;
+	}
+#endif /* CONFIG_BLK_DEV_HD */
+	hwif = (drive > 1);
+	printk("%s: ", ide_name[hwif]);
+	if (drive > 3) {
+		printk("too many drives defined\n");
+		return;
+	}
+	drive = drive & 1;
+	printk("%s: ", ide_devname[hwif][drive]);
+	if (!SUPPORT_TWO_INTERFACES && hwif != HWIF) {
+		printk(unsupported);
+		return;
+	}
+	dev = &ide_dev[hwif][drive];
+	if (dev->present)
+		printk("(redefined) ");
+#ifdef CONFIG_BLK_DEV_IDECD
+	if (ints[0] == 0) {
+		if (!strcmp(str,"cdrom")) {
+			printk("cdrom\n");
+			dev->present = 1;	/* force autoprobe to find it */
+			dev->type = cdrom;
+			return;
+		}
+	}
+#endif	/* CONFIG_BLK_DEV_IDECD */
+	if (ints[0] < 3 || ints[0] > 5) {
+		printk("bad parms, expected: cyls,heads,sects[,wpcom[,irq]]\n");
+	} else {
+		for (i=0; i++ < ints[0];)
+			printk("%s=%d%c",p[i-1],ints[i],i<ints[0]?',':'\n');
+		dev->type    = disk;
+		dev->cyl     = dev->bios_cyl  = ints[1];
+		dev->head    = dev->bios_head = ints[2];
+		dev->ctl     = (ints[2] > 8 ? 8 : 0);
+		dev->sect    = dev->bios_sect = ints[3];
+		dev->wpcom   = (ints[0] >= 4) ? ints[4] : 0;
+		if (ints[0] >= 5)
+			ide_irq[HWIF] = ints[5];
+		ide_capacity[HWIF][drive] = BIOS_SECTORS(dev);
+		dev->present = 1;
+	}
+}
+
+void hda_setup(char *str, int *ints)
+{
+	next_drive = 0;
+	ide_setup (str, ints);
+}
+
+void hdb_setup(char *str, int *ints)
+{
+	next_drive = 1;
+	ide_setup (str, ints);
+}
+
+void hdc_setup(char *str, int *ints)
+{
+	next_drive = 2;
+	ide_setup (str, ints);
+}
+
+void hdd_setup(char *str, int *ints)
+{
+	next_drive = 3;
+	ide_setup (str, ints);
+}
+
+#ifndef CONFIG_BLK_DEV_HD
+/*
+ * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
+ * controller that is BIOS compatible with ST-506, and thus showing up in our
+ * BIOS table, but not register compatible, and therefore not present in CMOS.
+ *
+ * Furthermore, we will assume that our ST-506 drives <if any> are the primary
+ * drives in the system -- the ones reflected as drive 1 or 2.  The first
+ * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
+ * nibble.  This will be either a 4 bit drive type or 0xf indicating use byte
+ * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value 
+ * means we have an AT controller hard disk for that drive.
+ */
+extern struct drive_info_struct drive_info;
+static void probe_cmos_for_drives (void)
+{
+	byte drive, cmos_disks, *BIOS = (byte *) &drive_info;
+
+	outb_p(0x12,0x70);		/* specify CMOS address 0x12 */
+	cmos_disks = inb_p(0x71);	/* read the data from 0x12 */
+	/* Extract drive geometry from CMOS+BIOS if not already setup */
+	for (drive = 0; drive < MAX_DRIVES; drive++) {
+		ide_dev_t *dev = &ide_dev[0][drive];
+		if ((cmos_disks & (0xf0 >> (drive*4))) && !dev->present) {
+			dev->cyl     = dev->bios_cyl  = *(unsigned short *)BIOS;
+			dev->head    = dev->bios_head = * (BIOS+2);
+			dev->sect    = dev->bios_sect = * (BIOS+14);
+			dev->wpcom   = (*(unsigned short *)(BIOS+5))>>2;
+			dev->ctl     = *(BIOS+8);
+			dev->wpcom   = 0;
+			dev->type    = disk;
+			dev->present = 1;
+			ide_capacity[0][drive] = BIOS_SECTORS(dev);
+		}
+		BIOS += 16;
+	}
+}
+#endif	/* CONFIG_BLK_DEV_HD */
+
+static void init_ide_data (byte hwif)
+{
+	int drive;
+
+	for (drive = 0; drive < (MAX_DRIVES<<PARTN_BITS); drive++)
+		ide_blksizes[hwif][drive] = 1024;
+	blksize_size[ide_major[hwif]] = ide_blksizes[hwif];
+
+	/* Initialize non-geometry fields -- ide_setup() runs before we do */
+	for (drive = 0; drive < MAX_DRIVES; drive++) {
+		ide_dev_t *dev = &ide_dev[hwif][drive];
+		dev->select.all			= (drive<<4)|0xa0;
+		dev->hwif			= hwif;
+		dev->unmask			= 0;
+		dev->busy			= 0;
+		dev->mult_count			= 0; /* set by do_identify() */
+		dev->mult_req			= 0; /* set by do_identify() */
+		dev->usage			= 0;
+		dev->id				= NULL;
+		dev->ctl			= 0x08;
+		dev->wqueue			= NULL;
+		dev->special.all		= 0;
+		dev->special.b.recalibrate	= 1;
+		dev->keep_settings		= 0;
+		ide_hd[hwif][drive<<PARTN_BITS].start_sect = 0;
+		dev->name = ide_devname[hwif][drive];
+	}
+}
+
+/*
+ * This is the harddisk IRQ description. The SA_INTERRUPT in sa_flags
+ * means we enter the IRQ-handler with interrupts disabled: this is bad for
+ * interrupt latency, but anything else has led to problems on some
+ * machines.  We enable interrupts as much as we can safely do in most places.
+ */
+static byte setup_irq (byte hwif)
+{
+	static byte rc = 0;
+	unsigned long flags;
+	const char *msg = "", *primary_secondary[] = {"primary", "secondary"};
+	void (*handler)(int) = HWIF ? &ide1_intr : &ide0_intr;
+
+#if SUPPORT_SHARING_IRQ
+	if (sharing_single_irq) {
+		if (HWIF != 0 && !rc) {	/* IRQ already allocated? */
+			msg = " (shared with ide0)";
+			goto done;
+		}
+		handler = &ide_shared_intr;
+	}
+#endif /* SUPPORT_SHARING_IRQ */
+	save_flags(flags);
+	cli();
+	if ((rc = request_irq(ide_irq[HWIF],handler,SA_INTERRUPT,ide_name[HWIF])))
+		msg = ":  FAILED! unable to allocate IRQ";
+	restore_flags(flags);
+#if SUPPORT_SHARING_IRQ
+done:
+#endif /* SUPPORT_SHARING_IRQ */
+	printk("%s: %s interface on irq %d%s\n",
+	 ide_name[HWIF], primary_secondary[HWIF], ide_irq[HWIF], msg);
+	return rc;
+}
+
+static void ide_geninit(byte hwif)
+{
+	static int drive;
+	
+	for (drive = 0; drive < MAX_DRIVES; drive++) {
+		ide_dev_t *dev = &ide_dev[HWIF][drive];
+		if (dev->present) {
+			ide_hd[HWIF][drive<<PARTN_BITS].nr_sects = ide_capacity[HWIF][drive];
+			/* Skip partition check for cdroms. */
+			if (dev->type == cdrom)
+				ide_hd[HWIF][drive<<PARTN_BITS].start_sect = -1;
+		}
+	}
+}
+
+static void ide0_geninit(void)
+{
+	ide_geninit(0);
+}
+
+static void ide1_geninit(void)
+{
+	ide_geninit(1);
+}
+
+static struct file_operations ide_fops = {
+	NULL,			/* lseek - default */
+	block_read,		/* read - general block-dev read */
+	block_write,		/* write - general block-dev write */
+	NULL,			/* readdir - bad */
+	NULL,			/* select */
+	ide_ioctl,		/* ioctl */
+	NULL,			/* mmap */
+	ide_open,		/* open */
+	ide_release,		/* release */
+	block_fsync		/* fsync */
+#ifdef CONFIG_BLK_DEV_IDECD
+	,NULL,			/* fasync */
+	ide_check_media_change,	/* check_media_change */
+	NULL			/* revalidate */
+#endif CONFIG_BLK_DEV_IDECD
+};
+
+/*
+ * This is gets invoked once during initialization, to set *everything* up
+ */
+unsigned long ide_init (unsigned long mem_start, unsigned long mem_end)
+{
+	byte hwif;
+
+	for (hwif = 0; hwif < 2; hwif++) {
+		init_ide_data (hwif);
+		if (SUPPORT_TWO_INTERFACES || hwif == HWIF) {
+			if (hwif == 0)
+#ifdef CONFIG_BLK_DEV_HD
+				continue;
+#else
+				probe_cmos_for_drives ();
+#endif /* CONFIG_BLJ_DEV_HD */
+			probe_mem_start = (mem_start + 3uL) & ~3uL;
+			probe_hw_for_drives (hwif);
+			mem_start = probe_mem_start;
+		}
+	}
+
+	/* At this point, all methods of drive detection have completed */
+	ide_gendisk[0].nr_real = ide_dev[0][0].present + ide_dev[0][1].present;
+	ide_gendisk[1].nr_real = ide_dev[1][0].present + ide_dev[1][1].present;
+	if (ide_gendisk[1].nr_real && (ide_irq[0] == ide_irq[1])) {
+		if (!ide_gendisk[0].nr_real) {
+			ide_irq[0] = 0;	/* needed by ide_intr() */
+		} else {
+#if SUPPORT_SHARING_IRQ
+			sharing_single_irq = 1;
+#else /* SUPPORT_SHARING_IRQ */
+			printk("%s: ide irq-sharing%s", ide_name[1], unsupported);
+			return mem_start;
+#endif /* SUPPORT_SHARING_IRQ */
+		}
+	}
+#ifdef CONFIG_BLK_DEV_HD
+#if SUPPORT_SHARING_IRQ
+	if (ide_irq[1] == 14 || sharing_single_irq) {
+#else
+	if (ide_irq[1] == 14) {
+#endif /* SUPPORT_SHARING_IRQ */
+		printk("%s: irq-sharing not possible with old harddisk driver (hd.c)\n", ide_name[1]);
+		return mem_start;
+	}
+#endif /* CONFIG_BLK_DEV_HD */
+
+	for (hwif = 2; hwif-- > 0;) {
+		if (ide_gendisk[hwif].nr_real != 0 && !setup_irq(hwif)) {
+			const char *name = ide_name[HWIF];
+			unsigned int major = ide_major[HWIF];
+			if (register_blkdev(major, name, &ide_fops)) {
+				printk("%s: unable to get major number %d\n", name, major);
+			} else {
+				timer_table[ide_timer[HWIF]].fn
+					= HWIF ? ide1_timer_expiry : ide0_timer_expiry;
+#if SUPPORT_SHARING_IRQ
+				if (sharing_single_irq)
+					blk_dev[major].request_fn = &do_shared_request;
+				else
+#endif /* SUPPORT_SHARING_IRQ */
+				blk_dev[major].request_fn =
+				 HWIF ? &do_ide1_request : &do_ide0_request;
+				read_ahead[major] = 8;	/* (4kB) */
+				ide_gendisk[HWIF].next = gendisk_head;
+				gendisk_head = &ide_gendisk[HWIF];
+			}
+		}
+	}
+	return mem_start;
+}
diff -u --recursive --new-file v1.1.75/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v1.1.75/linux/drivers/block/ll_rw_blk.c	Thu Dec 29 20:15:56 1994
+++ linux/drivers/block/ll_rw_blk.c	Sun Jan  1 16:28:20 1995
@@ -40,16 +40,29 @@
  *	next-request
  */
 struct blk_dev_struct blk_dev[MAX_BLKDEV] = {
-	{ NULL, NULL },		/* no_dev */
-	{ NULL, NULL },		/* dev mem */
-	{ NULL, NULL },		/* dev fd */
-	{ NULL, NULL },		/* dev hd */
-	{ NULL, NULL },		/* dev ttyx */
-	{ NULL, NULL },		/* dev tty */
-	{ NULL, NULL },		/* dev lp */
-	{ NULL, NULL },		/* dev pipes */
-	{ NULL, NULL },		/* dev sd */
-	{ NULL, NULL }		/* dev st */
+	{ NULL, NULL },		/* 0 no_dev */
+	{ NULL, NULL },		/* 1 dev mem */
+	{ NULL, NULL },		/* 2 dev fd */
+	{ NULL, NULL },		/* 3 dev ide0 or hd */
+	{ NULL, NULL },		/* 4 dev ttyx */
+	{ NULL, NULL },		/* 5 dev tty */
+	{ NULL, NULL },		/* 6 dev lp */
+	{ NULL, NULL },		/* 7 dev pipes */
+	{ NULL, NULL },		/* 8 dev sd */
+	{ NULL, NULL },		/* 9 dev st */
+	{ NULL, NULL },		/* 10 */
+	{ NULL, NULL },		/* 11 */
+	{ NULL, NULL },		/* 12 */
+	{ NULL, NULL },		/* 13 */
+	{ NULL, NULL },		/* 14 */
+	{ NULL, NULL },		/* 15 */
+	{ NULL, NULL },		/* 16 */
+	{ NULL, NULL },		/* 17 */
+	{ NULL, NULL },		/* 18 */
+	{ NULL, NULL },		/* 19 */
+	{ NULL, NULL },		/* 20 */
+	{ NULL, NULL },		/* 21 */
+	{ NULL, NULL }		/* 22 dev ide1 */
 };
 
 /*
@@ -171,10 +184,11 @@
 						kstat.dk_drive[disk_index]++;
 					break;
 		case HD_MAJOR:
-		case XT_DISK_MAJOR:	disk_index = (MINOR(req->dev) & 0x00C0) >> 6;
-					if (disk_index < 4)
-						kstat.dk_drive[disk_index]++;
+		case XT_DISK_MAJOR:	disk_index = (MINOR(req->dev) & 0x0040) >> 6;
+					kstat.dk_drive[disk_index]++;
 					break;
+		case IDE1_MAJOR:	disk_index = ((MINOR(req->dev) & 0x0040) >> 6) + 2;
+					kstat.dk_drive[disk_index]++;
 		default:		break;
 	}
 
@@ -254,17 +268,22 @@
 repeat:
 	cli();
 
-/* The scsi disk drivers completely remove the request from the queue when
- * they start processing an entry.  For this reason it is safe to continue
- * to add links to the top entry for scsi devices.
+/* The scsi disk drivers and the IDE driver completely remove the request
+ * from the queue when they start processing an entry.  For this reason
+ * it is safe to continue to add links to the top entry for those devices.
  */
-	if ((major == HD_MAJOR
+	if ((   major == IDE0_MAJOR	/* same as HD_MAJOR */
+	     || major == IDE1_MAJOR
 	     || major == FLOPPY_MAJOR
 	     || major == SCSI_DISK_MAJOR
 	     || major == SCSI_CDROM_MAJOR)
 	    && (req = blk_dev[major].current_request))
 	{
+#ifdef CONFIG_BLK_DEV_HD
 	        if (major == HD_MAJOR || major == FLOPPY_MAJOR)
+#else
+		if (major == FLOPPY_MAJOR)
+#endif CONFIG_BLK_DEV_HD
 			req = req->next;
 		while (req) {
 			if (req->dev == bh->b_dev &&
@@ -515,6 +534,9 @@
 	memset(ro_bits,0,sizeof(ro_bits));
 #ifdef CONFIG_BLK_DEV_HD
 	mem_start = hd_init(mem_start,mem_end);
+#endif
+#ifdef CONFIG_BLK_DEV_IDE
+	mem_start = ide_init(mem_start,mem_end);
 #endif
 #ifdef CONFIG_BLK_DEV_XD
 	mem_start = xd_init(mem_start,mem_end);
diff -u --recursive --new-file v1.1.75/linux/drivers/block/ramdisk.c linux/drivers/block/ramdisk.c
--- v1.1.75/linux/drivers/block/ramdisk.c	Mon Oct 24 15:45:52 1994
+++ linux/drivers/block/ramdisk.c	Thu Dec 29 19:58:41 1994
@@ -209,8 +209,8 @@
 	/* If no RAM disk specified, give up early. */
 	if (!rd_length)
 		return;
-	printk("RAMDISK: %d bytes, starting at 0x%x\n",
-			rd_length, (int) rd_start);
+	printk("RAMDISK: %d bytes, starting at 0x%p\n",
+			rd_length, rd_start);
 
 	/* If we are doing a diskette boot, we might have to pre-load it. */
 	if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR)
diff -u --recursive --new-file v1.1.75/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- v1.1.75/linux/drivers/char/ChangeLog	Thu Dec 15 11:01:49 1994
+++ linux/drivers/char/ChangeLog	Fri Dec 30 08:29:42 1994
@@ -1,3 +1,21 @@
+Thu Dec 29 17:53:48 1994    <tytso@rsx-11.mit.edu>
+
+	* tty_io.c (check_tty_count): New procedure which checks
+		tty->count to make sure that it matches with the number of
+		open file descriptors which point at the structure.  If
+		the number doesn't match, it prints a warning message.
+
+Wed Dec 28 15:41:51 1994    <tytso@rsx-11.mit.edu>
+
+	* tty_io.c (do_tty_hangup, disassociate_ctty): At hangup time,
+		save the tty's current foreground process group in the
+		session leader's task structure.  When the session leader
+		terminates, send a SIGHUP, SIGCONT to that process group.
+		This is not required by POSIX, but it's not prohibited
+		either, and it appears to be the least intrusive way
+		to fix a problem that dialup servers have with
+		orphaned process groups caused by modem hangups.
+
 Thu Dec  8 14:52:11 1994    <tytso@rsx-11.mit.edu>
 
 	* serial.c (rs_ioctl): Don't allow most ioctl's if the serial port
diff -u --recursive --new-file v1.1.75/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v1.1.75/linux/drivers/char/Makefile	Tue Dec 27 09:56:46 1994
+++ linux/drivers/char/Makefile	Sun Jan  1 19:49:19 1995
@@ -18,11 +18,11 @@
 
 OBJS  = tty_io.o n_tty.o console.o keyboard.o serial.o \
 	tty_ioctl.o pty.o vt.o mem.o \
-	defkeymap.o uni_to_437.o
+	defkeymap.o uni_to_437.o vesa_blank.o
 
 SRCS  = tty_io.c n_tty.c console.c keyboard.c serial.c \
 	tty_ioctl.c pty.c vt.c mem.c \
-	defkeymap.c uni_to_437.c
+	defkeymap.c uni_to_437.c vesa_blank.c
 
 
 ifdef CONFIG_CYCLADES
diff -u --recursive --new-file v1.1.75/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.1.75/linux/drivers/char/console.c	Thu Dec 29 20:15:56 1994
+++ linux/drivers/char/console.c	Sun Jan  1 19:49:19 1995
@@ -134,6 +134,7 @@
 static void set_origin(int currcons);
 static void blank_screen(void);
 static void unblank_screen(void);
+void poke_blanked_console(void);
 static void gotoxy(int currcons, int new_x, int new_y);
 static void save_cur(int currcons);
 static inline void set_cursor(int currcons);
@@ -141,6 +142,8 @@
 extern void reset_vc(unsigned int new_console);
 extern void vt_init(void);
 extern void register_console(void (*proc)(const char *));
+extern void vesa_blank(void);
+extern void vesa_unblank(void);
 extern void compute_shiftstate(void);
 extern int conv_uni_to_pc(unsigned long ucs);
 
@@ -149,8 +152,8 @@
 static unsigned long	video_mem_base;		/* Base of video memory		*/
 static unsigned long	video_mem_term;		/* End of video memory		*/
 static unsigned char	video_page;		/* Initial video page (unused)  */
-static unsigned short	video_port_reg;		/* Video register select port	*/
-static unsigned short	video_port_val;		/* Video register value port	*/
+       unsigned short	video_port_reg;		/* Video register select port	*/
+       unsigned short	video_port_val;		/* Video register value port	*/
 static unsigned long	video_num_columns;	/* Number of text columns	*/
 static unsigned long	video_num_lines;	/* Number of text lines		*/
 static unsigned long	video_size_row;
@@ -290,167 +293,6 @@
 #define vcmode		(vt_cons[currcons]->vc_mode)
 #define structsize	(sizeof(struct vc_data) + sizeof(struct vt_struct))
 
-#ifdef CONFIG_VESA_PSPM
-/*
- * This section(s) handles the VESA Power Saving Protocol that let a	*
- * monitor be powered down whenever not needed for a longer time.	*
- * VESA protocol defines:						*
- *									*
- *  Mode/Status		HSync	VSync	Video				*
- *  ----------------------------------------------			*
- *  "On"		on	on	active				*
- *  "Suspend" {either}	on	off	blank				*
- *            {  or  }	off	on	blank				*
- *  "Off"               off	off	blank	<<  PSPM_FORCE_OFF	*
- *									*
- * Original code taken from the Power Management Utility (PMU) of	*
- * Huang shi chao, delivered together with many new monitor models	*
- * capable of the VESA Power Saving Protocol.				*
- * Adapted to Linux by Christoph Rimek (chrimek@toppoint.de)  15-may-94	*
- * Re-Adapted by Nicholas Leon (nicholas@neko.binary9.com) 10/94        *
- *                 (with minor reorganization/changes)                  *
- */
-
-
-static void vesa_blank(void);
-static void vesa_unblank(void);
-
-#define seq_port_reg	(0x3c4)		/* Sequencer register select port */
-#define seq_port_val	(0x3c5)		/* Sequencer register value port  */
-#define video_misc_rd	(0x3cc)		/* Video misc. read port	*/
-#define video_misc_wr	(0x3c2)		/* Video misc. write port	*/
-
-/* structure holding original VGA register settings */
-static struct {
-	unsigned char	SeqCtrlIndex;		/* Sequencer Index reg.   */
-	unsigned char	CrtCtrlIndex;		/* CRT-Contr. Index reg.  */
-	unsigned char	CrtMiscIO;		/* Miscellaneous register */
-#ifdef CONFIG_PSPM_FORCE_OFF
-	unsigned char	HorizontalTotal;	/* CRT-Controller:00h */
-	unsigned char	HorizDisplayEnd;	/* CRT-Controller:01h */
-	unsigned char	StartHorizRetrace;	/* CRT-Controller:04h */
-	unsigned char	EndHorizRetrace;	/* CRT-Controller:05h */
-#endif
-	unsigned char	Overflow;		/* CRT-Controller:07h */
-	unsigned char	StartVertRetrace;	/* CRT-Controller:10h */
-	unsigned char	EndVertRetrace;		/* CRT-Controller:11h */
-	unsigned char	ModeControl;		/* CRT-Controller:17h */
-	unsigned char	ClockingMode;		/* Seq-Controller:01h */
-} vga;
-
-static int vesa_blanked = 0;
-
-/* routine to blank a vesa screen */
-static void vesa_blank(void)
-{
-	/* save original values of VGA controller registers */
-	cli();
-	vga.SeqCtrlIndex = inb_p(seq_port_reg);
-	vga.CrtCtrlIndex = inb_p(video_port_reg);
-	vga.CrtMiscIO = inb_p(video_misc_rd);
-	sti();
-#ifdef CONFIG_PSPM_FORCE_OFF
-	outb_p(0x00,video_port_reg);			/* HorizontalTotal */
-	vga.HorizontalTotal = inb_p(video_port_val);
-	outb_p(0x01,video_port_reg);			/* HorizDisplayEnd */
-	vga.HorizDisplayEnd = inb_p(video_port_val);
-	outb_p(0x04,video_port_reg);			/* StartHorizRetrace */
-	vga.StartHorizRetrace = inb_p(video_port_val);
-	outb_p(0x05,video_port_reg);			/* EndHorizRetrace */
-	vga.EndHorizRetrace = inb_p(video_port_val);
-#endif
-	outb_p(0x07,video_port_reg);			/* Overflow */
-	vga.Overflow = inb_p(video_port_val);
-	outb_p(0x10,video_port_reg);			/* StartVertRetrace */
-	vga.StartVertRetrace = inb_p(video_port_val);
-	outb_p(0x11,video_port_reg);			/* EndVertRetrace */
-	vga.EndVertRetrace = inb_p(video_port_val);
-	outb_p(0x17,video_port_reg);			/* ModeControl */
-	vga.ModeControl = inb_p(video_port_val);
-	outb_p(0x01,seq_port_reg);			/* ClockingMode */
-	vga.ClockingMode = inb_p(seq_port_val);
-
-	/* assure that video is enabled */
-	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
-	cli();
-	outb_p(0x01,seq_port_reg);
-	outb_p(vga.ClockingMode | 0x20,seq_port_val);
-
-/*	sti(); 
-	cli(); */
-	
-	/* test for vertical retrace in process.... */
-	if ((vga.CrtMiscIO & 0x80) == 0x80)
-		outb_p(vga.CrtMiscIO & 0xef,video_misc_wr);
-
-	/*  Set <End of vertical retrace> to minimum (0) and		*
-	 *  <Start of vertical Retrace> to maximum (incl. overflow)	*
-	 *  Result: turn off vertical sync (VSync) pulse		*/
-	outb_p(0x10,video_port_reg);		/* StartVertRetrace */
-	outb_p(0xff,video_port_val);		/* maximum value */
-	outb_p(0x11,video_port_reg);		/* EndVertRetrace */
-	outb_p(0x40,video_port_val);            /* minimum (bits 0..3)  */
-	outb_p(0x07,video_port_reg);		/* Overflow */
-	outb_p(vga.Overflow | 0x84,video_port_val);	/* bits 9,10 of  */
-							/* vert. retrace */
-#ifdef CONFIG_PSPM_FORCE_OFF
-	/*  Set <End of horizontal retrace> to minimum (0) and	*
-	 *  <Start of horizontal Retrace> to maximum		*
-	 *  Result: turn off horizontal sync (HSync) pulse	*/
-	outb_p(0x04,video_port_reg);		/* StartHorizRetrace */
-	outb_p(0xff,video_port_val);		/* maximum */
-	outb_p(0x05,video_port_reg);		/* EndHorizRetrace */
-	outb_p(0x00,video_port_val);		/* minimum (0) */
-#endif
-	/* restore both index registers */
-	outb_p(vga.SeqCtrlIndex,seq_port_reg);
-	outb_p(vga.CrtCtrlIndex,video_port_reg);
-	sti();
-
-	vesa_blanked = 1;
-}	
-
-/* routine to unblank a vesa screen */
-static void vesa_unblank(void)
-{
-	if (!vesa_blanked)
-	  return;
-
-	/* restore original values of VGA controller registers */
-	cli();
-	outb_p(vga.CrtMiscIO,video_misc_wr);
-#ifdef CONFIG_PSPM_FORCE_OFF
-	outb_p(0x00,video_port_reg);		/* HorizontalTotal */
-	outb_p(vga.HorizontalTotal,video_port_val);
-	outb_p(0x01,video_port_reg);		/* HorizDisplayEnd */
-	outb_p(vga.HorizDisplayEnd,video_port_val);
-	outb_p(0x04,video_port_reg);		/* StartHorizRetrace */
-	outb_p(vga.StartHorizRetrace,video_port_val);
-	outb_p(0x05,video_port_reg);		/* EndHorizRetrace */
-	outb_p(vga.EndHorizRetrace,video_port_val);
-#endif
-	outb_p(0x07,video_port_reg);		/* Overflow */
-	outb_p(vga.Overflow,video_port_val);
-	outb_p(0x10,video_port_reg);		/* StartVertRetrace */
-	outb_p(vga.StartVertRetrace,video_port_val);
-	outb_p(0x11,video_port_reg);		/* EndVertRetrace */
-	outb_p(vga.EndVertRetrace,video_port_val);
-	outb_p(0x17,video_port_reg);		/* ModeControl */
-	outb_p(vga.ModeControl,video_port_val);
-	outb_p(0x01,seq_port_reg);		/* ClockingMode */
-	outb_p(vga.ClockingMode,seq_port_val);
-
-	/* restore index/control registers */
-	outb_p(vga.SeqCtrlIndex,seq_port_reg);
-	outb_p(vga.CrtCtrlIndex,video_port_reg);
-	sti();
-
-	vesa_blanked = 0;
-}
-
-#endif /* CONFIG_VESA_PSPM */
-
-
 static void * memsetw(void * s, unsigned short c, unsigned int count)
 {
 __asm__("cld\n\t"
@@ -1302,6 +1144,7 @@
 			break;
 		case 9:	/* set blanking interval */
 			blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
+			poke_blanked_console();
 			break;
 	}
 }
@@ -2209,10 +2052,8 @@
 	hide_cursor();
 	console_blanked = fg_console + 1;
 
-#ifdef CONFIG_VESA_PSPM
 	if(!nopowersave)
 	    vesa_blank();
-#endif	
 }
 
 void do_unblank_screen(void)
@@ -2251,9 +2092,8 @@
 	set_cursor(fg_console);
 	if (resetorg)
 		__set_origin(blank__origin);
-#ifdef CONFIG_VESA_PSPM
+
 	vesa_unblank();
-#endif
 }
 
 /*
@@ -2307,7 +2147,7 @@
  * the new modes are needed for a fast and complete dump-restore cycle,
  * needed to implement root-window menus in text mode (A Rubini Nov 1994)
  */
-int do_screendump(int arg, int mode)
+int do_screendump(unsigned long arg, int mode)
 {
 	char *sptr, *buf = (char *)arg;
 	int currcons, l, chcount;
diff -u --recursive --new-file v1.1.75/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v1.1.75/linux/drivers/char/keyboard.c	Tue Dec 27 09:56:46 1994
+++ linux/drivers/char/keyboard.c	Sun Jan  1 19:49:19 1995
@@ -133,14 +133,14 @@
 
 static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
 	num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
-	SAK, decr_console, incr_console;
+	SAK, decr_console, incr_console, spawn_console;
 
 static void_fnp spec_fn_table[] = {
 	do_null,	enter,		show_ptregs,	show_mem,
 	show_state,	send_intr,	lastcons,	caps_toggle,
 	num,		hold,		scroll_forw,	scroll_back,
 	boot_it,	caps_on,	compose,	SAK,
-	decr_console,	incr_console
+	decr_console,	incr_console,	spawn_console
 };
 
 /* maximum values each key_handler can handle */
@@ -712,6 +712,15 @@
 static void compose(void)
 {
 	dead_key_next = 1;
+}
+
+int spawnpid, spawnsig;
+
+static void spawn_console(void)
+{
+        if (spawnpid)
+	   if(kill_proc(spawnpid, spawnsig, 1))
+	     spawnpid = 0;
 }
 
 static void SAK(void)
diff -u --recursive --new-file v1.1.75/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v1.1.75/linux/drivers/char/lp.c	Tue Dec  6 17:37:06 1994
+++ linux/drivers/char/lp.c	Thu Dec 29 20:13:17 1994
@@ -14,6 +14,7 @@
 #include <linux/lp.h>
 #include <linux/malloc.h>
 #include <linux/ioport.h>
+#include <linux/fcntl.h>
 
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -73,6 +74,10 @@
 		count ++;
 		if(need_resched)
 			schedule();
+		if ((LP_F(minor) & LP_CAREFUL) &&
+		    (status & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) != 
+		    (LP_PSELECD|LP_PERRORP))
+			continue;
 	} while(!(status & LP_PBUSY) && count < LP_CHAR(minor));
 
 	if (count == LP_CHAR(minor)) {
@@ -108,6 +113,10 @@
 	|| !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
 	|| !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) {
 
+		if ((LP_F(minor) & LP_CAREFUL) &&
+		    (status & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) != 
+		    (LP_PSELECD|LP_PERRORP))
+			return 0;
 		outb_p(lpchar, LP_B(minor));
 		/* must wait before taking strobe high, and after taking strobe
 		   low, according spec.  Some printers need it, others don't. */
@@ -160,29 +169,28 @@
 				--copy_size;
 				++bytes_written;
 			} else {
-				if (!((status = LP_S(minor)) & LP_PERRORP)) {
-					int rc = total_bytes_written + bytes_written;
-
-					if ((status & LP_POUTPA)) {
-						printk("lp%d out of paper\n", minor);
-						if (!rc)
-							rc = -ENOSPC;
-					} else if (!(status & LP_PSELECD)) {
-						printk("lp%d off-line\n", minor);
-						if (!rc)
-							rc = -EIO;
-					} else {
-						printk("lp%d printer error\n", minor);
-						if (!rc)
-							rc = -EIO;
-					}
-					if(LP_F(minor) & LP_ABORT)
-						return rc;
+				int rc = total_bytes_written + bytes_written;
+				status = LP_S(minor);
+				if ((status & LP_POUTPA)) {
+					printk("lp%d out of paper\n", minor);
+					if (LP_F(minor) & LP_ABORT)
+						return rc?rc:-ENOSPC;
+				} else if (!(status & LP_PSELECD)) {
+					printk("lp%d off-line\n", minor);
+					if (LP_F(minor) & LP_ABORT)
+						return rc?rc:-EIO;
+				} else if (!(status & LP_PERRORP)) {
+					printk("lp%d printer error\n", minor);
+					if (LP_F(minor) & LP_ABORT)
+						return rc?rc:-EIO;
 				}
 				cli();
 				outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
 				status = LP_S(minor);
-				if (!(status & LP_PACK) || (status & LP_PBUSY)) {
+				if ((!(status & LP_PACK) || (status & LP_PBUSY))
+				  && (!(LP_F(minor) & LP_CAREFUL) ||
+				  (status & (LP_POUTPA|LP_PSELECD|LP_PERRORP))
+				  == (LP_PSELECD|LP_PERRORP))) {
 					outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
 					sti();
 					continue;
@@ -257,7 +265,7 @@
 			if (!(status & LP_PERRORP)) {
 				printk("lp%d reported invalid error status (on fire, eh?)\n", minor);
 				if(LP_F(minor) & LP_ABORT)
-					return temp-buf?temp-buf:-EFAULT;
+					return temp-buf?temp-buf:-EIO;
 				current->state = TASK_INTERRUPTIBLE;
 				current->timeout = jiffies + LP_TIMEOUT_POLLED;
 				schedule();
@@ -310,6 +318,25 @@
 	if (LP_F(minor) & LP_BUSY)
 		return -EBUSY;
 
+	/* If ABORTOPEN is set and the printer is offline or out of paper,
+	   we may still want to open it to perform ioctl()s.  Therefore we
+	   have commandeered O_NONBLOCK, even though it is being used in
+	   a non-standard manner.  This is strictly a Linux hack, and
+	   should most likely only ever be used by the tunelp application. */
+        if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
+		int status = LP_S(minor);
+		if (status & LP_POUTPA) {
+			printk("lp%d out of paper\n", minor);
+			return -ENOSPC;
+		} else if (!(status & LP_PSELECD)) {
+			printk("lp%d off-line\n", minor);
+			return -EIO;
+		} else if (!(status & LP_PERRORP)) {
+			printk("lp%d printer error\n", minor);
+			return -EIO;
+		}
+	}
+
 	if ((irq = LP_IRQ(minor))) {
 		lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
 		if (!lp_table[minor].lp_buffer)
@@ -375,6 +402,18 @@
 			else
 				LP_F(minor) &= ~LP_ABORT;
 			break;
+		case LPABORTOPEN:
+			if (arg)
+				LP_F(minor) |= LP_ABORTOPEN;
+			else
+				LP_F(minor) &= ~LP_ABORTOPEN;
+			break;
+		case LPCAREFUL:
+			if (arg)
+				LP_F(minor) |= LP_CAREFUL;
+			else
+				LP_F(minor) &= ~LP_CAREFUL;
+			break;
 		case LPWAIT:
 			LP_WAIT(minor) = arg;
 			break;
@@ -423,6 +462,9 @@
 		}
 		case LPGETIRQ:
 			retval = LP_IRQ(minor);
+			break;
+		case LPGETSTATUS:
+			retval = LP_S(minor);	/* in range 0..255 */
 			break;
 		default:
 			retval = -EINVAL;
diff -u --recursive --new-file v1.1.75/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v1.1.75/linux/drivers/char/tty_io.c	Tue Dec 27 09:56:46 1994
+++ linux/drivers/char/tty_io.c	Sun Jan  1 19:49:19 1995
@@ -65,6 +65,9 @@
 
 #undef TTY_DEBUG_HANGUP
 
+#define TTY_PARANOIA_CHECK
+#define CHECK_TTY_COUNT
+
 #ifdef CONFIG_SELECTION
 extern int set_selection(const int arg, struct tty_struct *tty);
 extern int paste_selection(struct tty_struct *tty);
@@ -72,9 +75,10 @@
 extern int mouse_reporting(void);
 extern int shift_state;
 #endif /* CONFIG_SELECTION */
-extern int do_screendump(int arg, int mode);
+extern int do_screendump(unsigned long arg, int mode);
 extern void do_blank_screen(int nopowersave);
 extern void do_unblank_screen(void);
+extern void set_vesa_blanking(const unsigned long arg);
 
 struct termios tty_std_termios;		/* for the benefit of tty drivers  */
 struct tty_driver *tty_drivers = NULL;	/* linked list of tty drivers */
@@ -129,8 +133,6 @@
 	return(_tty_name(tty, buf));
 }
 
-#define TTY_PARANOIA_CHECK
-
 inline int tty_paranoia_check(struct tty_struct *tty, dev_t device,
 			      const char *routine)
 {
@@ -152,6 +154,33 @@
 	return 0;
 }
 
+static int check_tty_count(struct tty_struct *tty, const char *routine)
+{
+#ifdef CHECK_TTY_COUNT
+	struct file *f;
+	int i, count = 0;
+	
+	for (f = first_file, i=0; i<nr_files; i++, f = f->f_next) {
+		if (!f->f_count)
+			continue;
+		if (f->private_data == tty) {
+			count++;
+		}
+	}
+	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
+	    tty->driver.subtype == PTY_TYPE_SLAVE &&
+	    tty->link && tty->link->count)
+		count++;
+	if (tty->count != count) {
+		printk("Warning: dev (%d, %d) tty->count(%d) != #fd's(%d) in %s\n",
+		       MAJOR(tty->device), MINOR(tty->device), tty->count,
+		       count, routine);
+		return count;
+       }	
+#endif
+	return 0;
+}
+
 int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
 {
 	if (disc < N_TTY || disc >= NR_LDISCS)
@@ -319,6 +348,7 @@
 
 	if (!tty)
 		return;
+	check_tty_count(tty, "do_tty_hangup");
 	for (filp = first_file, i=0; i<nr_files; i++, filp = filp->f_next) {
 		if (!filp->f_count)
 			continue;
@@ -359,18 +389,21 @@
 		}
 	}
 	
-	if (tty->session > 0) {
-		kill_sl(tty->session,SIGHUP,1);
-		kill_sl(tty->session,SIGCONT,1);
+ 	for_each_task(p) {
+		if ((tty->session > 0) && (p->session == tty->session) &&
+		    p->leader) {
+			send_sig(SIGHUP,p,1);
+			send_sig(SIGCONT,p,1);
+			if (tty->pgrp > 0)
+				p->tty_old_pgrp = tty->pgrp;
+		}
+		if (p->tty == tty)
+			p->tty = NULL;
 	}
 	tty->flags = 0;
 	tty->session = 0;
 	tty->pgrp = -1;
 	tty->ctrl_status = 0;
- 	for_each_task(p) {
-		if (p->tty == tty)
-			p->tty = NULL;
-	}
 	if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS)
 		*tty->termios = tty->driver.init_termios;
 	if (tty->driver.hangup)
@@ -413,8 +446,13 @@
 	struct tty_struct *tty = current->tty;
 	struct task_struct *p;
 
-	if (!tty)
+	if (!tty) {
+		if (current->tty_old_pgrp) {
+			kill_pg(current->tty_old_pgrp, SIGHUP, priv);
+			kill_pg(current->tty_old_pgrp, SIGCONT, priv);
+		}
 		return;
+	}
 	if (tty->pgrp > 0) {
 		kill_pg(tty->pgrp, SIGHUP, priv);
 		kill_pg(tty->pgrp, SIGCONT, priv);
@@ -894,11 +932,12 @@
 	struct task_struct **p;
 	int	idx;
 	
-
 	tty = (struct tty_struct *)filp->private_data;
 	if (tty_paranoia_check(tty, filp->f_inode->i_rdev, "release_dev"))
 		return;
 
+	check_tty_count(tty, "release_dev");
+
 	tty_fasync(filp->f_inode, filp, 0);
 
 	tp = tty->termios;
@@ -979,7 +1018,7 @@
 	}
 	if (tty->count)
 		return;
-	
+
 	if (o_tty) {
 		if (o_tty->count)
 			return;
@@ -1049,6 +1088,7 @@
 	tty->magic = 0;
 	(*tty->driver.refcount)--;
 	free_page((unsigned long) tty);
+	filp->private_data = 0;
 	if (o_tty) {
 		o_tty->magic = 0;
 		(*o_tty->driver.refcount)--;
@@ -1091,9 +1131,10 @@
 	minor = MINOR(device);
 	
 	retval = init_dev(device, &tty);
-	filp->private_data = tty;
 	if (retval)
 		return retval;
+	filp->private_data = tty;
+	check_tty_count(tty, "tty_open");
 	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver.subtype == PTY_TYPE_MASTER)
 		noctty = 1;
@@ -1208,7 +1249,7 @@
 /*
  * XXX does anyone use this anymore?!?
  */
-static int do_get_ps_info(int arg)
+static int do_get_ps_info(unsigned long arg)
 {
 	struct tstruct {
 		int flag;
@@ -1439,6 +1480,9 @@
 				case 8: /* second arg is 1 or 2 */
 				case 9: /* both are explained in console.c */
 					return do_screendump(arg,retval-7);
+				case 10:
+					set_vesa_blanking(arg);
+					return 0;
 				default: 
 					return -EINVAL;
 			}
diff -u --recursive --new-file v1.1.75/linux/drivers/char/vesa_blank.c linux/drivers/char/vesa_blank.c
--- v1.1.75/linux/drivers/char/vesa_blank.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/char/vesa_blank.c	Sun Jan  1 19:49:19 1995
@@ -0,0 +1,243 @@
+/*
+ * vesa_blank.c
+ *
+ * Exported functions:
+ *	void vesa_blank(void);
+ *	void vesa_unblank(void);
+ *	void set_vesa_blanking(const unsigned long arg);
+ *
+ * Not all hardware reacts well to this code - activate at your own risk.
+ * Activation is done using a sufficiently recent version of setterm
+ * or using a tiny C program like the following.
+ *
+-----------------------------------------------------------------------
+|#include <stdio.h>
+|#include <linux/termios.h>
+|main(int argc, char *argv[]) {
+|    int fd;
+|    struct { char ten, onoff; } arg;
+|
+|    if (argc != 2) {
+|	fprintf(stderr, "usage: setvesablank ON|on|off\n");
+|	exit(1);
+|    }
+|    if ((fd = open("/dev/console", 0)) < 0)
+|      fd = 0;
+|    arg.ten = 10;
+|    arg.onoff = 0;
+|    if (!strcmp(argv[1], "on"))
+|      arg.onoff = 1;
+|    else if (!strcmp(argv[1], "ON"))
+|      arg.onoff = 2;
+|    if (ioctl(fd, TIOCLINUX, &arg)) {
+|	perror("setvesablank: TIOCLINUX");
+|	exit(1);
+|    }
+|    exit(0);
+|}
+-----------------------------------------------------------------------
+*/
+
+#include <asm/io.h>
+#include <asm/system.h>
+extern unsigned short video_port_reg, video_port_val;
+
+/*
+ * This file handles the VESA Power Saving Protocol that lets a
+ * monitor be powered down whenever not needed for a longer time.
+ * The VESA protocol defines:
+ *
+ *  Mode/Status		HSync	VSync	Video
+ *  -------------------------------------------
+ *  "On"		on	on	active  (mode 0)
+ *  "Suspend" {either}	on	off	blank   (mode 1)
+ *            {  or  }	off	on	blank   
+ *  "Off"               off	off	blank	(mode 2)
+ *
+ * Original code taken from the Power Management Utility (PMU) of
+ * Huang shi chao, delivered together with many new monitor models
+ * capable of the VESA Power Saving Protocol.
+ *
+ * Adapted to Linux by Christoph Rimek (chrimek@toppoint.de)  15-may-94.
+ * A slightly adapted fragment of his README follows.
+ *
+Patch (based on Linux Kernel revision 1.0) for handling the Power Saving
+feature of the new monitor generation. The code works on all these monitors
+(mine is a Smile 1506) and should run on *all* video adapter cards (change
+some i/o-adresses), although tested only on two different VGA-cards: a  
+cheap Cirrus Logic (5428) and a miro Crystal 8S (S3-805).
+
+You can choose from two options:
+
+(1) Setting vesa_blanking_mode to 1.
+    The code will save the current setting of your video adapters'
+    register settings and then program the controller to turn off
+    the vertical synchronisation pulse.
+
+(2) Setting vesa_blanking_mode to 2.
+    If your monitor locally has an Off_Mode timer then you should not
+    force your video card to send the OFF-signal - your monitor will
+    power down by itself.
+    If your monitor cannot handle this and needs the Off-signal directly,
+    or if you like your monitor to power down immediately when the
+    blank_timer times out, then you choose this option.
+
+On the other hand I'd recommend to not choose this second option unless
+it is absolutely necessary. Powering down a monitor to the Off_State with
+an approx. power consumption of 3-5 Watts is a rather strong action for
+the CRT and it should not be done every now and then. If the software only  
+sends the signal to enter Standby mode, you have the chance to interfere
+before the monitor powers down. Do not set a too short period, if you love
+your hardware :-)) .
+
+If requested, in the future it may be possible to install another timer
+to provide a configurable delay between the two stages Standby and Off
+similar to the "setterm -blank"-feature.
+*/
+
+#define seq_port_reg	(0x3c4)		/* Sequencer register select port */
+#define seq_port_val	(0x3c5)		/* Sequencer register value port  */
+#define video_misc_rd	(0x3cc)		/* Video misc. read port	  */
+#define video_misc_wr	(0x3c2)		/* Video misc. write port	  */
+
+/* structure holding original VGA register settings */
+static struct {
+	unsigned char	SeqCtrlIndex;		/* Sequencer Index reg.   */
+	unsigned char	CrtCtrlIndex;		/* CRT-Contr. Index reg.  */
+	unsigned char	CrtMiscIO;		/* Miscellaneous register */
+	unsigned char	HorizontalTotal;	/* CRT-Controller:00h */
+	unsigned char	HorizDisplayEnd;	/* CRT-Controller:01h */
+	unsigned char	StartHorizRetrace;	/* CRT-Controller:04h */
+	unsigned char	EndHorizRetrace;	/* CRT-Controller:05h */
+	unsigned char	Overflow;		/* CRT-Controller:07h */
+	unsigned char	StartVertRetrace;	/* CRT-Controller:10h */
+	unsigned char	EndVertRetrace;		/* CRT-Controller:11h */
+	unsigned char	ModeControl;		/* CRT-Controller:17h */
+	unsigned char	ClockingMode;		/* Seq-Controller:01h */
+} vga;
+
+static int vesa_blanking_mode = 0;
+static int vesa_blanked = 0;
+
+/* routine to blank a vesa screen */
+void vesa_blank(void)
+{
+	int mode;
+
+	if((mode = vesa_blanking_mode) == 0)
+	  return;
+
+	/* save original values of VGA controller registers */
+	cli();
+	vga.SeqCtrlIndex = inb_p(seq_port_reg);
+	vga.CrtCtrlIndex = inb_p(video_port_reg);
+	vga.CrtMiscIO = inb_p(video_misc_rd);
+	sti();
+
+	if(mode == 2) {
+	    outb_p(0x00,video_port_reg);		/* HorizontalTotal */
+	    vga.HorizontalTotal = inb_p(video_port_val);
+	    outb_p(0x01,video_port_reg);		/* HorizDisplayEnd */
+	    vga.HorizDisplayEnd = inb_p(video_port_val);
+	    outb_p(0x04,video_port_reg);		/* StartHorizRetrace */
+	    vga.StartHorizRetrace = inb_p(video_port_val);
+	    outb_p(0x05,video_port_reg);		/* EndHorizRetrace */
+	    vga.EndHorizRetrace = inb_p(video_port_val);
+	}
+	outb_p(0x07,video_port_reg);			/* Overflow */
+	vga.Overflow = inb_p(video_port_val);
+	outb_p(0x10,video_port_reg);			/* StartVertRetrace */
+	vga.StartVertRetrace = inb_p(video_port_val);
+	outb_p(0x11,video_port_reg);			/* EndVertRetrace */
+	vga.EndVertRetrace = inb_p(video_port_val);
+	outb_p(0x17,video_port_reg);			/* ModeControl */
+	vga.ModeControl = inb_p(video_port_val);
+	outb_p(0x01,seq_port_reg);			/* ClockingMode */
+	vga.ClockingMode = inb_p(seq_port_val);
+
+	/* assure that video is enabled */
+	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
+	cli();
+	outb_p(0x01,seq_port_reg);
+	outb_p(vga.ClockingMode | 0x20,seq_port_val);
+
+	/* test for vertical retrace in process.... */
+	if ((vga.CrtMiscIO & 0x80) == 0x80)
+		outb_p(vga.CrtMiscIO & 0xef,video_misc_wr);
+
+	/*
+	 * Set <End of vertical retrace> to minimum (0) and
+	 * <Start of vertical Retrace> to maximum (incl. overflow)
+	 * Result: turn off vertical sync (VSync) pulse.
+	 */
+	outb_p(0x10,video_port_reg);		/* StartVertRetrace */
+	outb_p(0xff,video_port_val);		/* maximum value */
+	outb_p(0x11,video_port_reg);		/* EndVertRetrace */
+	outb_p(0x40,video_port_val);            /* minimum (bits 0..3)  */
+	outb_p(0x07,video_port_reg);		/* Overflow */
+	outb_p(vga.Overflow | 0x84,video_port_val);	/* bits 9,10 of  */
+							/* vert. retrace */
+	if (mode == 2) {
+	    /*
+	     * Set <End of horizontal retrace> to minimum (0) and
+	     *  <Start of horizontal Retrace> to maximum
+	     * Result: turn off horizontal sync (HSync) pulse.
+	     */
+	    outb_p(0x04,video_port_reg);	/* StartHorizRetrace */
+	    outb_p(0xff,video_port_val);	/* maximum */
+	    outb_p(0x05,video_port_reg);	/* EndHorizRetrace */
+	    outb_p(0x00,video_port_val);	/* minimum (0) */
+	}
+
+	/* restore both index registers */
+	outb_p(vga.SeqCtrlIndex,seq_port_reg);
+	outb_p(vga.CrtCtrlIndex,video_port_reg);
+	sti();
+
+	vesa_blanked = mode;
+}	
+
+/* routine to unblank a vesa screen */
+void vesa_unblank(void)
+{
+	if (!vesa_blanked)
+	  return;
+
+	/* restore original values of VGA controller registers */
+	cli();
+	outb_p(vga.CrtMiscIO,video_misc_wr);
+
+	if (vesa_blanked == 2) {
+	    outb_p(0x00,video_port_reg);	/* HorizontalTotal */
+	    outb_p(vga.HorizontalTotal,video_port_val);
+	    outb_p(0x01,video_port_reg);	/* HorizDisplayEnd */
+	    outb_p(vga.HorizDisplayEnd,video_port_val);
+	    outb_p(0x04,video_port_reg);	/* StartHorizRetrace */
+	    outb_p(vga.StartHorizRetrace,video_port_val);
+	    outb_p(0x05,video_port_reg);	/* EndHorizRetrace */
+	    outb_p(vga.EndHorizRetrace,video_port_val);
+	}
+	outb_p(0x07,video_port_reg);		/* Overflow */
+	outb_p(vga.Overflow,video_port_val);
+	outb_p(0x10,video_port_reg);		/* StartVertRetrace */
+	outb_p(vga.StartVertRetrace,video_port_val);
+	outb_p(0x11,video_port_reg);		/* EndVertRetrace */
+	outb_p(vga.EndVertRetrace,video_port_val);
+	outb_p(0x17,video_port_reg);		/* ModeControl */
+	outb_p(vga.ModeControl,video_port_val);
+	outb_p(0x01,seq_port_reg);		/* ClockingMode */
+	outb_p(vga.ClockingMode,seq_port_val);
+
+	/* restore index/control registers */
+	outb_p(vga.SeqCtrlIndex,seq_port_reg);
+	outb_p(vga.CrtCtrlIndex,video_port_reg);
+	sti();
+
+	vesa_blanked = 0;
+}
+
+void set_vesa_blanking(const unsigned long arg) {
+	char *argp = (char *)(arg + 1);
+	unsigned int mode = get_fs_byte(argp);
+	vesa_blanking_mode = ((mode < 3) ? mode : 0);
+}
diff -u --recursive --new-file v1.1.75/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v1.1.75/linux/drivers/char/vt.c	Thu Dec 29 20:15:56 1994
+++ linux/drivers/char/vt.c	Sun Jan  1 19:49:19 1995
@@ -585,10 +585,33 @@
 		return 0;
 
 	case KDSETLED:
-		/* OK, I'll let ordinary users run blinkenlights - zblaxell */
+		if (!perm)
+		  return -EPERM;
 		setledstate(kbd, arg);
 		return 0;
 
+	/*
+	 * A process can indicate its willingness to accept signals
+	 * generated by pressing an appropriate key combination.
+	 * Thus, one can have a daemon that e.g. spawns a new console
+	 * upon a keypress and then changes to it.
+	 * Probably init should be changed to do this (and have a
+	 * field ks (`keyboard signal') in inittab describing the
+	 * desired action), so that the number of background daemons
+	 * does not increase.
+	 */
+	case KDSIGACCEPT:
+	{
+		extern int spawnpid, spawnsig;
+		if (!perm)
+		  return -EPERM;
+		if (arg < 1 || arg > NSIG || arg == SIGKILL)
+		  return -EINVAL;
+		spawnpid = current->pid;
+		spawnsig = arg;
+		return 0;
+	}
+
 	case VT_SETMODE:
 	{
 		struct vt_mode *vtmode = (struct vt_mode *)arg;
@@ -644,8 +667,7 @@
 		put_fs_word(fg_console + 1, &vtstat->v_active);
 		state = 1;	/* /dev/tty0 is always open */
 		for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
-			if (console_driver.table[i] &&
-			    console_driver.table[i]->count > 0)
+			if (VT_IS_IN_USE(i))
 				state |= mask;
 		put_fs_word(state, &vtstat->v_state);
 		return 0;
@@ -759,28 +781,20 @@
 	  * Disallocate memory associated to VT (but leave VT1)
 	  */
 	 case VT_DISALLOCATE:
-		if (!perm)
-			return -EPERM;
 		if (arg > MAX_NR_CONSOLES)
 			return -ENXIO;
 		if (arg == 0) {
 		    /* disallocate all unused consoles, but leave 0 */
 		    for (i=1; i<MAX_NR_CONSOLES; i++)
-		      if (! VT_IS_IN_USE(i)) {
-			  if (i == fg_console)
-			    change_console(0);
-			  vc_disallocate(i);
-		      }
+		      if (! VT_IS_IN_USE(i) && i != fg_console)
+			vc_disallocate(i);
 		} else {
 		    /* disallocate a single console, if possible */
 		    arg--;
-		    if (VT_IS_IN_USE(arg))
+		    if (VT_IS_IN_USE(arg) || arg == fg_console)
 		      return -EBUSY;
-		    if (arg) {			      /* leave 0 */
-			if (arg == fg_console)
-			  change_console(0);
-			vc_disallocate(arg);
-		    }
+		    if (arg)			      /* leave 0 */
+		      vc_disallocate(arg);
 		}
 		return 0;
 
@@ -801,10 +815,14 @@
 	case PIO_FONT:
 		if (!perm)
 			return -EPERM;
+		if (vt_cons[fg_console]->vc_mode != KD_TEXT)
+			return -EINVAL;
 		return con_set_font((char *)arg);
 		/* con_set_font() defined in console.c */
 
 	case GIO_FONT:
+		if (vt_cons[fg_console]->vc_mode != KD_TEXT)
+			return -EINVAL;
 		return con_get_font((char *)arg);
 		/* con_get_font() defined in console.c */
 
diff -u --recursive --new-file v1.1.75/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v1.1.75/linux/drivers/net/3c503.c	Tue Nov 22 15:41:11 1994
+++ linux/drivers/net/3c503.c	Sun Jan  1 16:22:34 1995
@@ -30,6 +30,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -145,8 +146,10 @@
     static unsigned version_printed = 0;
 
     /* Reset and/or avoid any lurking NE2000 */
-    if (inb(ioaddr + 0x408) == 0xff)
+    if (inb(ioaddr + 0x408) == 0xff) {
+    	udelay(1000);
 	return ENODEV;
+    }
 
     /* We verify that it's a 3C503 board by checking the first three octets
        of its ethernet address. */
diff -u --recursive --new-file v1.1.75/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c
--- v1.1.75/linux/drivers/net/hp-plus.c	Tue Nov 15 15:35:39 1994
+++ linux/drivers/net/hp-plus.c	Thu Dec 29 19:58:42 1994
@@ -27,15 +27,12 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
 
-#ifdef start_bh_atomic			/* This checks for kernels >= 1.1.0. */
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#else
-#include "dev.h"
-#endif
 
 #include "8390.h"
 extern struct device *init_etherdev(struct device *dev, int sizeof_private,
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c
--- v1.1.75/linux/drivers/scsi/aha1542.c	Thu Dec  1 19:15:04 1994
+++ linux/drivers/scsi/aha1542.c	Sun Jan  1 15:44:03 1995
@@ -149,27 +149,31 @@
    are ever sent. */
 static int aha1542_out(unsigned int base, unchar *cmdp, int len)
 {
+  unsigned long flags = 0;
+  
   if(len == 1) {
     while(1==1){
 	WAIT(STATUS(base), CDF, 0, CDF);
+	save_flags(flags);
 	cli();
-	if(inb(STATUS(base)) & CDF) {sti(); continue;}
+	if(inb(STATUS(base)) & CDF) {restore_flags(flags); continue;}
 	outb(*cmdp, DATA(base));
-	sti();
+	restore_flags(flags);
 	return 0;
       }
   } else {
+    save_flags(flags);
     cli();
     while (len--)
       {
 	WAIT(STATUS(base), CDF, 0, CDF);
 	outb(*cmdp++, DATA(base));
       }
-    sti();
+    restore_flags(flags);
   }
     return 0;
   fail:
-  sti();
+    restore_flags(flags);
     printk("aha1542_out failed(%d): ", len+1); aha1542_stat();
     return 1;
 }
@@ -178,16 +182,19 @@
    here */
 static int aha1542_in(unsigned int base, unchar *cmdp, int len)
 {
+    unsigned long flags;
+
+    save_flags(flags);
     cli();
     while (len--)
       {
 	  WAIT(STATUS(base), DF, DF, 0);
 	  *cmdp++ = inb(DATA(base));
       }
-    sti();
+    restore_flags(flags);
     return 0;
   fail:
-    sti();
+    restore_flags(flags);
     printk("aha1542_in failed(%d): ", len+1); aha1542_stat();
     return 1;
 }
@@ -197,16 +204,19 @@
    if the board will respond the the command we are about to send or not */
 static int aha1542_in1(unsigned int base, unchar *cmdp, int len)
 {
+    unsigned long flags;
+    
+    save_flags(flags);
     cli();
     while (len--)
       {
 	  WAITd(STATUS(base), DF, DF, 0, 100);
 	  *cmdp++ = inb(DATA(base));
       }
-    sti();
+    restore_flags(flags);
     return 0;
   fail:
-    sti();
+    restore_flags(flags);
     return 1;
 }
 
@@ -340,6 +350,7 @@
     void (*my_done)(Scsi_Cmnd *) = NULL;
     int errstatus, mbi, mbo, mbistatus;
     int number_serviced;
+    unsigned int flags;
     struct Scsi_Host * shost;
     Scsi_Cmnd * SCtmp;
     int irqno, * irqp, flag;
@@ -390,6 +401,7 @@
 
       aha1542_intr_reset(shost->io_port);
 
+      save_flags(flags);
       cli();
       mbi = HOSTDATA(shost)->aha1542_last_mbi_used + 1;
       if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
@@ -401,7 +413,7 @@
       } while (mbi != HOSTDATA(shost)->aha1542_last_mbi_used);
       
       if(mb[mbi].status == 0){
-	sti();
+	restore_flags(flags);
 	/* Hmm, no mail.  Must have read it the last time around */
 	if (!number_serviced && !needs_restart)
 	  printk("aha1542.c: interrupt received, but no mail.\n");
@@ -415,7 +427,7 @@
       mbistatus = mb[mbi].status;
       mb[mbi].status = 0;
       HOSTDATA(shost)->aha1542_last_mbi_used = mbi;
-      sti();
+      restore_flags(flags);
       
 #ifdef DEBUG
       {
@@ -498,6 +510,7 @@
     unchar *cmd = (unchar *) SCpnt->cmnd;
     unchar target = SCpnt->target;
     unchar lun = SCpnt->lun;
+    unsigned long flags;
     void *buff = SCpnt->request_buffer;
     int bufflen = SCpnt->request_bufflen;
     int mbo;
@@ -545,6 +558,7 @@
 /* Use the outgoing mailboxes in a round-robin fashion, because this
    is how the host adapter will scan for them */
 
+    save_flags(flags);
     cli();
     mbo = HOSTDATA(SCpnt->host)->aha1542_last_mbo_used + 1;
     if (mbo >= AHA1542_MAILBOXES) mbo = 0;
@@ -563,7 +577,7 @@
 			    screwing with this cdb. */
 
     HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo;    
-    sti();
+    restore_flags(flags);
 
 #ifdef DEBUG
     printk("Sending command (%d %x)...",mbo, done);
@@ -903,6 +917,7 @@
 {
     unsigned char dma_chan;
     unsigned char irq_level;
+    unsigned long flags;
     unsigned int base_io;
     int trans;
     struct Scsi_Host * shpnt = NULL;
@@ -974,6 +989,7 @@
 		    DEB(aha1542_stat());
 		    
 		    DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
+		    save_flags(flags);
 		    cli();
 		    if (request_irq(irq_level,aha1542_intr_handle, 0, "aha1542")) {
 			    printk("Unable to allocate IRQ for adaptec controller.\n");
@@ -1003,7 +1019,7 @@
 		    HOSTDATA(shpnt)->aha1542_last_mbi_used  = (2*AHA1542_MAILBOXES - 1);
 		    HOSTDATA(shpnt)->aha1542_last_mbo_used  = (AHA1542_MAILBOXES - 1);
 		    memset(HOSTDATA(shpnt)->SCint, 0, sizeof(HOSTDATA(shpnt)->SCint));
-		    sti();
+		    restore_flags(flags);
 #if 0
 		    DEB(printk(" *** READ CAPACITY ***\n"));
 		    
@@ -1083,6 +1099,7 @@
 #if 0
   int intval[3];
   unchar ahacmd = CMD_START_SCSI;
+  unsigned long flags;
   struct mailbox * mb;
   int mbi, mbo, i;
 
@@ -1090,6 +1107,7 @@
 	 inb(STATUS(SCpnt->host->io_port)),
 	 inb(INTRFLAGS(SCpnt->host->io_port)));
 
+  save_flags(flags);
   cli();
   mb = HOSTDATA(SCpnt->host)->mb;
   mbi = HOSTDATA(SCpnt->host)->aha1542_last_mbi_used + 1;
@@ -1100,7 +1118,7 @@
     mbi++;
     if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
   } while (mbi != HOSTDATA(SCpnt->host)->aha1542_last_mbi_used);
-  sti();
+  restore_flags(flags);
 
   if(mb[mbi].status) {
     printk("Lost interrupt discovered on irq %d - attempting to recover\n", 
@@ -1130,12 +1148,13 @@
 
     DEB(printk("aha1542_abort\n"));
 #if 0
+    save_flags(flags);
     cli();
     for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++)
       if (SCpnt == HOSTDATA(SCpnt->host)->SCint[mbo]){
 	mb[mbo].status = 2;  /* Abort command */
 	aha1542_out(SCpnt->host->io_port, &ahacmd, 1); /* start scsi command */
-	sti();
+	restore_flags(flags);
 	break;
       };
 #endif
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c
--- v1.1.75/linux/drivers/scsi/aha1740.c	Mon Dec  5 18:47:55 1994
+++ linux/drivers/scsi/aha1740.c	Sun Jan  1 15:44:03 1995
@@ -247,6 +247,7 @@
     unchar direction;
     unchar *cmd = (unchar *) SCpnt->cmnd;
     unchar target = SCpnt->target;
+    unsigned long flags;
     void *buff = SCpnt->request_buffer;
     int bufflen = SCpnt->request_bufflen;
     int ecbno;
@@ -279,6 +280,7 @@
 
     /* locate an available ecb */
 
+    save_flags(flags);
     cli();
     ecbno = aha1740_last_ecb_used + 1;		/* An optimization */
     if (ecbno >= AHA1740_ECBS) ecbno = 0;
@@ -296,7 +298,7 @@
     ecb[ecbno].cmdw = AHA1740CMD_INIT;	/* SCSI Initiator Command doubles as reserved flag */
 
     aha1740_last_ecb_used = ecbno;    
-    sti();
+    restore_flags(flags);
 
 #ifdef DEBUG
     printk("Sending command (%d %x)...",ecbno, done);
@@ -375,6 +377,7 @@
         ulong adrs;
 
 	DEB(printk("aha1740[%d] critical section\n",ecbno));
+	save_flags(flags);
 	cli();
 	if ( ! (inb(G2STAT) & G2STAT_MBXOUT) )
 	{
@@ -394,7 +397,7 @@
 	}
 	while ( inb(G2STAT) & G2STAT_BUSY );		/* And Again! */
 	outb(ATTN_START | (target & 7), ATTN);	/* Start it up */
-	sti();
+	restore_flags(flags);
 	DEB(printk("aha1740[%d] request queued.\n",ecbno));
     }
     else
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/buslogic.c linux/drivers/scsi/buslogic.c
--- v1.1.75/linux/drivers/scsi/buslogic.c	Thu Dec 29 20:15:57 1994
+++ linux/drivers/scsi/buslogic.c	Sun Jan  1 15:44:03 1995
@@ -240,28 +240,32 @@
 static int buslogic_out(unsigned int base, const unsigned char *cmdp,
 			size_t len)
 {
+    unsigned long flags = 0;
+    
     if (len == 1) {
 	for (;;) {
 	    WAIT_WHILE(STATUS(base), CPRBSY);
+	    save_flags(flags);
 	    cli();
 	    if (!(inb(STATUS(base)) & CPRBSY)) {
 		outb(*cmdp, COMMAND_PARAMETER(base));
-		sti();
+		restore_flags(flags);
 		return FALSE;
 	    }
-	    sti();
+	    restore_flags(flags);
 	}
     } else {
+	save_flags(flags);
 	cli();
 	while (len--) {
 	    WAIT_WHILE(STATUS(base), CPRBSY);
 	    outb(*cmdp++, COMMAND_PARAMETER(base));
 	}
-	sti();
+	restore_flags(flags);
     }
     return FALSE;
   fail:
-    sti();
+    restore_flags(flags);
     buslogic_printk("failed(%u): ", len + 1);
     buslogic_stat(base);
     return TRUE;
@@ -272,15 +276,18 @@
    sure whether the board will respond to the command we just sent. */
 static int buslogic_in(unsigned int base, unsigned char *cmdp, size_t len)
 {
+    unsigned long flags;
+    
+    save_flags(flags);
     cli();
     while (len--) {
 	WAIT_UNTIL_FAST(STATUS(base), DIRRDY);
 	*cmdp++ = inb(DATA_IN(base));
     }
-    sti();
+    restore_flags(flags);
     return FALSE;
   fail:
-    sti();
+    restore_flags(flags);
 #if (BUSLOGIC_DEBUG & BD_IO)
     buslogic_printk("failed(%u): ", len + 1);
     buslogic_stat(base);
@@ -421,6 +428,7 @@
     size_t mbi, mbo = 0;
     struct Scsi_Host *shpnt;
     Scsi_Cmnd *sctmp;
+    unsigned long flags;
     int irqno, base, flag;
     int needs_restart;
     struct mailbox *mb;
@@ -479,6 +487,7 @@
 
 	INTR_RESET(base);
 
+	save_flags(flags);
 	cli();
 
 	mbi = HOSTDATA(shpnt)->last_mbi_used + 1;
@@ -506,7 +515,7 @@
 	    HOSTDATA(shpnt)->last_mbi_used = mbi;
 	}
 
-	sti();
+	restore_flags(flags);
 
 	if (!found) {
 	    /* Hmm, no mail.  Must have read it the last time around. */
@@ -593,6 +602,7 @@
     void *buff = scpnt->request_buffer;
     int bufflen = scpnt->request_bufflen;
     int mbo;
+    unsigned long flags;
     struct mailbox *mb;
     struct ccb *ccb;
     struct Scsi_Host *shpnt = scpnt->host;
@@ -645,6 +655,7 @@
     /* Use the outgoing mailboxes in a round-robin fashion, because this
        is how the host adapter will scan for them. */
 
+    save_flags(flags);
     cli();
 
     mbo = HOSTDATA(shpnt)->last_mbo_used + 1;
@@ -663,7 +674,7 @@
     if (mb[mbo].status != MBX_NOT_IN_USE || HOSTDATA(shpnt)->sc[mbo]) {
 	/* ??? Instead of failing, should we enable OMBR interrupts and sleep
 	   until we get one? */
-	sti();
+	restore_flags(flags);
 	buslogic_printk("unable to find empty mailbox.\n");
 	goto fail;
     }
@@ -674,7 +685,7 @@
 
     HOSTDATA(shpnt)->last_mbo_used = mbo;
 
-    sti();
+    restore_flags(flags);
 
 #if (BUSLOGIC_DEBUG & BD_COMMAND)
     buslogic_printk("sending command (%d %08X)...", mbo, done);
@@ -1125,6 +1136,7 @@
     char bus_type;
     unsigned short max_sg;
     unsigned char bios_translation;
+    unsigned long flags;
     const unsigned char *bios;
     char *model;
     char *firmware_rev;
@@ -1239,11 +1251,12 @@
 	    buslogic_printk("enable interrupt channel %d.\n", irq);
 #endif
 
+	    save_flags(flags);
 	    cli();
 	    if (request_irq(irq, buslogic_interrupt, 0, "buslogic")) {
 		buslogic_printk("unable to allocate IRQ for "
 				"BusLogic controller.\n");
-		sti();
+		restore_flags(flags);
 		goto unregister;
 	    }
 
@@ -1252,7 +1265,7 @@
 		    buslogic_printk("unable to allocate DMA channel for "
 				    "BusLogic controller.\n");
 		    free_irq(irq);
-		    sti();
+		    restore_flags(flags);
 		    goto unregister;
 		}
 
@@ -1284,7 +1297,7 @@
 	    HOSTDATA(shpnt)->last_mbi_used = 2 * BUSLOGIC_MAILBOXES - 1;
 	    HOSTDATA(shpnt)->last_mbo_used = BUSLOGIC_MAILBOXES - 1;
 	    memset(HOSTDATA(shpnt)->sc, 0, sizeof HOSTDATA(shpnt)->sc);
-	    sti();
+	    restore_flags(flags);
 
 #if 0
 	    {
@@ -1369,12 +1382,14 @@
     static const unsigned char buscmd[] = { CMD_START_SCSI };
     struct mailbox *mb;
     size_t mbi, mbo;
+    unsigned long flags;
     unsigned int i;
 
     buslogic_printk("%X %X\n",
 		    inb(STATUS(scpnt->host->io_port)),
 		    inb(INTERRUPT(scpnt->host->io_port)));
 
+    save_flags(flags);
     cli();
     mb = HOSTDATA(scpnt->host)->mb;
     mbi = HOSTDATA(scpnt->host)->last_mbi_used + 1;
@@ -1388,7 +1403,7 @@
 	if (mbi >= 2 * BUSLOGIC_MAILBOXES)
 	    mbi = BUSLOGIC_MAILBOXES;
     } while (mbi != HOSTDATA(scpnt->host)->last_mbi_used);
-    sti();
+    restore_flags(flags);
 
     if (mb[mbi].status != MBX_NOT_IN_USE) {
 	buslogic_printk("lost interrupt discovered on irq %d"
@@ -1427,6 +1442,7 @@
 #if 1
     /* This section of code should be used carefully - some devices cannot
        abort a command, and this merely makes it worse. */
+    save_flags(flags);
     cli();
     for (mbo = 0; mbo < BUSLOGIC_MAILBOXES; mbo++)
 	if (scpnt == HOSTDATA(scpnt->host)->sc[mbo]) {
@@ -1434,7 +1450,7 @@
 	    buslogic_out(scpnt->host->io_port, buscmd, sizeof buscmd);
 	    break;
 	}
-    sti();
+    restore_flags(flags);
 #endif
 
     return SCSI_ABORT_SNOOZE;
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/constants.c linux/drivers/scsi/constants.c
--- v1.1.75/linux/drivers/scsi/constants.c	Fri Aug 19 08:54:04 1994
+++ linux/drivers/scsi/constants.c	Thu Dec 29 19:58:42 1994
@@ -78,7 +78,7 @@
 
 static void print_opcode(int opcode) {
   const char **table = commands[ group(opcode) ];
-  switch ((int) table) {
+  switch ((unsigned long) table) {
   case RESERVED_GROUP:
   	printk("%s(0x%02x) ", reserved, opcode); 
   	break;
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c
--- v1.1.75/linux/drivers/scsi/in2000.c	Tue Nov 29 18:51:26 1994
+++ linux/drivers/scsi/in2000.c	Sun Jan  1 15:44:03 1995
@@ -405,6 +405,7 @@
     unchar *cmd = (unchar *) SCpnt->cmnd;
     unchar target = SCpnt->target;
     void *buff = SCpnt->request_buffer;
+    unsigned long flags;
     int bufflen = SCpnt->request_bufflen;
     int timeout, size, loop;
     int i;
@@ -511,6 +512,7 @@
     /*
      * Set up the FIFO
      */
+    save_flags(flags);
     cli();		/* so FIFO init waits till WD set */
     outb(0,INFRST);
     if ( direction == 1 )
@@ -538,7 +540,7 @@
     outb(COMMAND,INSTAT);
     outb(0,INNLED);
     outb(8,INDATA);		/* Select w/ATN & Transfer */
-    sti();			/* let the intrpt rip */
+    restore_flags(flags);			/* let the intrpt rip */
     return 0;
 }
 
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.1.75/linux/drivers/scsi/scsi.c	Thu Dec 29 20:15:57 1994
+++ linux/drivers/scsi/scsi.c	Sun Jan  1 15:44:03 1995
@@ -683,6 +683,7 @@
   int dev = -1;
   struct request * req = NULL;
   int tablesize;
+  unsigned int flags;
   struct buffer_head * bh, *bhp;
   struct Scsi_Host * host;
   Scsi_Cmnd * SCpnt = NULL;
@@ -721,15 +722,16 @@
       };
       SCpnt = SCpnt->next;
     };
+    save_flags(flags);
     cli();
     /* See if this request has already been queued by an interrupt routine */
     if (req && ((req->dev < 0) || (req->dev != dev))) {
-      sti();
+      restore_flags(flags);
       return NULL;
     };
     if (!SCpnt || SCpnt->request.dev >= 0)  /* Might have changed */
       {
-	sti();
+	restore_flags(flags);
 	if(!wait) return NULL;
 	if (!SCwait) {
 	  printk("Attempt to allocate device target %d, lun %d\n",
@@ -775,7 +777,7 @@
 	  SCpnt->request.dev = 0xffff; /* Busy */
 	  SCpnt->request.sem = NULL;  /* And no one is waiting for this to complete */
 	};
-	sti();
+	restore_flags(flags);
 	break;
       };
   };
@@ -867,10 +869,13 @@
 
 static void scsi_request_sense (Scsi_Cmnd * SCpnt)
 	{
+	unsigned int flags;
+	
+	save_flags(flags);
 	cli();
 	SCpnt->flags |= WAS_SENSE | ASKED_FOR_SENSE;
 	update_timeout(SCpnt, SENSE_TIMEOUT);
-	sti();
+	restore_flags(flags);
 	
 
 	memcpy ((void *) SCpnt->cmnd , (void *) generic_sense,
@@ -900,6 +905,7 @@
 		  int timeout, int retries 
 		   )
         {
+	unsigned long flags;
 	struct Scsi_Host * host = SCpnt->host;
 
 #ifdef DEBUG
@@ -933,6 +939,7 @@
 
         for(;;) {
 
+	  save_flags(flags);
           cli();
 
 	  if (host->can_queue &&
@@ -947,7 +954,7 @@
                                            && host != host_active) 
                 host_next = host;
 
-	     sti();
+	     restore_flags(flags);
 	     SCSI_SLEEP(&host->host_wait, 
                        ((host->block && host_active && host != host_active) ||
                         (host->block && host_next && host != host_next) ||
@@ -970,7 +977,7 @@
                 max_active++;
                 }
 
-	     sti();
+	     restore_flags(flags);
 	     break;
 	     }
           }
@@ -1488,10 +1495,12 @@
 int scsi_abort (Scsi_Cmnd * SCpnt, int why, int pid)
 	{
 	int oldto;
+	unsigned long flags;
 	struct Scsi_Host * host = SCpnt->host;
 	
 	while(1)	
 		{
+		save_flags(flags);
 		cli();
 
 		/*
@@ -1499,13 +1508,13 @@
 		 * on a different command forget it.
 		 */
 		if (SCpnt->request.dev == -1 || pid != SCpnt->pid) {
-		  sti();
+		  restore_flags(flags);
 		  return 0;
 		}
 
 		if (SCpnt->internal_timeout & IN_ABORT) 
 			{
-			sti();
+			restore_flags(flags);
 			while (SCpnt->internal_timeout & IN_ABORT);
 			}
 		else
@@ -1521,7 +1530,7 @@
 				 " the bus was reset\n", SCpnt->target, SCpnt->lun);
 			}
 			
-			sti();
+			restore_flags(flags);
 			if (!host->host_busy) {
 			  SCpnt->internal_timeout &= ~IN_ABORT;
 			  update_timeout(SCpnt, oldto);
@@ -1543,10 +1552,11 @@
 						 this is too severe */
 			case SCSI_ABORT_SNOOZE:
 			  if(why == DID_TIME_OUT) {
+			    save_flags(flags);
 			    cli();
 			    SCpnt->internal_timeout &= ~IN_ABORT;
 			    if(SCpnt->flags & WAS_TIMEDOUT) {
-			      sti();
+			      restore_flags(flags);
 			      return 1; /* Indicate we cannot handle this.
 					   We drop down into the reset handler
 					   and try again */
@@ -1555,14 +1565,15 @@
 			      oldto = SCpnt->timeout_per_command;
 			      update_timeout(SCpnt, oldto);
 			    }
-			    sti();
+			    restore_flags(flags);
 			  }
 			  return 0;
 			case SCSI_ABORT_PENDING:
 			  if(why != DID_TIME_OUT) {
+			    save_flags(flags);
 			    cli();
 			    update_timeout(SCpnt, oldto);
-			    sti();
+			    restore_flags(flags);
 			  }
 			  return 0;
 			case SCSI_ABORT_SUCCESS:
@@ -1584,6 +1595,7 @@
 int scsi_reset (Scsi_Cmnd * SCpnt)
 	{
 	int temp, oldto;
+	unsigned long flags;
 	Scsi_Cmnd * SCpnt1;
 	struct Scsi_Host * host = SCpnt->host;
 	
@@ -1591,10 +1603,11 @@
 	printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n",host->host_no);
 #endif
 	while (1) {
-		cli();	
+		save_flags(flags);
+		cli();
 		if (SCpnt->internal_timeout & IN_RESET)
 			{
-			sti();
+			restore_flags(flags);
 			while (SCpnt->internal_timeout & IN_RESET);
 			}
 		else
@@ -1604,7 +1617,7 @@
 					
 			if (host->host_busy)
 				{	
-				sti();
+				restore_flags(flags);
 				SCpnt1 = host->host_queue;
 				while(SCpnt1) {
 				  if (SCpnt1->request.dev > 0) {
@@ -1629,7 +1642,7 @@
                                    host_next = NULL;
                                    }
 	
-				sti();
+				restore_flags(flags);
 				temp = host->hostt->reset(SCpnt);
 				host->last_reset = jiffies;
 				host->host_busy--;
@@ -1648,10 +1661,11 @@
 #endif
 			switch(temp) {
 			case SCSI_RESET_SUCCESS:
+			  save_flags(flags);
 			  cli();
 			  SCpnt->internal_timeout &= ~IN_RESET;
 			  update_timeout(SCpnt, oldto);
-			  sti();
+			  restore_flags(flags);
 			  return 0;
 			case SCSI_RESET_PENDING:
 			  return 0;
@@ -1665,10 +1679,11 @@
 			     so that this command does not time out any more,
 			     and we return 1 so that we get a message on the
 			     screen. */
+			  save_flags(flags);
 			  cli();
 			  SCpnt->internal_timeout &= ~IN_RESET;
 			  update_timeout(SCpnt, 0);
-			  sti();
+			  restore_flags(flags);
 			  /* If you snooze, you lose... */
 			case SCSI_RESET_ERROR:
 			default:
@@ -1688,10 +1703,12 @@
 	*/
 
 	int timed_out, pid;
+	unsigned long flags;
 	struct Scsi_Host * host;
 	Scsi_Cmnd * SCpnt = NULL;
 
 	do 	{	
+		save_flags(flags);
 		cli();
 
 		update_timeout(NULL, 0);
@@ -1707,14 +1724,15 @@
 		      {
 			SCpnt->timeout = 0;
 			pid = SCpnt->pid;
-			sti();
+			restore_flags(flags);
 			scsi_times_out(SCpnt, pid);
 			++timed_out; 
+			save_flags(flags);
 			cli();
 		      }
 		};
 	      } while (timed_out);	
-	sti();
+	restore_flags(flags);
       }
 
 /*
@@ -1729,9 +1747,11 @@
 	{
 	unsigned int least, used;
 	unsigned int oldto;
+	unsigned long flags;
 	struct Scsi_Host * host;
 	Scsi_Cmnd * SCpnt = NULL;
 
+	save_flags(flags);
 	cli();
 
 /* 
@@ -1780,7 +1800,7 @@
 		timer_table[SCSI_TIMER].expires = time_start = time_elapsed = 0;
 		timer_active &= ~(1 << SCSI_TIMER);
 		}	
-	sti();
+	restore_flags(flags);
 	return oldto;
 	}		
 
@@ -1822,15 +1842,15 @@
 
 int scsi_free(void *obj, unsigned int len)
 {
-  int offset;
   int page, sector, nbits, mask;
+  long offset;
   unsigned long flags;
 
 #ifdef DEBUG
   printk("Sfree %x %d\n",obj, len);
 #endif
 
-  offset = ((int) obj) - ((int) dma_malloc_buffer);
+  offset = ((unsigned long) obj) - ((unsigned long) dma_malloc_buffer);
 
   if (offset < 0) panic("Bad offset");
   page = offset >> 13;
@@ -1859,14 +1879,14 @@
    They act line a malloc function, but they simply take memory from the
    pool */
 
-static unsigned int scsi_init_memory_start = 0;
+static unsigned long scsi_init_memory_start = 0;
 int scsi_loadable_module_flag; /* Set after we scan builtin drivers */
 
 void * scsi_init_malloc(unsigned int size)
 {
-  unsigned int retval;
+  unsigned long retval;
   if(scsi_loadable_module_flag) {
-    retval = (unsigned int) kmalloc(size, GFP_ATOMIC);
+    retval = (unsigned long) kmalloc(size, GFP_ATOMIC);
   } else {
     retval = scsi_init_memory_start;
     scsi_init_memory_start += size;
@@ -1878,11 +1898,11 @@
 void scsi_init_free(char * ptr, unsigned int size)
 { /* FIXME - not right.  We need to compare addresses to see whether this was
      kmalloc'd or not */
-  if((unsigned int) ptr < scsi_loadable_module_flag) {
+  if((unsigned long) ptr < scsi_loadable_module_flag) {
     kfree(ptr);
   } else {
-    if(((unsigned int) ptr) + size == scsi_init_memory_start)
-      scsi_init_memory_start = (unsigned int) ptr;
+    if(((unsigned long) ptr) + size == scsi_init_memory_start)
+      scsi_init_memory_start = (unsigned long) ptr;
   }
 }
 
@@ -2049,6 +2069,7 @@
   int pcount;
   struct Scsi_Host * shpnt;
   struct Scsi_Host * host = NULL;
+  unsigned long flags;
   Scsi_Device * SDpnt;
   Scsi_Cmnd * SCpnt;
   struct Scsi_Device_Template * sdtpnt;
@@ -2166,6 +2187,8 @@
 	  
 
 	  /* When we dick with the actual DMA list, we need to protect things */
+
+	  save_flags(flags);
 	  cli();
 	  memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3);
 	  scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
@@ -2178,7 +2201,7 @@
 	  dma_malloc_pages = new_dma_malloc_pages;
 	  dma_sectors = new_dma_sectors;
 	  need_isa_buffer = new_need_isa_buffer;
-	  sti();
+	  restore_flags(flags);
 
 	  
 	}
@@ -2198,6 +2221,7 @@
   Scsi_Host_Template * SHT, *SHTp;
   Scsi_Device *sdpnt, * sdppnt, * sdpnt1;
   Scsi_Cmnd * SCpnt;
+  unsigned long flags;
   struct Scsi_Device_Template * sdtpnt;
   struct Scsi_Host * shpnt, *sh1;
   int pcount;
@@ -2213,9 +2237,10 @@
       if (shpnt->hostt != tpnt) continue;
       for(SCpnt = shpnt->host_queue; SCpnt; SCpnt = SCpnt->next)
 	{
+	  save_flags(flags);
 	  cli();
 	  if(SCpnt->request.dev != -1) {
-	    sti();
+	    restore_flags(flags);
 	    for(SCpnt = shpnt->host_queue; SCpnt; SCpnt = SCpnt->next)
 	      if(SCpnt->request.dev == 0xffe0) SCpnt->request.dev = -1;
 	    printk("Device busy???\n");
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v1.1.75/linux/drivers/scsi/scsi.h	Tue Dec 27 09:56:46 1994
+++ linux/drivers/scsi/scsi.h	Sun Jan  1 15:44:03 1995
@@ -579,7 +579,7 @@
 #define INIT_SCSI_REQUEST \
 	if (!CURRENT) {\
 		CLEAR_INTR; \
-		sti();   \
+		restore_flags(flags);   \
 		return; \
 	} \
 	if (MAJOR(CURRENT->dev) != MAJOR_NR) \
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c
--- v1.1.75/linux/drivers/scsi/scsi_debug.c	Sun Jul 10 09:09:38 1994
+++ linux/drivers/scsi/scsi_debug.c	Sun Jan  1 15:44:03 1995
@@ -164,6 +164,7 @@
     struct scatterlist * sgpnt;
     int target = SCpnt->target;
     int bufflen = SCpnt->request_bufflen;
+    unsigned long flags;
     int i;
     sgcount = 0;
     sgpnt = NULL;
@@ -372,7 +373,8 @@
       return 0;
     };
 
-    cli();
+   save_flags(flags); 
+   cli();
     for(i=0;i<SCSI_DEBUG_MAILBOXES; i++){
       if (SCint[i] == 0) break;
     };
@@ -405,7 +407,7 @@
     };
 
     SCpnt->result = scsi_debug_errsts;
-    sti();
+    restore_flags(flags);
 
 #if 0
     printk("Sending command (%d %x %d %d)...", i, done, timeout[i],jiffies);
@@ -441,7 +443,8 @@
     Scsi_Cmnd * SCtmp;
     int i, pending;
     void (*my_done)(Scsi_Cmnd *); 
-   int to;
+    unsigned long flags;
+    int to;
 
 #ifndef IMMEDIATE
     timer_table[SCSI_DEBUG_TIMER].expires = 0;
@@ -449,6 +452,7 @@
 #endif
 
   repeat:
+    save_flags(flags);
     cli();
     for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
       if (SCint[i] == 0) continue;
@@ -466,7 +470,7 @@
       for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
 	if (SCint[i] == 0) continue;
 	if (timeout[i] == 0) continue;
-	if (timeout[i] <= jiffies) {sti(); goto repeat;};
+	if (timeout[i] <= jiffies) {restore_flags(flags); goto repeat;};
 	if (timeout[i] > jiffies) {
 	  if (pending > timeout[i]) pending = timeout[i];
 	  continue;
@@ -477,7 +481,7 @@
 	  (pending <= jiffies ? jiffies+1 : pending);
 	timer_active |= 1 << SCSI_DEBUG_TIMER;
       };
-      sti();
+      restore_flags(flags);
 #endif
       return;
     };
@@ -490,7 +494,7 @@
       timeout[i] = 0;
       SCtmp = (Scsi_Cmnd *) SCint[i];
       SCint[i] = NULL;
-      sti();
+      restore_flags(flags);
 
       if (!my_done) {
 	printk("scsi_debug_intr_handle: Unexpected interrupt\n"); 
@@ -525,17 +529,20 @@
 {
     int j;
     void (*my_done)(Scsi_Cmnd *);
+    unsigned long flags;
+
     DEB(printk("scsi_debug_abort\n"));
     SCpnt->result = SCpnt->abort_reason << 16;
     for(j=0;j<SCSI_DEBUG_MAILBOXES; j++) {
       if(SCpnt == SCint[j]) {
 	my_done = do_done[j];
 	my_done(SCpnt);
+        save_flags(flags);
 	cli();
 	timeout[j] = 0;
 	SCint[j] = NULL;
 	do_done[j] = NULL;
-	sti();
+	restore_flags(flags);
       };
     };
     return 0;
@@ -553,6 +560,8 @@
 int scsi_debug_reset(Scsi_Cmnd * SCpnt)
 {
     int i;
+    unsigned long flags;
+
     void (*my_done)(Scsi_Cmnd *);
     DEB(printk("scsi_debug_reset called\n"));
     for(i=0;i<SCSI_DEBUG_MAILBOXES; i++) {
@@ -560,11 +569,12 @@
       SCint[i]->result = DID_ABORT << 16;
       my_done = do_done[i];
       my_done(SCint[i]);
+      save_flags(flags);
       cli();
       SCint[i] = NULL;
       do_done[i] = NULL;
       timeout[i] = 0;
-      sti();
+      restore_flags(flags);
     };
     return 0;
 }
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v1.1.75/linux/drivers/scsi/sd.c	Thu Dec 29 20:15:57 1994
+++ linux/drivers/scsi/sd.c	Sun Jan  1 15:44:03 1995
@@ -333,11 +333,14 @@
 {
   Scsi_Cmnd * SCpnt = NULL;
   struct request * req = NULL;
+  unsigned long flags;
   int flag = 0;
+
   while (1==1){
+    save_flags(flags);
     cli();
     if (CURRENT != NULL && CURRENT->dev == -1) {
-      sti();
+      restore_flags(flags);
       return;
     };
 
@@ -359,7 +362,7 @@
       SCpnt = allocate_device(&CURRENT,
 			      rscsi_disks[DEVICE_NR(MINOR(CURRENT->dev))].device, 0); 
     else SCpnt = NULL;
-    sti();
+    restore_flags(flags);
 
 /* This is a performance enhancement.  We dig down into the request list and
    try and find a queueable request (i.e. device not busy, and host able to
@@ -371,6 +374,7 @@
     if (!SCpnt && sd_template.nr_dev > 1){
       struct request *req1;
       req1 = NULL;
+      save_flags(flags);
       cli();
       req = CURRENT;
       while(req){
@@ -386,7 +390,7 @@
 	else
 	  req1->next = req->next;
       };
-      sti();
+      restore_flags(flags);
     };
     
     if (!SCpnt) return; /* Could not find anything to do */
@@ -1150,6 +1154,7 @@
 int revalidate_scsidisk(int dev, int maxusage){
 	  int target, major;
 	  struct gendisk * gdev;
+	  unsigned long flags;
 	  int max_p;
 	  int start;
 	  int i;
@@ -1157,14 +1162,15 @@
 	  target =  DEVICE_NR(MINOR(dev));
 	  gdev = &GENDISK_STRUCT;
 
+	  save_flags(flags);
 	  cli();
 	  if (DEVICE_BUSY || USAGE > maxusage) {
-	    sti();
+	    restore_flags(flags);
 	    printk("Device busy for revalidation (usage=%d)\n", USAGE);
 	    return -EBUSY;
 	  };
 	  DEVICE_BUSY = 1;
-	  sti();
+	  restore_flags(flags);
 
 	  max_p = gdev->max_p;
 	  start = target << gdev->minor_shift;
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v1.1.75/linux/drivers/scsi/sr.c	Thu Dec  1 19:15:04 1994
+++ linux/drivers/scsi/sr.c	Sun Jan  1 15:44:03 1995
@@ -431,12 +431,14 @@
 {
   Scsi_Cmnd * SCpnt = NULL;
   struct request * req = NULL;
+  unsigned long flags;
   int flag = 0;
 
   while (1==1){
+    save_flags(flags);
     cli();
     if (CURRENT != NULL && CURRENT->dev == -1) {
-      sti();
+      restore_flags(flags);
       return;
     };
     
@@ -446,7 +448,7 @@
       SCpnt = allocate_device(&CURRENT,
 			      scsi_CDs[DEVICE_NR(MINOR(CURRENT->dev))].device, 0); 
     else SCpnt = NULL;
-    sti();
+    restore_flags(flags);
 
 /* This is a performance enhancement.  We dig down into the request list and
    try and find a queueable request (i.e. device not busy, and host able to
@@ -458,6 +460,7 @@
     if (!SCpnt && sr_template.nr_dev > 1){
       struct request *req1;
       req1 = NULL;
+      save_flags(flags);
       cli();
       req = CURRENT;
       while(req){
@@ -473,7 +476,7 @@
 	else
 	  req1->next = req->next;
       };
-      sti();
+      restore_flags(flags);
     };
     
     if (!SCpnt)
diff -u --recursive --new-file v1.1.75/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v1.1.75/linux/drivers/scsi/st.c	Tue Dec 27 09:56:47 1994
+++ linux/drivers/scsi/st.c	Sun Jan  1 15:44:03 1995
@@ -195,17 +195,19 @@
 {
   Scsi_Tape * STp;
   ST_buffer * STbuffer;
+  unsigned long flags;
 
   STp = &(scsi_tapes[dev]);
   STbuffer = STp->buffer;
 
+  save_flags(flags);
   cli();
   if (STbuffer->last_result < 0) {
     STbuffer->writing = (- STbuffer->writing);
     sleep_on( &(STp->waiting) );
     STbuffer->writing = (- STbuffer->writing);
   }
-  sti();
+  restore_flags(flags);
 
   if (STbuffer->writing < STbuffer->buffer_bytes)
     memcpy(STbuffer->b_data,
diff -u --recursive --new-file v1.1.75/linux/fs/msdos/buffer.c linux/fs/msdos/buffer.c
--- v1.1.75/linux/fs/msdos/buffer.c	Thu Dec 29 20:15:57 1994
+++ linux/fs/msdos/buffer.c	Thu Dec 29 20:13:17 1994
@@ -28,7 +28,7 @@
 					in the middle of a hardware block. The bad news is
 					that a hardware sector may hold data own by two
 					different files. This means that the hardware sector
-					must be read, patch and written allmost all the time.
+					must be read, patch and written almost all the time.
 
 					Needless to say that it kills write performance
 					on all OS.
@@ -43,8 +43,8 @@
 					hidden though!
 				*/
 				/*
-					THe memset is there only to catch errors. The msdos
-					fs is only unsing b_data
+					The memset is there only to catch errors. The msdos
+					fs is only using b_data
 				*/
 				memset (ret,0,sizeof(*ret));
 				ret->b_data = real->b_data;
@@ -69,7 +69,7 @@
 			A write is always preceded by a read of the complete block
 			(large hardware sector size). This defeat write performance.
 			There is a possibility to optimize this when writing large
-			chunk by making sure we are filling large block. Volunter ?
+			chunk by making sure we are filling large block. Volunteer ?
 		*/
 		ret = msdos_bread (sb,block);
 	}
diff -u --recursive --new-file v1.1.75/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.1.75/linux/fs/proc/array.c	Thu Dec 29 20:15:57 1994
+++ linux/fs/proc/array.c	Mon Jan  2 15:09:31 1995
@@ -213,11 +213,29 @@
 
 	uptime = jiffies;
 	idle = task[0]->utime + task[0]->stime;
+
+	/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
+	   that would overflow about every five days at HZ == 100.
+	   Therefore the identity a = (a / b) * b + a % b is used so that it is
+	   calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
+	   The part in front of the '+' always evaluates as 0 (mod 100). All divisions
+	   in the above formulas are truncating. For HZ being a power of 10, the
+	   calculations simplify to the version in the #else part (if the printf
+	   format is adapted to the same number of digits as zeroes in HZ.
+	 */
+#if HZ!=100
+	return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
+		uptime / HZ,
+		(((uptime % HZ) * 100) / HZ) % 100,
+		idle / HZ,
+		(((idle % HZ) * 100) / HZ) % 100);
+#else
 	return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
 		uptime / HZ,
 		uptime % HZ,
 		idle / HZ,
 		idle % HZ);
+#endif
 }
 
 static int get_meminfo(char * buffer)
diff -u --recursive --new-file v1.1.75/linux/fs/select.c linux/fs/select.c
--- v1.1.75/linux/fs/select.c	Tue Aug  9 09:33:00 1994
+++ linux/fs/select.c	Mon Jan  2 07:58:49 1995
@@ -76,7 +76,7 @@
 	if ((fops = file->f_op) && (select = fops->select))
 		return select(inode, file, flag, wait)
 		    || (wait && select(inode, file, flag, NULL));
-	if (S_ISREG(inode->i_mode))
+	if (flag != SEL_EX)
 		return 1;
 	return 0;
 }
diff -u --recursive --new-file v1.1.75/linux/fs/super.c linux/fs/super.c
--- v1.1.75/linux/fs/super.c	Tue Dec 27 09:56:47 1994
+++ linux/fs/super.c	Mon Jan  2 14:20:58 1995
@@ -389,7 +389,7 @@
 			return -EACCES;
 		}
 	} else {
-		if (!inode || !inode->i_sb || inode != inode->i_sb->s_mounted) {
+		if (!inode->i_sb || inode != inode->i_sb->s_mounted) {
 			iput(inode);
 			return -EINVAL;
 		}
@@ -584,6 +584,7 @@
 	if (!fstype)		
 		return -ENODEV;
 	t = fstype->name;
+	fops = NULL;
 	if (fstype->requires_dev) {
 		retval = namei(dev_name,&inode);
 		if (retval)
@@ -601,22 +602,27 @@
 			iput(inode);
 			return -ENXIO;
 		}
+		fops = get_blkfops(MAJOR(dev));
+		if (!fops) {
+			iput(inode);
+			return -ENOTBLK;
+		}
+		if (fops->open) {
+			struct file dummy;	/* allows read-write or read-only flag */
+			memset(&dummy, 0, sizeof(dummy));
+			dummy.f_inode = inode;
+			dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3;
+			retval = fops->open(inode, &dummy);
+			if (retval) {
+				iput(inode);
+				return retval;
+			}
+		}
+
 	} else {
 		if (!(dev = get_unnamed_dev()))
 			return -EMFILE;
 		inode = NULL;
-	}
-	fops = get_blkfops(MAJOR(dev));
-	if (fops && fops->open) {
-		struct file dummy;	/* allows read-write or read-only flag */
-		memset(&dummy, 0, sizeof(dummy));
-		dummy.f_inode = inode;
-		dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3;
-		retval = fops->open(inode, &dummy);
-		if (retval) {
-			iput(inode);
-			return retval;
-		}
 	}
 	page = 0;
 	if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) {
diff -u --recursive --new-file v1.1.75/linux/include/asm-alpha/dma.h linux/include/asm-alpha/dma.h
--- v1.1.75/linux/include/asm-alpha/dma.h	Mon Nov 28 14:21:46 1994
+++ linux/include/asm-alpha/dma.h	Sun Jan  1 19:49:18 1995
@@ -265,7 +265,7 @@
 
 
 /* These are in kernel/dma.c: */
-extern int request_dma(unsigned int dmanr, char * deviceID);	/* reserve a DMA channel */
+extern int request_dma(unsigned int dmanr, char * device_id);	/* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);	/* release it again */
 
 
diff -u --recursive --new-file v1.1.75/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v1.1.75/linux/include/asm-alpha/processor.h	Thu Dec 29 20:15:58 1994
+++ linux/include/asm-alpha/processor.h	Mon Jan  2 07:36:19 1995
@@ -1,11 +1,11 @@
 /*
- * include/asm-i386/processor.h
+ * include/asm-alpha/processor.h
  *
  * Copyright (C) 1994 Linus Torvalds
  */
 
-#ifndef __ASM_I386_PROCESSOR_H
-#define __ASM_I386_PROCESSOR_H
+#ifndef __ASM_ALPHA_PROCESSOR_H
+#define __ASM_ALPHA_PROCESSOR_H
 
 /*
  * Bus types
@@ -30,4 +30,4 @@
 	0, 0, 0, \
 }
 
-#endif /* __ASM_I386_PROCESSOR_H */
+#endif /* __ASM_ALPHA_PROCESSOR_H */
diff -u --recursive --new-file v1.1.75/linux/include/asm-alpha/segment.h linux/include/asm-alpha/segment.h
--- v1.1.75/linux/include/asm-alpha/segment.h	Mon Nov 28 14:21:46 1994
+++ linux/include/asm-alpha/segment.h	Mon Jan  2 09:28:27 1995
@@ -63,6 +63,16 @@
 
 #define memcpy_tofs(to, from, n) memcpy((to),(from),(n))
 
+/*
+ * For segmented arhictectures, these are used to specify which segment
+ * to use for the above functions.
+ *
+ * The alpha is not segmented, so these are just dummies.
+ */
+
+#define KERNEL_DS 0
+#define USER_DS 1
+
 static inline unsigned long get_fs(void)
 {
 	return 0;
diff -u --recursive --new-file v1.1.75/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- v1.1.75/linux/include/asm-alpha/system.h	Thu Dec 29 20:15:58 1994
+++ linux/include/asm-alpha/system.h	Thu Dec 29 19:58:42 1994
@@ -62,6 +62,11 @@
 #define PAL_rtsys	61
 #define PAL_rti		63
 
+#ifndef __ASSEMBLY__
+
+extern void wrent(void *, unsigned long);
+extern void wrkgp(unsigned long);
+
 #define halt() __asm__ __volatile__(".long 0");
 #define move_to_user_mode() halt()
 #define switch_to(x) halt()
@@ -120,5 +125,7 @@
 {
 	return (void *) xchg_u64((long *) m, (unsigned long) val);
 }
+
+#endif /* __ASSEMBLY__ */
 
 #endif
diff -u --recursive --new-file v1.1.75/linux/include/asm-i386/dma.h linux/include/asm-i386/dma.h
--- v1.1.75/linux/include/asm-i386/dma.h	Thu Dec  1 19:15:05 1994
+++ linux/include/asm-i386/dma.h	Sun Jan  1 19:49:18 1995
@@ -264,7 +264,7 @@
 
 
 /* These are in kernel/dma.c: */
-extern int request_dma(unsigned int dmanr, char * deviceID);	/* reserve a DMA channel */
+extern int request_dma(unsigned int dmanr, char * device_id);	/* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);	/* release it again */
 
 
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/asi.h linux/include/asm-sparc/asi.h
--- v1.1.75/linux/include/asm-sparc/asi.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/asi.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,37 @@
+#ifndef _SPARC_ASI_H
+#define _SPARC_ASI_H
+
+/* asi.h:  Address Space Indentifier values for the sparc.
+
+   Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+*/
+
+/* These are sun4c, beware on other architectures. Although things should
+ * be similar under regular sun4's.
+ */
+
+#define ASI_NULL1        0x0
+#define ASI_NULL2        0x1
+
+/* sun4c and sun4 control registers and mmu/vac ops */
+#define ASI_CONTROL          0x2
+#define ASI_SEGMAP           0x3
+#define ASI_PTE              0x4
+#define ASI_HWFLUSHSEG       0x5      /* These are to initiate hw flushes of the cache */
+#define ASI_HWFLUSHPAGE      0x6
+#define ASI_HWFLUSHCONTEXT   0x7
+
+
+#define ASI_USERTXT      0x8
+#define ASI_KERNELTXT    0x9
+#define ASI_USERDATA     0xa
+#define ASI_KERNELDATA   0xb
+
+/* VAC Cache flushing on sun4c and sun4 */
+
+#define ASI_FLUSHSEG     0xc      /* These are for "software" flushes of the cache */
+#define ASI_FLUSHPG      0xd
+#define ASI_FLUSHCTX     0xe
+
+
+#endif /* _SPARC_ASI_H */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h
--- v1.1.75/linux/include/asm-sparc/bitops.h	Thu Dec 15 11:01:55 1994
+++ linux/include/asm-sparc/bitops.h	Mon Jan  2 15:26:45 1995
@@ -9,67 +9,167 @@
 /* Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
  * is in the highest of the four bytes and bit '31' is the high bit
  * within the first byte. Sparc is BIG-Endian. Unless noted otherwise
- * all bit-ops return 0 is bit previously clear and != 0 otherwise.
+ * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
+ */
+
+/* For now, the sun4c implementation will disable and enable traps
+ * in order to insure atomicity. Things will have to be different
+ * for sun4m (ie. SMP) no doubt.
  */
 
 extern __inline__ unsigned int set_bit(unsigned int nr, void *addr)
 {
+  register unsigned long retval, tmp, mask, psr;
 
-  __asm__ __volatile__(
-		       "or %g0, %g0, %o2\n\t"
-		       "or %g0, %g0, %o3\n\t"
-		       "or %g0, %o0, %o4\n\t"
-		       "srl %o4, 0x5, %o4\n\t"
-		       "add %o1, %o4, %o1\n\t"
-		       "or %g0, 0x1, %o5"
-		       "or %g0, 0x1f, %o6"
-		       "and %o6, %o5, %o6"
-		       "sll %o5, %o6, %o2"
-		       "ld [%o1], %o5\n\t"
-		       "and %o5, %o2, %o0"
-		       "or %o5, %o2, %o5"
-		       "st %o5, [%o1]");
+  __asm__ __volatile__("or %%g0, 0x1, %3\n\t"     /* produce the mask */
+		       "sll %3, %4, %3\n\t"
+		       "rd %%psr, %5\n\t"         /* read the psr */
+		       "andn %5, 0x20, %5\n\t"    /* clear ET bit */
+		       "wr %5, 0x0, %%psr\n\t"    /* traps disabled */
+		       "ld [%1], %2\n\t"          /* critical section */
+		       "and %3, %2, %0\n\t"
+		       "or  %3, %2, %2\n\t"
+		       "st  %2, [%1]\n\t"
+		       "wr %5, 0x20, %%psr\n\t" : /* re-enable traps */
+                       "=r" (retval) :
+                       "r" (addr), "r" (tmp=0), "r" (mask=0),
+                       "r" (nr), "r" (psr=0));
 
-  return nr; /* confuse gcc :-) */
+  return retval; /* confuse gcc :-) */
 
 }
 
 extern __inline__ unsigned int clear_bit(unsigned int nr, void *addr)
 {
-  __asm__ __volatile__(
-		       "or %g0, %g0, %o2\n\t"
-		       "or %g0, %g0, %o3\n\t"
-		       "or %g0, %o0, %o4\n\t"
-		       "srl %o4, 0x5, %o4\n\t"
-		       "add %o1, %o4, %o1\n\t"
-		       "or %g0, 0x1, %o5"
-		       "or %g0, 0x1f, %o6"
-		       "and %o6, %o5, %o6"
-		       "sll %o5, %o6, %o2"
-		       "ld [%o1], %o5\n\t"
-		       "and %o5, %o2, %o0\n\t"
-		       "xnor %g0, %o2, %o2\n\t"
-		       "and %o5, %o2, %o5\n\t"
-		       "st %o5, [%o1]\n\t");
-
-  return nr; /* confuse gcc ;-) */
+  register unsigned long retval, tmp, mask, psr;
+
+  __asm__ __volatile__("or %%g0, 0x1, %3\n\t"
+		       "sll %3, %4, %3\n\t"
+		       "rd %%psr, %5\n\t"
+		       "andn %5, 0x20, %5\n\t"    /* clear ET bit */
+		       "wr %5, 0x0, %%psr\n\t"    /* disable traps */
+                       "ld [%1], %2\n\t"
+		       "and %2, %3, %0\n\t"       /* get old bit */
+		       "andn %2, %3, %2\n\t"      /* set new val */
+		       "st  %2, [%1]\n\t"
+		       "wr %5, 0x20, %%psr\n\t" : /* enable traps */
+		       "=r" (retval) :
+		       "r" (addr), "r" (tmp=0), "r" (mask=0),
+		       "r" (nr), "r" (psr=0));
+
+  return retval; /* confuse gcc ;-) */
 
 }
 
-extern __inline__ unsigned int test_bit(int nr, int *addr)
-{
-  __asm__ __volatile__(
-		       "or %g0, %o0, %o3\n\t"
-		       "srl %o3, 0x5, %o3\n\t"
-		       "add %o1, %o3, %o1\n\t"
-		       "and %o0, 0x1f, %o0\n\t"
-		       "or %g0, 0x1, %o2\n\t"
-		       "sll %o2, %o0, %o0"
-		       "ld [%o1], %o2\n\t"
-		       "and %o0, %o2, %o0\n\t");
+extern __inline__ unsigned int change_bit(unsigned int nr, void *addr)
+{
+  register unsigned long retval, tmp, mask, psr;
+
+  __asm__ __volatile__("or %%g0, 0x1, %3\n\t"
+		       "sll %3, %4, %3\n\t"
+		       "rd %%psr, %5\n\t"
+		       "andn %5, 0x20, %5\n\t"    /* clear ET bit */
+		       "wr %5, 0x0, %%psr\n\t"    /* disable traps */
+                       "ld [%1], %2\n\t"
+		       "and %3, %2, %0\n\t"       /* get old bit val */
+		       "xor %3, %2, %2\n\t"       /* set new val */
+		       "st  %2, [%1]\n\t"
+		       "wr %5, 0x20, %%psr\n\t" : /* enable traps */
+		       "=r" (retval) :
+		       "r" (addr), "r" (tmp=0), "r" (mask=0),
+		       "r" (nr), "r" (psr=0));
 
-  return nr; /* confuse gcc :> */
+  return retval; /* confuse gcc ;-) */
 
 }
+
+/* The following routine need not be atomic. */
+
+extern __inline__ unsigned int test_bit(int nr, void *addr)
+{
+  register unsigned long retval, tmp;
+
+  __asm__ __volatile__("ld [%1], %2\n\t"
+		       "or %%g0, 0x1, %0\n\t"
+		       "sll %0, %3, %0\n\t"
+		       "and %0, %2, %0\n\t" :
+		       "=r" (retval) :
+		       "r" (addr), "r" (tmp=0),
+		       "r" (nr));
+
+  return retval; /* confuse gcc :> */
+
+}
+
+/* There has to be a faster way to do this, sigh... */
+
+extern __inline__ unsigned long ffz(unsigned long word)
+{
+  register unsigned long cnt, tmp, tmp2;
+
+  cnt = 0;
+
+  __asm__("or %%g0, %3, %2\n\t"
+	  "1: and %2, 0x1, %1\n\t"
+	  "srl %2, 0x1, %2\n\t"
+	  "cmp %1, 0\n\t"
+	  "bne,a 1b\n\t"
+	  "add %0, 0x1, %0\n\t" :
+	  "=r" (cnt) :
+	  "r" (tmp=0), "r" (tmp2=0), "r" (word));
+
+  return cnt;
+}
+
+/* find_next_zero_bit() finds the first zero bit in a bit string of length
+ * 'size' bits, starting the search at bit 'offset'. This is largely based
+ * on Linus's ALPHA routines, which are pretty portable BTW.
+ */
+
+extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+{
+  unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
+  unsigned long result = offset & ~31UL;
+  unsigned long tmp;
+
+  if (offset >= size)
+    return size;
+  size -= result;
+  offset &= 31UL;
+  if (offset) 
+    {
+      tmp = *(p++);
+      tmp |= ~0UL >> (32-offset);
+      if (size < 32)
+	goto found_first;
+      if (~tmp)
+	goto found_middle;
+      size -= 32;
+      result += 32;
+    }
+  while (size & ~32UL) 
+    {
+      if (~(tmp = *(p++)))
+	goto found_middle;
+      result += 32;
+      size -= 32;
+    }
+  if (!size)
+    return result;
+  tmp = *p;
+
+found_first:
+  tmp |= ~0UL << size;
+found_middle:
+  return result + ffz(tmp);
+}
+
+/* Linus sez that gcc can optimize the following correctly, we'll see if this
+ * holds on the Sparc as it does for the ALPHA.
+ */
+
+#define find_first_zero_bit(addr, size) \
+        find_next_zero_bit((addr), (size), 0)
+
 
 #endif /* defined(_SPARC_BITOPS_H) */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/bugs.h linux/include/asm-sparc/bugs.h
--- v1.1.75/linux/include/asm-sparc/bugs.h	Thu Dec 29 20:15:58 1994
+++ linux/include/asm-sparc/bugs.h	Mon Jan  2 15:26:45 1995
@@ -14,14 +14,16 @@
 
 #include <asm/openprom.h>
 
-extern struct promvec *romvec;
+extern struct linux_romvec *romvec;
 extern int tbase_needs_unmapping;   /* We do the bug workaround in pagetables.c */
 
-static void check_mmu()
+static void check_mmu(void)
 {
-  register struct promvec *romvec;
+  register struct linux_romvec *lvec;
   register int root_node;
-  register unsigned int present;
+  unsigned int present;
+
+  lvec = romvec;
 
   root_node = (*(romvec->pv_nodeops->no_nextnode))(0);
   tbase_needs_unmapping=0;
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/contregs.h linux/include/asm-sparc/contregs.h
--- v1.1.75/linux/include/asm-sparc/contregs.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/contregs.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,19 @@
+#ifndef _SPARC_CONTREGS_H
+#define _SPARC_CONTREGS_H
+
+/* contregs.h:  Addresses of registers in the ASI_CONTROL alternate address
+                space. These are for the mmu's context register, etc.
+
+   Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+*/
+
+#define AC_CONTEXT    0x30000000    /* current mmu-context, handy for invalidate()'s ;-)   */
+#define AC_SENABLE    0x40000000    /* system dvma/cache enable, plus special reset poking */
+#define AC_CACHETAGS  0x80000000    /* directo access to the VAC cache, unused...          */
+#define AC_SYNC_ERR   0x60000000    /* what type of synchronous memory error happened      */
+#define AC_SYNC_VA    0x60000004    /* what virtual address caused the error to occur      */
+#define AC_ASYNC_ERR  0x60000008    /* what type of asynchronous mem-error happened        */
+#define AC_ASYNC_VA   0x6000000c    /* what virtual address caused the async-err to happen */
+#define AC_CACHEDDATA 0x90000000    /* where the actual VAC cached data sits               */
+
+#endif /* _SPARC_CONTREGS_H */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/delay.h linux/include/asm-sparc/delay.h
--- v1.1.75/linux/include/asm-sparc/delay.h	Thu Dec 15 11:01:55 1994
+++ linux/include/asm-sparc/delay.h	Mon Jan  2 15:26:45 1995
@@ -29,4 +29,12 @@
 	  "umul %o1, %o0, %o0\n\t");
 }
 
+/* calibrate_delay() wants this... */
+
+extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
+{
+	return ((a/c)*c);
+}
+
 #endif /* defined(__SPARC_DELAY_H) */
+
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/dma.h linux/include/asm-sparc/dma.h
--- v1.1.75/linux/include/asm-sparc/dma.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/dma.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,15 @@
+/*
+ * include/asm-sparc/dma.h
+ *
+ * Don't even ask, I am figuring out how this crap works
+ * on the Sparc. It may end up being real hairy to plug
+ * into this code, maybe not, we'll see.
+ *
+ * Copyright (C) David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _ASM_SPARC_DMA_H
+#define _ASM_SPARC_DMA_H
+
+
+#endif /* !(_ASM_SPARC_DMA_H) */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/head.h linux/include/asm-sparc/head.h
--- v1.1.75/linux/include/asm-sparc/head.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/head.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,51 @@
+#define KERNSIZE	134217728
+#define KERNBASE	0           /* new strategy */
+#define LOAD_ADDR       0x4000
+#define C_STACK         96
+#define SUN4C_SEGSZ     (1 << 18)
+#define NBPG		4096	
+#define UPAGES		2
+#define PROM_BASE	-1568768
+#define PAGESHIFT_SUN4C 12          /* This is good for sun4m's also */
+#define ASI_CONTROL     0x02        /* for cache enable, context registers, etc. */
+#define ASI_SEGMAP      0x03
+#define ASI_PTE         0x04
+#define AC_CONTEXT      0x30000000
+#define USRSTACK        KERNBASE
+#define IE_REG_PTE_PG   -201326592
+#define INT_ENABLE_REG_PHYSADR      0xf5000000
+#define IE_ALLIE        0x01
+
+/* This crap should go elsewhere */
+
+#define PSR_IMPL        0xf0000000      /* implementation */
+#define PSR_VER         0x0f000000      /* version */
+#define PSR_ICC         0x00f00000      /* integer condition codes */
+#define PSR_N           0x00800000      /* negative */
+#define PSR_Z           0x00400000      /* zero */
+#define PSR_O           0x00200000      /* overflow */
+#define PSR_C           0x00100000      /* carry */
+#define PSR_EC          0x00002000      /* coprocessor enable */
+#define PSR_EF          0x00001000      /* FP enable */
+#define PSR_PIL         0x00000f00      /* interrupt level */
+#define PSR_S           0x00000080      /* supervisor (kernel) mode */
+#define PSR_PS          0x00000040      /* previous supervisor mode (traps) */
+#define PSR_ET          0x00000020      /* trap enable */
+#define PSR_CWP         0x0000001f      /* current window pointer */
+
+#define PCB_WIM         20
+
+#define HZ              100
+
+/* Offsets into the proc structure for window info, etc. Just dummies
+   for now.
+*/
+
+#define TASK_WIM      0x8
+#define TASK_UW       0x16
+#define TASK_SIZE     8192
+#define TASK_RW       0x32
+#define TASK_NSAVED   0x40
+#define PG_VSHIFT     0x16
+#define PG_PROTSHIFT  0x6
+#define PG_PROTUWRITE 0x4
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/io.h linux/include/asm-sparc/io.h
--- v1.1.75/linux/include/asm-sparc/io.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/io.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,87 @@
+#ifndef __SPARC_IO_H
+#define __SPARC_IO_H
+
+/*
+ * Defines for io operations on the Sparc. Whether a memory access is going
+ * to i/o sparc is encoded in the pte. The type bits determine whether this
+ * is i/o sparc, on board memory, or VME space for VME cards. I think VME
+ * space only works on sun4's
+ */
+
+extern inline unsigned long inb_local(unsigned long addr)
+{
+  return 0;
+}
+
+extern inline void outb_local(unsigned char b, unsigned long addr)
+{
+  return;
+}
+
+extern inline unsigned long inb(unsigned long addr)
+{
+  return 0;
+}
+
+extern inline unsigned long inw(unsigned long addr)
+{
+  return 0;
+}
+
+extern inline unsigned long inl(unsigned long addr)
+{
+  return 0;
+}
+
+extern inline void outb(unsigned char b, unsigned long addr)
+{
+  return;
+}
+
+extern inline void outw(unsigned short b, unsigned long addr)
+{
+  return;
+}
+
+extern inline void outl(unsigned int b, unsigned long addr)
+{
+  return;
+}
+
+/*
+ * Memory functions
+ */
+extern inline unsigned long readb(unsigned long addr)
+{
+  return 0;
+}
+
+extern inline unsigned long readw(unsigned long addr)
+{
+  return 0;
+}
+
+extern inline unsigned long readl(unsigned long addr)
+{
+  return 0;
+}
+
+extern inline void writeb(unsigned short b, unsigned long addr)
+{
+  return;
+}
+
+extern inline void writew(unsigned short b, unsigned long addr)
+{
+  return;
+}
+
+extern inline void writel(unsigned int b, unsigned long addr)
+{
+  return;
+}
+
+#define inb_p inb
+#define outb_p outb
+
+#endif /* !(__SPARC_IO_H) */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/irq.h linux/include/asm-sparc/irq.h
--- v1.1.75/linux/include/asm-sparc/irq.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/irq.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,43 @@
+#ifndef _ALPHA_IRQ_H
+#define _ALPHA_IRQ_H
+
+/*
+ *	linux/include/asm-sparc/irq.h
+ *
+ *	Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <linux/linkage.h>
+
+extern void disable_irq(unsigned int);
+extern void enable_irq(unsigned int);
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+ 
+#define SAVE_ALL "xx"
+
+#define SAVE_MOST "yy"
+
+#define RESTORE_MOST "zz"
+
+#define ACK_FIRST(mask) "aa"
+
+#define ACK_SECOND(mask) "dummy"
+
+#define UNBLK_FIRST(mask) "dummy"
+
+#define UNBLK_SECOND(mask) "dummy"
+
+#define IRQ_NAME2(nr) nr##_interrupt(void)
+#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
+#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
+#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
+	
+#define BUILD_IRQ(chip,nr,mask) \
+asmlinkage void IRQ_NAME(nr); \
+asmlinkage void FAST_IRQ_NAME(nr); \
+asmlinkage void BAD_IRQ_NAME(nr); \
+asm code comes here
+
+#endif
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/memerr.h linux/include/asm-sparc/memerr.h
--- v1.1.75/linux/include/asm-sparc/memerr.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/memerr.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,32 @@
+#ifndef _SPARC_MEMERR_H
+#define _SPARC_MEMERR_H
+
+/* memerr.h:  Bit fields in the asynchronous and synchronous memory error
+              registers used to determine what 'type' of error has just
+	      induced a trap.
+
+   Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+*/
+
+/* synchronous error register fields come first... */
+
+#define SYNCER_WRITE    0x8000        /* write error...                               */
+#define SYNCER_INVAL    0x0080        /* invalid page access was attempted            */
+#define SYNCER_PROT     0x0040        /* protection violation                         */
+#define SYNCER_TIMEOUT  0x0020        /* mem-bus access timeout (mem does not exist). */
+#define SYNCER_SBUSERR  0x0010        /* same as above, but for an SBUS access        */
+#define SYNCER_MEMERR   0x0008        /* Bus parity error, lose lose... panic time    */
+#define SYNCER_SZERR    0x0002        /* an attempted access was of BAD size, whoops  */
+#define SYNCER_WATCHDOG 0x0001        /* although we never see these, the prom will.. */
+
+/* asynchronous error bits go here */
+
+#define ASYNCER_WBINVAL   0x80        /* situation arose where the cache tried to write
+                                       * back a page for which the valid bit was not set
+				       * within the mmu. This is due to bad mm kernel bugs.
+				       */
+
+#define ASYNCER_TIMEOUT   0x20        /* mem-access bus timeout... */
+#define ASYNCER_DVMAERR   0x10        /* dvma transfer to/from memory bombed... */
+
+#endif /* _SPARC_MEMERR_H */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/openprom.h linux/include/asm-sparc/openprom.h
--- v1.1.75/linux/include/asm-sparc/openprom.h	Thu Dec 29 20:15:58 1994
+++ linux/include/asm-sparc/openprom.h	Mon Jan  2 15:26:45 1995
@@ -1,5 +1,5 @@
-#ifndef _SPARC_OPENPROM_H
-#define _SPARC_OPENPROM_H
+#ifndef __SPARC_OPENPROM_H
+#define __SPARC_OPENPROM_H
 
 /* openprom.h:  Prom structures and defines for access to the OPENBOOT
                 prom routines and data areas.
@@ -19,7 +19,7 @@
 #define	LINUX_OPPROM_MAGIC      0x10010407
 
 /* The device functions structure for the v0 prom. Nice and neat, open,
-   close, read & write divvied up between net + block + char devices. We
+   close, read & write divied up between net + block + char devices. We
    also have a seek routine only usable for block devices. The divide
    and conquer strategy of this struct becomes unnecessary for v2.
 
@@ -33,12 +33,12 @@
 struct linux_dev_v0_funcs {
 	int	(*v0_devopen)(char *device_str);
 	int	(*v0_devclose)(int dev_desc);
-	int	(*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, caddr_t buf);
-	int	(*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, caddr_t buf);
-	int	(*v0_wrnetdev)(int dev_desc, int num_bytes, caddr_t buf);
-	int	(*v0_rdnetdev)(int dev_desc, int num_bytes, caddr_t buf);
-	int	(*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, caddr_t buf);
-	int	(*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, caddr_t buf);
+	int	(*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char*  buf);
+	int	(*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char*  buf);
+	int	(*v0_wrnetdev)(int dev_desc, int num_bytes, char*  buf);
+	int	(*v0_rdnetdev)(int dev_desc, int num_bytes, char*  buf);
+	int	(*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char*  buf);
+	int	(*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char*  buf);
 	int	(*v0_seekdev)(int dev_desc, long logical_offst, int from);
 };
 
@@ -54,7 +54,7 @@
    the time can be a pain in the rear after a while. Why v2 has memory
    allocations in here are beyond me. Perhaps they figure that if you
    are going to use only the prom's device drivers then your memory
-   management is either non-existent or pretty sad. :-)
+   management is either non-existant or pretty sad. :-)
 */
 
 struct linux_dev_v2_funcs {
@@ -64,23 +64,23 @@
 	    only safe to use for mapping device address spaces...
         */
 
-	caddr_t	(*v2_dumb_mem_alloc)(caddr_t va, unsigned sz);
-	void	(*v2_dumb_mem_free)(caddr_t va, unsigned sz);
+	char* 	(*v2_dumb_mem_alloc)(char*  va, unsigned sz);
+	void	(*v2_dumb_mem_free)(char*  va, unsigned sz);
 
-	/* "dumb" mmap() munmap(), copy on write? what's that? */
-	caddr_t	(*v2_dumb_mmap)(caddr_t virta, int asi, unsigned prot, unsigned sz);
-	void	(*v2_dumb_munmap)(caddr_t virta, unsigned size);
+	/* "dumb" mmap() munmap(), copy on write? whats that? */
+	char* 	(*v2_dumb_mmap)(char*  virta, int asi, unsigned prot, unsigned sz);
+	void	(*v2_dumb_munmap)(char*  virta, unsigned size);
 
 	/* Basic Operations, self-explanatory */
 	int	(*v2_dev_open)(char *devpath);
 	void	(*v2_dev_close)(int d);
-	int	(*v2_dev_read)(int d, caddr_t buf, int nbytes);
-	int	(*v2_dev_write)(int d, caddr_t buf, int nbytes);
+	int	(*v2_dev_read)(int d, char*  buf, int nbytes);
+	int	(*v2_dev_write)(int d, char*  buf, int nbytes);
 	void	(*v2_dev_seek)(int d, int hi, int lo);
 
         /* huh? */
-	void	(*v2_wheee2)();
-	void	(*v2_wheee3)();
+	void	(*v2_wheee2)(void);
+	void	(*v2_wheee3)(void);
 };
 
 /* Just like the device ops, they slightly screwed up the mem-list
@@ -91,7 +91,7 @@
 
 struct linux_mlist_v0 {
 	struct	linux_mlist_v0 *theres_more;
-	caddr_t	start_adr;
+	char* 	start_adr;
 	unsigned num_bytes;
 };
 
@@ -106,7 +106,7 @@
 	struct  linux_mlist_v0 **v0_available;	/* what phys. is left over */
 };
 
-/* Arguments sent to the kernel from the boot prompt. */
+/* Arguements sent to the kernel from the boot prompt. */
 
 struct linux_arguments_v0 {
 	char	*argv[8];		/* argv format for boot string */
@@ -136,22 +136,22 @@
    it jumps to the kernel start address. I will update this soon to cover
    the v3 semantics (cpu_start, cpu_stop and other SMP fun things). :-)
 */
-struct promvec {
+struct linux_romvec {
 	/* Version numbers. */
-	u_int	pv_magic;		/* Magic number */
-	u_int	pv_romvec_vers;		/* interface version (0, 2) */
-	u_int	pv_plugin_vers;		/* ??? */
-	u_int	pv_printrev;		/* PROM rev # (* 10, e.g 1.9 = 19) */
+	unsigned int	pv_magic_cookie;      /* Magic Mushroom... */
+	unsigned int	pv_romvers;	      /* iface vers (0, 2, or 3) */
+	unsigned int	pv_plugin_revision;   /* revision relative to above vers */
+	unsigned int	pv_printrev;	      /* printrevision */
 
 	/* Version 0 memory descriptors (see below). */
-	struct	v0mem pv_v0mem;		/* V0: Memory description lists. */
+	struct linux_mem_v0 pv_v0mem;	      /* V0: Memory description lists. */
 
 	/* Node operations (see below). */
-	struct	nodeops *pv_nodeops;	/* node functions */
+	struct	linux_nodeops *pv_nodeops;   /* node functions, gets device data */
 
-	char	**pv_bootstr;		/* Boot command, eg sd(0,0,0)vmunix */
+	char	**pv_bootstr;		    /* Boot command, eg sd(0,0,0)vmunix */
 
-	struct	v0devops pv_v0devops;	/* V0: device ops */
+	struct	linux_dev_v0_funcs pv_v0devops; 	/* V0: device ops */
 
 	/*
 	 * PROMDEV_* cookies.  I fear these may vanish in lieu of fd0/fd1
@@ -178,10 +178,10 @@
 	/* Miscellany. */
 	void	(*pv_reboot)(char *bootstr);
 	void	(*pv_printf)(const char *fmt, ...);
-	void	(*pv_abort)(void);	/* L1-A abort */
-	int	*pv_ticks;		/* Ticks since last reset */
-	__dead void (*pv_halt)(void);	/* Halt! */
-	void	(**pv_synchook)(void);	/* "sync" command hook */
+	void	(*pv_abort)(void);	/* BREAK key abort */
+	int	*pv_ticks;		/* milliseconds since last reset */
+	void    (*pv_halt)(void);	/* End the show */
+	void	(**pv_synchook)(void);	/* "sync" ptr to function */
 
 	/*
 	 * This eval's a FORTH string.  Unfortunately, its interface
@@ -192,15 +192,15 @@
 		void	(*v2_eval)(char *str);
 	} pv_fortheval;
 
-	struct	v0bootargs **pv_v0bootargs;	/* V0: Boot args */
+	struct	linux_arguments_v0 **pv_v0bootargs; /* V0: Boot args */
 
 	/* Extract Ethernet address from network device. */
-	u_int	(*pv_enaddr)(int d, char *enaddr);
+	unsigned int	(*pv_enaddr)(int d, char *enaddr);
 
-	struct	v2bootargs pv_v2bootargs;	/* V2: Boot args + std in/out */
-	struct	v2devops pv_v2devops;	/* V2: device operations */
+	struct	linux_bootargs_v2 pv_v2bootargs;    /* V2: Boot args+std-in/out */
+	struct	linux_dev_v2_funcs pv_v2devops;	    /* V2: device operations */
 
-	int	pv_spare[15];
+	int	whatzthis[15];       /* huh? */
 
 	/*
 	 * The following is machine-dependent.
@@ -213,7 +213,41 @@
 	 * all memory references go to the PROM, so the PROM can do it
 	 * easily.
 	 */
-	void	(*pv_setctxt)(int ctxt, caddr_t va, int pmeg);
+	void	(*pv_setctxt)(int ctxt, char*  va, int pmeg);
+
+	/* Prov version 3 Multiprocessor routines. This stuff is crazy.
+	 * No joke. Calling these when there is only one cpu probably
+	 * crashes the machine, have to test this. :-)
+         */
+
+	/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
+	 * 'thiscontext' executing at address 'prog_counter'
+	 *
+	 * XXX Have to figure out what 'cancontext' means.
+         */
+
+	int (*v3_cpustart)(unsigned int whichcpu, int cancontext,
+			   int thiscontext, char* prog_counter);
+
+	/* v3_cpustop() will cause cpu 'whichcpu' to stop executint
+	 * until a resume cpu call is made.
+	 */
+
+	int (*v3_cpustop)(unsigned int whichcpu);
+
+	/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
+	 * resume cpu call is made.
+	 */
+
+	int (*v3_cpuidle)(unsigned int whichcpu);
+
+	/* v3_cpuresume() will resume processor 'whichcpu' executing
+	 * starting with whatever 'pc' and 'npc' were left at the
+	 * last 'idle' or 'stop' call.
+	 */
+
+	int (*v3_cpuresume)(unsigned int whichcpu);
+
 };
 
 /*
@@ -234,19 +268,22 @@
  * format is an `address', which is made up of one or more sets of three
  * integers as defined below.
  *
+ * One uses these functions to traverse the device tree to see what devices
+ * this machine has attached to it.
+ *
  * N.B.: for the `next' functions, next(0) = first, and next(last) = 0.
  * Whoever designed this part had good taste.  On the other hand, these
  * operation vectors are global, rather than per-node, yet the pointers
  * are not in the openprom vectors but rather found by indirection from
  * there.  So the taste balances out.
  */
-struct openprom_addr {
+struct linux_prom_addr {
 	int	oa_space;		/* address space (may be relative) */
-	u_int	oa_base;		/* address within space */
-	u_int	oa_size;		/* extent (number of bytes) */
+	unsigned int	oa_base;		/* address within space */
+	unsigned int	oa_size;		/* extent (number of bytes) */
 };
 
-struct nodeops {
+struct linux_nodeops {
 	/*
 	 * Tree traversal.
 	 */
@@ -258,10 +295,10 @@
 	 * proplen first to make sure it fits.  Kind of a pain, but no
 	 * doubt more convenient for the PROM coder.
 	 */
-	int	(*no_proplen)(int node, caddr_t name);
-	int	(*no_getprop)(int node, caddr_t name, caddr_t val);
-	int	(*no_setprop)(int node, caddr_t name, caddr_t val, int len);
-	caddr_t	(*no_nextprop)(int node, caddr_t name);
+	int	(*no_proplen)(int node, char*  name);
+	int	(*no_getprop)(int node, char*  name, char*  val);
+	int	(*no_setprop)(int node, char*  name, char*  val, int len);
+	char* 	(*no_nextprop)(int node, char*  name);
 };
 
-#endif /* !(_SPARC_OPENPROM_H) */
+#endif /* !(__SPARC_OPENPROM_H) */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h
--- v1.1.75/linux/include/asm-sparc/page.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/page.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,128 @@
+/* page.h:  Various defines and such for MMU operations on the Sparc for
+            the Linux kernel.
+
+   Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+*/
+
+#ifndef _SPARC_PAGE_H
+#define _SPARC_PAGE_H
+
+#include <asm/asi.h>        /* for get/set segmap/pte routines */
+#include <asm/contregs.h>   /* for switch_to_context */
+
+/* The current va context is global and known, so all that is needed to
+ * do an invalidate is flush the VAC.
+ */
+
+#define invalidate() flush_vac_context()  /* how conveeeiiiiinnnent :> */
+
+
+#define PAGE_SHIFT   12             /* This is the virtual page... */
+#define PGDIR_SHIFT  18             /* This is the virtual segment */
+#define PAGE_SIZE    (1UL << PAGE_SHIFT)
+#define PGDIR_SIZE   (1UL << PGDIR_SHIFT)
+
+#ifdef __KERNEL__
+
+#define BITS_PER_PTR      (8*sizeof(unsigned long))   /* better check this stuff */
+#define PAGE_MASK         (~(PAGE_SIZE-1))
+#define PGDIR_MASK        (~(PGDIR_SIZE-1))
+#define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+#define PGDIR_ALIGN(addr) (((addr)+PGDIR_SIZE-1)&PGDIR_MASK)
+#define PTR_MASK          (~(sizeof(void*)-1))
+
+
+#define SIZEOF_PTR_LOG2   2
+
+/* The rest is kind of funky because on the sparc, the offsets into the mmu 
+ * entries are encoded in magic alternate address space tables. I will 
+ * probably find some nifty inline assembly routines to do the equivalent. 
+ * Much thought must go into this code.   (davem@caip.rutgers.edu)
+ */
+
+#define PAGE_DIR_OFFSET(base, address)   ((void *) 0)
+#define PAGE_PTR(address)                ((void *) 0)
+#define PTRS_PER_PAGE                    (64)  /* 64 pte's per phys_seg */
+
+/* Bitfields within a Sparc sun4c PTE (page table entry). */
+
+#define PTE_V     0x80000000   /* valid bit */
+#define PTE_ACC   0x60000000   /* access bits */
+#define PTE_W     0x40000000   /* writable bit */
+#define PTE_P     0x20000000   /* privileged page */
+#define PTE_NC    0x10000000   /* page is non-cacheable */
+#define PTE_TYP   0x0c000000   /* page type field */
+#define PTE_RMEM  0x00000000   /* type == on board real memory */
+#define PTE_IO    0x04000000   /* type == i/o area */
+#define PTE_VME16 0x08000000   /* type == 16-bit VME area */
+#define PTE_VME32 0x0c000000   /* type == 32-bit VME area */
+#define PTE_R     0x02000000   /* page has been referenced */
+#define PTE_M     0x01000000   /* page has been modified */
+#define PTE_RESV  0x00f80000   /* reserved bits */
+#define PTE_PHYPG 0x0007ffff   /* phys pg number, sun4c only uses 16bits */
+
+/* termed a 'page table' in the linux kernel, a segmap entry is obtained
+ * with the following macro
+ */
+
+extern __inline__ unsigned long get_segmap(unsigned long addr)
+{
+  register unsigned long entry;
+
+  __asm__ __volatile__("lduha [%1] 0x3, %0" : 
+		       "=r" (entry) :
+		       "r" (addr)); 
+
+  return entry;
+}
+
+extern __inline__ void put_segmap(unsigned long* addr, unsigned long entry)
+{
+
+  __asm__ __volatile__("stha %1, [%0] 0x3" : : "r" (addr), "r" (entry));
+
+  return;
+}
+
+extern __inline__ unsigned long get_pte(unsigned long addr)
+{
+  register unsigned long entry;
+
+  __asm__ __volatile__("lda [%1] 0x4, %0" : 
+		       "=r" (entry) :
+		       "r" (addr));
+  return entry;
+}
+
+extern __inline__ void put_pte(unsigned long addr, unsigned long entry)
+{
+  __asm__ __volatile__("sta %1, [%0] 0x4" : :
+		       "r" (addr), 
+		       "r" (entry));
+
+  return;
+}
+
+extern __inline__ void switch_to_context(int context)
+{
+  __asm__ __volatile__("stba %0, [%1] 0x2" : :
+		       "r" (context),
+		       "r" (0x30000000));		       
+
+  return;
+}
+
+extern __inline__ int get_context(void)
+{
+  register int ctx;
+
+  __asm__ __volatile__("lduba [%1] 0x2, %0" :
+		       "=r" (ctx) :
+		       "r" (0x30000000));
+
+  return ctx;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _SPARC_PAGE_H */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v1.1.75/linux/include/asm-sparc/processor.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/processor.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,46 @@
+/* include/asm-sparc/processor.h
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __ASM_SPARC_PROCESSOR_H
+#define __ASM_SPARC_PROCESSOR_H
+
+/*
+ * Bus types
+ */
+extern int EISA_bus;
+#define MCA_bus 0
+
+/*
+ * User space process size: 3GB. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.
+ *
+ * "this is gonna have to change to 1gig for the sparc" - David S. Miller
+ */
+#define TASK_SIZE	0xc0000000
+
+/*
+ * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
+ */
+#define IO_BITMAP_SIZE	32
+
+struct thread_struct {
+	unsigned long ksp;          /* kernel stack pointer */
+	unsigned long usp;          /* user's sp, throw reg windows here */
+	unsigned long ptbr;
+	unsigned int pcc;
+	unsigned int asn;
+	unsigned long unique;
+	unsigned long flags;
+	unsigned long res1, res2;
+};
+
+#define INIT_TSS  { \
+	0, 0, 0, \
+	0, 0, 0, \
+	0, 0, 0, \
+}
+
+#endif /* __ASM_SPARC_PROCESSOR_H */
+
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/psr.h linux/include/asm-sparc/psr.h
--- v1.1.75/linux/include/asm-sparc/psr.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/psr.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,98 @@
+/* psr.h: This file holds the macros for masking off various parts of
+          the processor status register on the Sparc. This is valid
+	  for Version 8. On the V9 this is renamed to the PSTATE
+	  register and it's members are accessed as fields like
+	  PSTATE.PRIV for the current CPU privilege level.
+
+   Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+*/
+
+#ifndef __LINUX_SPARC_PSR_H
+#define __LINUX_SPARC_PSR_H
+
+
+#ifdef __LINUX_SPARC_V8
+
+/* The Sparc PSR fields are laid out as the following:
+
+    ------------------------------------------------------------------------
+    | impl  | vers  | icc   | resv  | EC | EF | PIL  | S | PS | ET |  CWP  |
+bits| 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6  | 5  |  4-0  |
+    ------------------------------------------------------------------------
+
+   The PSR can only be directly be written/read by the privileged instructions
+   'rd' and 'wr'. Certain fields are changed as a side effect due to the 'Ticc',
+   'save', 'restore', and 'rett' instructions. Also the integer condition codes
+   'icc' are modified by various arithmetic instructions.
+
+   For example:  wr  %o2, or'd_bit_pattern, %psr
+                 rd  %psr, %o3
+
+*/
+
+#define PSR_CWP     0x0000001f         /* current window pointer     */
+#define PSR_ET      0x00000020         /* enable traps field         */
+#define PSR_PS      0x00000040         /* previous privilege level   */
+#define PSR_S       0x00000080         /* current privilege level    */
+#define PSR_PIL     0x00000f00         /* processor interrupt level  */
+#define PSR_EF      0x00001000         /* enable floating point      */
+#define PSR_EC      0x00002000         /* enable co-processor        */
+#define PSR_ICC     0x00f00000         /* integer condition codes    */
+#define PSR_C       0x00100000         /* carry bit                  */
+#define PSR_V       0x00200000         /* overflow bit               */
+#define PSR_Z       0x00400000         /* zero bit                   */
+#define PSR_N       0x00800000         /* negative bit               */
+#define PSR_VERS    0x0f000000         /* cpu-version field          */
+#define PSR_IMPL    0xf0000000         /* cpu-implementation field   */
+
+#endif /* !(__LINUX_SPARC_V8) */
+
+#ifdef __LINUX_SPARC_V9
+
+/* The information available in the %psr on the V8 is spread amongst
+   a whole bunch of registers on the V9. The main one being PSTATE.
+
+     --------------------------------------------------------
+     |  CLE  | TLE |  MM  | RED | PEF | AM | PRIV | IE | AG |
+bits |   9   |  8  |  7-6 |  5  |  4  |  3 |   2  |  1 |  0 |
+     --------------------------------------------------------
+
+   Writes and reads to PSTATE are done via 'wrpr' and 'rdpr' instructions.
+
+   For example:  wrpr %o2, or'd_bit_pattern, %pstate
+                 rdpr %pstate, %o3
+*/
+
+#define PSTATE_AG    0x001   /* Alternate Globals             */
+#define PSTATE_IE    0x002   /* Interrupt Enable              */
+#define PSTATE_PRIV  0x004   /* Current privilege level       */
+#define PSTATE_AM    0x008   /* Address mask (data reads can  */
+			     /* be chosen to be either big or */
+			     /* little endian on V9).         */
+#define PSTATE_PEF   0x010   /* enable floating point         */
+#define PSTATE_RED   0x020   /* RED trap state (set if trap   */
+                             /* trap_level == max_tl).        */
+#define PSTATE_MM    0x0c0   /* Memory model (Total Store     */
+                             /* Order=0, Partial Store Order  */
+                             /* =1 or Relaxed Memory Order=2) */
+#define PSTATE_TLE   0x100   /* Trap Little Endian            */
+#define PSTATE_CLE   0x200   /* Current Little Endian         */
+
+
+/* The Version Register holds vendor information for the chip:
+
+    ---------------------------------------------------------------------------
+    | manufacturer | implementation | mask | reserved | maxtl | resv | maxwin |
+bits|  63-48       |   47-32        | 31-24|   23-16  | 15-8  | 7-5  |  4-0   |
+    ---------------------------------------------------------------------------
+
+*/
+
+#define VERS_MAXWIN  0x000000000000001f     /* 'nwindows' on this chip       */
+#define VERS_MAXTL   0x00000000000ff000     /* Maximum Trap-level supported  */
+#define VERS_MASK    0x0000000ff0000000     /* impl. dep. chip mask revision */
+#define VERS_MANUF   0xffff000000000000     /* Manufacturer ID code          */
+
+#endif /* !(__LINUX_SPARC_V9) */
+
+#endif /* !(__LINUX_SPARC_PSR_H) */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/segment.h linux/include/asm-sparc/segment.h
--- v1.1.75/linux/include/asm-sparc/segment.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/segment.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,86 @@
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
+
+#define KERNEL_CS   0x0
+#define KERNEL_DS   0x0
+
+#define USER_CS     0x1
+#define USER_DS     0x1
+
+#include <linux/string.h>
+
+static inline unsigned char get_user_byte(const char * addr)
+{
+	return *addr;
+}
+
+#define get_fs_byte(addr) get_user_byte((char *)(addr))
+
+static inline unsigned short get_user_word(const short *addr)
+{
+	return *addr;
+}
+
+#define get_fs_word(addr) get_user_word((short *)(addr))
+
+static inline unsigned long get_user_long(const int *addr)
+{
+	return *addr;
+}
+
+#define get_fs_long(addr) get_user_long((int *)(addr))
+
+static inline unsigned long get_user_quad(const long *addr)
+{
+	return *addr;
+}
+
+#define get_fs_quad(addr) get_user_quad((long *)(addr))
+
+static inline void put_user_byte(char val,char *addr)
+{
+	*addr = val;
+}
+
+#define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr))
+
+static inline void put_user_word(short val,short * addr)
+{
+	*addr = val;
+}
+
+#define put_fs_word(x,addr) put_user_word((x),(short *)(addr))
+
+static inline void put_user_long(unsigned long val,int * addr)
+{
+	*addr = val;
+}
+
+#define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
+
+static inline void put_user_quad(unsigned long val,long * addr)
+{
+	*addr = val;
+}
+
+#define put_fs_quad(x,addr) put_user_quad((x),(long *)(addr))
+
+#define memcpy_fromfs(to, from, n) memcpy((to),(from),(n))
+
+#define memcpy_tofs(to, from, n) memcpy((to),(from),(n))
+
+static inline unsigned long get_fs(void)
+{
+	return 0;
+}
+
+static inline unsigned long get_ds(void)
+{
+	return 0;
+}
+
+static inline void set_fs(unsigned long val)
+{
+}
+
+#endif /* _ASM_SEGMENT_H */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/string.h linux/include/asm-sparc/string.h
--- v1.1.75/linux/include/asm-sparc/string.h	Thu Dec 15 11:01:55 1994
+++ linux/include/asm-sparc/string.h	Mon Jan  2 15:26:45 1995
@@ -4,8 +4,224 @@
    Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
 */
 
-extern int strlen(char* str);
-extern int strcmp(char* str1, char* str2);
-extern int strncmp(char* str1, char* str2, int strlen);
-extern int strcpy(char* dest, char* source);
-extern int strncpy(char* dest, char* source, int cpylen);
+extern __inline__ size_t strlen(const char* str)
+{
+  register int retval, tmp;
+
+  __asm__("ldub [%1], %2\n\t"
+	  "or %%g0, %%g0, %0\n\t"
+	  "orcc %2, %%g0, %%g0\n\t"
+	  "be 2f\n\t"
+	  "add %1, 0x1, %1\n\t"
+	  "1: ldub [%1], %2\n\t"
+	  "add %0, 0x1, %0\n\t"
+	  "orcc %2, %%g0, %%g0\n\t"
+	  "bne 1b\n\t"
+	  "add %1, 0x1, %1\n\t"
+	  "2:" :
+	  "=r" (retval) :
+	  "r" (str), "r" (tmp=0));
+
+  return retval;
+}
+
+extern __inline__ int strcmp(const char* str1, const char* str2)
+{
+  register unsigned int tmp1, tmp2;
+  register int retval;
+
+  __asm__("ldub [%1], %3\n\t"
+	  "ldub [%2], %4\n\t"
+	  "1: add %2, 0x1, %2\n\t"
+	  "cmp %3, %4\n\t"
+	  "bne,a 2f\n\t"
+	  "sub %2, 0x1, %2\n\t"
+	  "ldub [%1], %3\n\t"
+	  "add %1, 0x1, %1\n\t"
+	  "cmp %3, 0x0\n\t"
+	  "bne,a 1b\n\t"
+	  "ldub [%2], %4\n\t"
+	  "b 3f\n\t"
+	  "or %%g0, %%g0, %0\n\t"
+	  "2: ldub [%1], %3\n\t"
+	  "ldub [%2], %4\n\t"
+          "sub %3, %4, %0\n\t"
+	  "3: \n\t" :
+	  "=r" (retval) :
+	  "r" (str1), "r" (str2),
+	  "r" (tmp1=0), "r" (tmp2=0));
+
+  return retval;
+}
+
+extern __inline__ int strncmp(const char* str1, const char* str2, size_t strlen)
+{
+  register char tmp1, tmp2;
+  register int retval;
+
+  __asm__("cmp %3, 0x0\n\t"
+	  "be 2f\n\t"
+	  "ldub [%2], %5\n\t"
+	  "1: ldub [%1], %4\n\t"
+	  "sub %4, %5, %0\n\t"
+	  "cmp %0, 0x0\n\t"
+	  "bne 2f\n\t"
+	  "add %2, 0x1, %2\n\t"
+	  "cmp %4, 0x0\n\t"
+	  "be 2f\n\t"
+	  "add %1, 0x1, %1\n\t"
+	  "addcc %3, -1, %3\n\t"
+	  "bne,a 1b\n\t"
+	  "ldub [%2], %5\n\t"
+	  "2: " :
+	  "=r" (retval) :
+	  "r" (str1), "r" (str2),
+	  "r" (strlen), "r" (tmp1=0),
+	  "r" (tmp2=0));
+
+  return retval;
+}
+
+
+extern __inline__ char *strcpy(char* dest, const char* source)
+{
+  register char tmp;
+  register char *retval;
+
+  __asm__("or %%g0, %2, %0\n\t"
+	  "ldub [%1], %3\n\t"
+	  "1: stb %3, [%2]\n\t"
+	  "cmp %3, 0x0\n\t"
+	  "bne,a 1b\n\t"
+	  "ldub [%1], %3\n\t" :
+	  "=r" (retval) :
+	  "r" (source), "r" (dest), "r" (tmp));
+
+  return retval;
+}
+
+extern __inline__ char *strncpy(char *dest, const char *source, size_t cpylen)
+{
+  register char tmp;
+  register char *retval;
+
+  __asm__("or %%g0, %1, %0\n\t"
+	  "1: cmp %4, 0x0\n\t"
+	  "be 2f\n\t"
+	  "ldub [%1], %3\n\t"
+	  "add %1, 0x1, %1\n\t"
+	  "stb %3, [%2]\n\t"
+	  "sub %4, 0x1, %4\n\t"
+	  "ba 1\n\t"
+	  "add %2, 0x1, %2\n\t" :
+	  "=r" (retval) :
+	  "r" (dest), "r" (source), 
+	  "r" (tmp), "r" (cpylen));
+
+  return retval;
+}
+
+/* extern __inline__ char *strcat(char *dest, char *src); */
+
+/* extern __inline__ char *strncat(char *dest, char *src, int len); */
+
+/* extern __inline__ char *strchr(char *src, char c); */
+
+/* extern __inline__ char *strpbrk(char *cs, char *ct); */
+
+/* extern __inline__ char *strtok(char *s, char *ct); */
+
+/* extern __inline__ int strspn(char *s, char *accept); */
+
+extern __inline__ void *memset(void *src, char c, size_t count)
+{
+  register void *retval;
+
+  __asm__("or %%g0, %1, %0\n\t"
+	  "1: add %1, 0x1, %1\n\t"
+	  "2: add %3, -1, %3\n\t"
+	  "cmp %3, -1\n\t"
+	  "bne,a 1b\n\t"
+	  "stb %2, [%1]\n\t" :
+	  "=r" (retval) :
+	  "r" (src), "r" (c), "r" (count));
+
+  return retval;
+}
+
+extern __inline__ void *memcpy(void *dest, const void *src, size_t count)
+{
+  register void *retval;
+  register char tmp;
+
+  __asm__("or %%g0, %1, %0\n\t"
+	  "add %3, -1, %3\n\t"
+	  "cmp %3, -1\n\t"
+	  "be 2f\n\t"
+	  "1: ldub [%2], %4\n\t"
+	  "add %2, 0x1, %2\n\t"
+	  "add %3, -1, %3\n\t"
+	  "cmp %3, -1\n\t"
+	  "stb %4, [%1]\n\t"
+	  "bne 1b\n\t"
+	  "add %1, 0x1, %1\n\t"
+	  "2: " :
+	  "=r" (retval) :
+	  "r" (dest), "r" (src), "r" (count), "r" (tmp));
+
+  return retval;
+}
+
+extern __inline__ void *memmove(void *dest, const void *src, size_t count)
+{
+  register void *retval;
+  register char tmp;
+
+  __asm__("or %%g0, %1, %1\n\t"
+	  "add %3, -1, %3\n\t"
+	  "cmp %3, -1\n\t"
+	  "be 2f\n\t"
+	  "1: ldub [%2], %4\n\t"
+	  "add %2, 0x1, %2\n\t"
+	  "add %3, -1, %3\n\t"
+	  "cmp %3, -1\n\t"
+	  "stb %4, [%1]\n\t"
+	  "bne 1b\n\t"
+	  "add %1, 0x1, %1\n\t"
+	  "2: " :
+	  "=r" (retval) :
+	  "r" (dest), "r" (src), "r" (count), "r" (tmp));
+
+  return retval;
+}
+
+extern __inline__ int memcmp(const void *cs, const void *ct, size_t count)
+{
+  register int retval;
+  register unsigned long tmp1, tmp2;
+
+  __asm__("or %%g0, %1, %0\n\t"
+	  "cmp %3, 0x0\n\t"
+	  "ble,a 3f\n\t"
+	  "or %%g0, %%g0, %0\n\t"
+	  "1: ldub [%1], %4\n\t"
+	  "ldub [%2], %5\n\t"
+	  "cmp %4, %5\n\t"
+	  "be,a 2f\n\t"
+	  "add %1, 0x1, %1\n\t"
+	  "bgeu 3f\n\t"
+	  "or %%g0, 0x1, %0\n\t"
+	  "b 3f\n\t"
+	  "or %%g0, -1, %0\n\t"
+	  "2: add %3, -1, %3\n\t"
+	  "cmp %3, 0x0\n\t"
+	  "bg 1b\n\t"
+	  "add %2, 0x1, %2\n\t"
+	  "or %%g0, %%g0, %0\n\t"
+	  "3: " :
+	  "=r" (retval) :
+	  "r" (cs), "r" (ct), "r" (count), "r" (tmp1=0), "r" (tmp2=0));
+
+  return retval;
+}
+
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/sysen.h linux/include/asm-sparc/sysen.h
--- v1.1.75/linux/include/asm-sparc/sysen.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/sysen.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,14 @@
+#ifndef _SPARC_SYSEN_H
+#define _SPARC_SYSEN_H
+
+/* sysen.h:  Bit fields within the "System Enable" register accessed via
+             the ASI_CONTROL address space at address AC_SYSENABLE.
+
+   Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+*/
+
+#define SENABLE_DVMA   0x20   /* enable dvma transfers */
+#define SENABLE_CACHE  0x10   /* enable VAC cache */
+#define SENABLE_RESET  0x04   /* reset the whole mache, danger Will Robinson */
+
+#endif /* _SPARC_SYSEN_H */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v1.1.75/linux/include/asm-sparc/system.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/system.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,92 @@
+#ifndef __SPARC_SYSTEM_H
+#define __SPARC_SYSTEM_H
+
+/*
+ * System defines.. Note that this is included both from .c and .S
+ * files, so it does only defines, not any C code.
+ */
+
+/*
+ * I wish the boot time image was as beautiful as the Alpha's
+ * but no such luck. The icky PROM loads us at 0x0, and jumps
+ * to magic addess 0x4000 to start thing going. This means that
+ * I can stick the pcb and user/kernel stacks in the area from
+ * 0x0-0x4000 and be reasonably sure that this is sane.
+ *
+ * Sorry, I can't impress people with cool looking 64-bit values
+ * yet. ;-)
+ */
+
+#include <asm/openprom.h>
+
+#define INIT_PCB	0x00011fe0
+#define INIT_STACK	0x00013fe0
+#define START_ADDR	0x00004000
+#define START_SIZE	(32*1024)
+
+#ifndef __ASSEMBLY__
+
+extern void wrent(void *, unsigned long);
+extern void wrkgp(unsigned long);
+extern struct linux_romvec *romvec;
+
+#define halt() { romvec->pv_halt(); }
+#define move_to_user_mode() halt()
+#define switch_to(x) halt()
+
+#ifndef stbar  /* store barrier Sparc insn to snchronize stores in PSO */
+#define stbar() __asm__ __volatile__("stbar": : :"memory")
+#endif
+
+/* Changing the PIL on the sparc is a bit hairy. I figure out some
+ * more optimized way of doing this soon.
+ */
+
+#define swpipl(__new_ipl) \
+({ unsigned long __old_ipl, psr; \
+__asm__ __volatile__( \
+	"and %1, 15, %1\n\t" \
+	"sll %1, 8, %1\n\t" \
+	"rd %%psr, %2\n\t" \
+	"or %%g0, %2, %0\n\t" \
+	"or %2, %1, %2\n\t" \
+	"wr %2, 0x0, %%psr\n\t" \
+	"srl %0, 8, %0\n\t" \
+        "and %0, 15, %0\n\t" \
+	: "=r" (__old_ipl) \
+	: "r" (__new_ipl), "r" (psr=0)); \
+__old_ipl; })
+
+#define cli()			swpipl(15)  /* 15 = no int's except nmi's */
+#define sti()			swpipl(0)   /* same as alpha */
+#define save_flags(flags)	do { flags = swpipl(15); } while (0)
+#define restore_flags(flags)	swpipl(flags)
+
+/* Must this be atomic? */
+
+extern inline void *xchg_u32(int * m, unsigned long val)
+{
+	unsigned long dummy;
+
+	__asm__ __volatile__(
+		"ld %1,%2\n\t"
+		"st %0, %1\n\t"
+		"or %%g0, %2, %0"
+		: "=r" (val), "=m" (*m), "=r" (dummy)
+		: "1" (*m), "2" (val));
+	return (void *)val;
+}
+
+
+/* pointers are 32 bits on the sparc (at least the v8, and they'll work
+ * on the V9 none the less). I don't need the xchg_u64 routine for now.
+ */
+
+extern inline void *xchg_ptr(void *m, void *val)
+{
+	return (void *) xchg_u32((int *) m, (unsigned long) val);
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- v1.1.75/linux/include/asm-sparc/unistd.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/unistd.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,44 @@
+#ifndef _SPARC_UNISTD_H
+#define _SPARC_UNISTD_H
+
+/*
+ * System calls under the Sparc.
+ *
+ * This is work in progress.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) \
+{ \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) \
+{ \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+} 
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+	  type5,arg5) \
+type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+{ \
+}
+
+#endif /* _ALPHA_UNISTD_H */
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/vac-ops.h linux/include/asm-sparc/vac-ops.h
--- v1.1.75/linux/include/asm-sparc/vac-ops.h	Tue Dec 27 09:56:47 1994
+++ linux/include/asm-sparc/vac-ops.h	Mon Jan  2 15:26:45 1995
@@ -12,10 +12,15 @@
 {
   int success;
 
-  __asm__ __volatile__("lduba [0x40000000] 0x2, %0\n\t"
+  &success;
+  
+  __asm__ __volatile__("lduba [%1] 2, %0\n\t"
 		       "or    %0, 0x10, %0\n\t"
-		       "stba  %0, [0x40000000] 0x2\n\t"
-		       "or    %g0, %g0, %0" : "=r" (success) : "0" (success));
+		       "stba  %0, [%1] 2\n\t"
+		       "or    %%g0, %%g0, %0" :
+		       "=r" (success) :
+		       "r" ((unsigned int) 0x40000000),
+		       "0" (success));
   return success;
 }
 
@@ -27,10 +32,13 @@
 {
   int success;
 
-  __asm__ __volatile__("lduba [0x40000000] 0x2, %0\n\t"
+  __asm__ __volatile__("lduba [%1] 0x2, %0\n\t"
 			"xor   %0, 0x10, %0\n\t"
-			"stba  %0, [0x40000000] 0x2\n\t"
-			"or    %g0, %g0, %0" : "=r" (success) : "0" (success));
+			"stba  %0, [%1] 0x2\n\t"
+			"or    %%g0, %%g0, %0" : 
+		       "=r" (success) : 
+		       "r" (0x40000000),
+		       "0" (success));
   return success;
 }
 
@@ -38,31 +46,31 @@
 
 extern __inline__ void hw_flush_vac_context_entry(char* addr)
 {
-  __asm__ __volatile__("sta 0, [%0] 0x7" : : "r" (addr));
+  __asm__ __volatile__("sta %%g0, [%0] 0x7" : : "r" (addr));
 }
 
 extern __inline__ void sw_flush_vac_context_entry(char* addr)
 {
-  __asm__ __volatile__("sta 0, [%0] 0xe" : : "r" (addr));
+  __asm__ __volatile__("sta %%g0, [%0] 0xe" : : "r" (addr));
 }
 
 extern __inline__ void hw_flush_vac_segment_entry(char* addr)
 {
-  __asm__ __volatile__("sta 0, [%0] 0x5" : : "r" (addr));
+  __asm__ __volatile__("sta %%g0, [%0] 0x5" : : "r" (addr));
 }
 
 extern __inline__ void sw_flush_vac_segment_entry(char* addr)
 {
-  __asm__ __volatile__("sta 0, [%0], 0xc" : : "r" (addr));
+  __asm__ __volatile__("sta %%g0, [%0] 0xc" : : "r" (addr));
 }
 
 extern __inline__ void hw_flush_vac_page_entry(char* addr)
 {
-  __asm__ __volatile__("sta 0, [%0] 0x6" : : "r" (addr));
+  __asm__ __volatile__("sta %%g0, [%0] 0x6" : : "r" (addr));
 }
 
 extern __inline__ void sw_flush_vac_page_entry(char* addr)
 {
-  __asm__ __volatile__("sta 0, [%0] 0xd" : : "r" (addr));
+  __asm__ __volatile__("sta %%g0, [%0] 0xd" : : "r" (addr));
 }
  
diff -u --recursive --new-file v1.1.75/linux/include/asm-sparc/wim.h linux/include/asm-sparc/wim.h
--- v1.1.75/linux/include/asm-sparc/wim.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/wim.h	Mon Jan  2 15:26:45 1995
@@ -0,0 +1,56 @@
+/* wim.h: Defines the layout of the "Window Invalid Register" on
+          Version 8 of the Sparc Architecture.
+
+   Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+*/
+
+#ifndef __LINUX_SPARC_WIM_H
+#define __LINUX_SPARC_WIM_H
+
+#ifdef __LINUX_SPARC_V8     /* register doesn't exist on the V9 */
+
+/* The Window Invalid Register %wim, holds a set of which register
+   windows are 'valid' at this point in time.
+
+   ------------------------------------------------------------
+   |W31|W30|W29|W28|W27|W26|W25|W24|W23|....|W5|W4|W3|W2|W1|W0|
+   ------------------------------------------------------------
+
+   Each register window on the chip gets one bit. If the bit is
+   set then the window is currently 'invalid' and hardware will
+   trap if that window is entered via a 'save', 'restore', or
+   'rett' instruction. Privileged software is responsible for
+   updating this on trap fills/spills etc. Therefore if a 'save'
+   instruction is executed and it causes the Current Window
+   Pointer to equal a register window which has it's bit set in
+   %wim we get a 'overflow' trap, a restore into such a register
+   invokes a window 'spill' trap.
+*/
+
+#define __LINUX_SPARC_HAS_WIM
+
+/* Macro to fine the %wim bit mask for the current window pointer */
+#define CWP_TO_WIM_MASK(cwp)  (1<<(cwp))
+
+/* Assembly version of above macro, 'cwp' and 'wimask' must be registers */
+#define ASM_CWP_TO_WIM_MASK(cwp,wimask) \
+          or  %g0, 0x1, wimask \
+          sll wimask, cwp, wimask
+
+/* Assembly macro to find if the given window is set to invalid in the %wim.
+   Again 'window', 'result', and 'scratch' must be in registers. This leaves 
+   a non-zero value in result if the window is indeed invalid. This routine
+   works because we keep exactly one window invalid at all times to maximize
+   register utilization, which means both kernel and user windows can be in
+   the register file at the same time in certain trap situations.
+*/
+#define ASM_REG_WIN_INVAL(window,result,scratch) \
+         rd  %wim, result \
+         or  %g0, 0x1, scratch \
+         sll scratch, window, scratch \
+         and scratch, result, result
+
+#endif /* !(__LINUX_SPARC_V8) */
+
+#endif  /* !(__LINUX_SPARC_WIM_H) */
+
diff -u --recursive --new-file v1.1.75/linux/include/linux/config.h linux/include/linux/config.h
--- v1.1.75/linux/include/linux/config.h	Thu Dec 29 20:15:58 1994
+++ linux/include/linux/config.h	Sun Jan  1 16:28:20 1995
@@ -48,37 +48,12 @@
  */
 
 /*
- * Normally, Linux can get the drive parameters from the BIOS at
- * startup, but if this for some unfathomable reason fails, you'd
- * be left stranded. For this case, you can define HD_TYPE, which
- * contains all necessary info on your harddisk.
- *
- * The HD_TYPE macro should look like this:
- *
- * #define HD_TYPE { head, sect, cyl, wpcom, lzone, ctl}
- *
- * In case of two harddisks, the info should be separated by
- * commas:
- *
- * #define HD_TYPE { h,s,c,wpcom,lz,ctl },{ h,s,c,wpcom,lz,ctl }
+ * HD_TYPE has been superceeded by kernel command line parameters.
  */
-/*
- This is an example, two drives, first is type 2, second is type 3:
-
-#define HD_TYPE { 4,17,615,300,615,8 }, { 6,17,615,300,615,0 }
-
- NOTE: ctl is 0 for all drives with heads<=8, and ctl=8 for drives
- with more than 8 heads.
 
- If you want the BIOS to tell what kind of drive you have, just
- leave HD_TYPE undefined. This is the normal thing to do.
-*/
-
-#undef HD_TYPE
- 
 /*
-	File type specific stuff goes into this.
-*/
+ *	File type specific stuff goes into this.
+ */
 
 #ifdef ASM_SRC
 #endif
diff -u --recursive --new-file v1.1.75/linux/include/linux/hdreg.h linux/include/linux/hdreg.h
--- v1.1.75/linux/include/linux/hdreg.h	Mon Oct 24 08:39:01 1994
+++ linux/include/linux/hdreg.h	Sun Jan  1 16:28:20 1995
@@ -44,7 +44,8 @@
 #define WIN_SEEK 		0x70
 #define WIN_DIAGNOSE		0x90
 #define WIN_SPECIFY		0x91
-#define WIN_SETIDLE		0x97
+#define WIN_SETIDLE1		0xE3
+#define WIN_SETIDLE2		0x97
 
 #define WIN_PIDENTIFY		0xA1	/* identify ATA-PI device	*/
 #define WIN_MULTREAD		0xC4	/* read multiple sectors	*/
@@ -72,16 +73,15 @@
 #define HDIO_GETGEO		0x301	/* get device geometry */
 #define HDIO_REQ		HDIO_GETGEO	/* obsolete, use HDIO_GETGEO */
 #define HDIO_GET_UNMASKINTR	0x302	/* get current unmask setting */
-#define HDIO_SETUNMASKINTR	0x303	/* obsolete */
 #define HDIO_GET_MULTCOUNT	0x304	/* get current IDE blockmode setting */
-#define HDIO_SETMULTCOUNT	0x305	/* obsolete */
 #define HDIO_GET_IDENTITY 	0x307	/* get IDE identification info */
+#define HDIO_GET_KEEPSETTINGS 	0x308	/* get keep-settings-on-reset flag */
+#define HDIO_DRIVE_CMD		0x31f	/* execute a special drive command */
 
 /* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x32n/0x33n */
 #define HDIO_SET_MULTCOUNT	0x321	/* set IDE blockmode */
 #define HDIO_SET_UNMASKINTR	0x322	/* permit other irqs during I/O */
 #define HDIO_SET_KEEPSETTINGS	0x323	/* keep ioctl settings on reset */
-#define HDIO_SET_XFERMODE	0x324	/* set IDE transfer mode */
 
 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
 struct hd_driveid {
@@ -133,4 +133,19 @@
 	/* unsigned short vendor7  [32];*/	/* vendor unique (words 128-159) */
 	/* unsigned short reservedyy[96];*/	/* reserved (words 160-255) */
 };
-#endif
+
+/*
+ * These routines are used for kernel command line parameters from main.c:
+ */
+#ifdef CONFIG_BLK_DEV_HD
+void hd_setup(char *, int *);
+#endif	/* CONFIG_BLK_DEV_HD */
+#ifdef CONFIG_BLK_DEV_IDE
+void ide_setup(char *, int *);
+void hda_setup(char *, int *);
+void hdb_setup(char *, int *);
+void hdc_setup(char *, int *);
+void hdd_setup(char *, int *);
+#endif	/* CONFIG_BLK_DEV_IDE */
+
+#endif	/* _LINUX_HDREG_H */
diff -u --recursive --new-file v1.1.75/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v1.1.75/linux/include/linux/interrupt.h	Thu Dec 29 20:15:59 1994
+++ linux/include/linux/interrupt.h	Sun Jan  1 16:28:20 1995
@@ -42,4 +42,34 @@
 	set_bit(nr, &bh_mask);
 }
 
+/*
+ * Autoprobing for irqs:
+ *
+ * probe_irq_on() and probe_irq_off() provide robust primitives
+ * for accurate IRQ probing during kernel initialization.  They are
+ * reasonably simple to use, are not "fooled" by spurious interrupts,
+ * and, unlike other attempts at IRQ probing, they do not get hung on
+ * stuck interrupts (such as unused PS2 mouse interfaces on ASUS boards).
+ *
+ * For reasonably foolproof probing, use them as follows:
+ *
+ * 1. clear and/or mask the device's internal interrupt.
+ * 2. sti();
+ * 3. irqs = probe_irq_on();      // "take over" all unassigned idle IRQs
+ * 4. enable the device and cause it to trigger an interrupt.
+ * 5. wait for the device to interrupt, using non-intrusive polling or a delay.
+ * 6. irq = probe_irq_off(irqs);  // get IRQ number, 0=none, negative=multiple
+ * 7. service the device to clear its pending interrupt.
+ * 8. loop again if paranoia is required.
+ *
+ * probe_irq_on() returns a mask of snarfed irq's.
+ *
+ * probe_irq_off() takes the mask as a parameter,
+ * and returns the irq number which occured,
+ * or zero if none occured, or a negative irq number
+ * if more than one irq occured.
+ */
+extern unsigned int probe_irq_on(void);	/* returns 0 on failure */
+extern int probe_irq_off(unsigned int); /* returns 0 or negative on failure */
+
 #endif
diff -u --recursive --new-file v1.1.75/linux/include/linux/kd.h linux/include/linux/kd.h
--- v1.1.75/linux/include/linux/kd.h	Tue Nov 22 15:41:14 1994
+++ linux/include/linux/kd.h	Sun Jan  1 19:49:19 1995
@@ -112,7 +112,9 @@
 #define KDGETKEYCODE	0x4B4C	/* read kernel keycode table entry */
 #define KDSETKEYCODE	0x4B4D	/* write kernel keycode table entry */
 
-/* note: 0x4B00-0x4B4D all have had a value at some time;
+#define KDSIGACCEPT	0x4B4E	/* accept kbd generated signals */
+
+/* note: 0x4B00-0x4B4E all have had a value at some time;
    don't reuse for the time being */
 /* note: 0x4B60-0x4B68 used above */
 
diff -u --recursive --new-file v1.1.75/linux/include/linux/keyboard.h linux/include/linux/keyboard.h
--- v1.1.75/linux/include/linux/keyboard.h	Thu Oct 13 14:07:09 1994
+++ linux/include/linux/keyboard.h	Sun Jan  1 19:49:19 1995
@@ -319,6 +319,7 @@
 #define K_SAK		K(KT_SPEC,15)
 #define K_DECRCONSOLE	K(KT_SPEC,16)
 #define K_INCRCONSOLE	K(KT_SPEC,17)
+#define K_SPAWNCONSOLE	K(KT_SPEC,18)
 
 #define K_ALLOCATED	K(KT_SPEC,126) /* dynamically allocated keymap */
 #define K_NOSUCHMAP	K(KT_SPEC,127) /* returned by KDGKBENT */
diff -u --recursive --new-file v1.1.75/linux/include/linux/lp.h linux/include/linux/lp.h
--- v1.1.75/linux/include/linux/lp.h	Thu Oct  6 07:16:22 1994
+++ linux/include/linux/lp.h	Thu Dec 29 20:13:17 1994
@@ -18,6 +18,8 @@
 #define LP_NOPA  0x0010
 #define LP_ERR   0x0020
 #define LP_ABORT 0x0040
+#define LP_CAREFUL 0x0080
+#define LP_ABORTOPEN 0x0100
 
 /* timeout for each character.  This is relative to bus cycles -- it
  * is the count in a busy loop.  THIS IS THE VALUE TO CHANGE if you
@@ -59,6 +61,12 @@
 			    or 0 for polling (no IRQ) */
 #define LPGETIRQ 0x0006  /* get the current IRQ number */
 #define LPWAIT   0x0008  /* corresponds to LP_INIT_WAIT */
+#define LPCAREFUL   0x0009  /* call with TRUE arg to require out-of-paper, off-
+			    line, and error indicators good on all writes,
+			    FALSE to ignore them.  Default is ignore. */
+#define LPABORTOPEN 0x000a  /* call with TRUE arg to abort open() on error,
+			    FALSE to ignore error.  Default is ignore.  */
+#define LPGETSTATUS 0x000b  /* return LP_S(minor) */
 
 /* timeout for printk'ing a timeout, in jiffies (100ths of a second).
    This is also used for re-checking error conditions if LP_ABORT is
diff -u --recursive --new-file v1.1.75/linux/include/linux/major.h linux/include/linux/major.h
--- v1.1.75/linux/include/linux/major.h	Fri Jul  8 11:36:04 1994
+++ linux/include/linux/major.h	Sun Jan  1 16:28:20 1995
@@ -51,7 +51,8 @@
 #define UNNAMED_MAJOR	0
 #define MEM_MAJOR	1
 #define FLOPPY_MAJOR	2
-#define HD_MAJOR	3
+#define IDE0_MAJOR	3
+#define HD_MAJOR	IDE0_MAJOR
 #define TTY_MAJOR	4
 #define TTYAUX_MAJOR	5
 #define LP_MAJOR	6
@@ -69,7 +70,7 @@
 #define AF_INET_MAJOR	18
 /* unused: 19, 20 */
 #define SCSI_GENERIC_MAJOR 21
-/* unused: 22 */
+#define IDE1_MAJOR	22
 #define MITSUMI_CDROM_MAJOR 23
 #define CDU535_CDROM_MAJOR 24
 #define MATSUSHITA_CDROM_MAJOR 25
diff -u --recursive --new-file v1.1.75/linux/include/linux/mm.h linux/include/linux/mm.h
--- v1.1.75/linux/include/linux/mm.h	Thu Dec  1 19:15:05 1994
+++ linux/include/linux/mm.h	Thu Dec 29 19:58:42 1994
@@ -6,6 +6,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
@@ -150,10 +151,7 @@
 
 	page = __get_free_page(priority);
 	if (page)
-		__asm__ __volatile__("rep ; stosl"
-			: /* no outputs */ \
-			:"a" (0),"c" (1024),"D" (page)
-			:"di","cx");
+		memset((void *) page, 0, PAGE_SIZE);
 	return page;
 }
 
diff -u --recursive --new-file v1.1.75/linux/include/linux/sched.h linux/include/linux/sched.h
--- v1.1.75/linux/include/linux/sched.h	Thu Dec 29 20:15:59 1994
+++ linux/include/linux/sched.h	Fri Dec 30 08:29:42 1994
@@ -156,7 +156,7 @@
 	unsigned long personality;
 	int dumpable:1;
 	int did_exec:1;
-	int pid,pgrp,session,leader;
+	int pid,pgrp,tty_old_pgrp,session,leader;
 	int	groups[NGROUPS];
 	/* 
 	 * pointers to (original) parent process, youngest child, younger sibling,
@@ -219,7 +219,7 @@
 /* signals */	{{ 0, },}, \
 /* stack */	0,(unsigned long) &init_kernel_stack, \
 /* ec,brk... */	0,0,0,0,0, \
-/* pid etc.. */	0,0,0,0, \
+/* pid etc.. */	0,0,0,0,0, \
 /* suppl grps*/ {NOGROUP,}, \
 /* proc links*/ &init_task,&init_task,NULL,NULL,NULL,NULL, \
 /* uid etc */	0,0,0,0,0,0,0,0, \
diff -u --recursive --new-file v1.1.75/linux/include/linux/socket.h linux/include/linux/socket.h
--- v1.1.75/linux/include/linux/socket.h	Thu Dec 15 11:01:56 1994
+++ linux/include/linux/socket.h	Sun Jan  1 15:33:21 1995
@@ -81,7 +81,7 @@
 #define	IPTOS_THROUGHPUT	0x08
 #define	IPTOS_RELIABILITY	0x04
 #define IP_TTL		2
-#ifdef 1_3_WILL_DO_THIS_FUNKY_STUFF
+#ifdef V1_3_WILL_DO_THIS_FUNKY_STUFF
 #define IP_HRDINCL	3
 #define IP_OPTIONS	4
 #endif
diff -u --recursive --new-file v1.1.75/linux/include/linux/time.h linux/include/linux/time.h
--- v1.1.75/linux/include/linux/time.h	Wed Dec  1 14:44:15 1993
+++ linux/include/linux/time.h	Mon Jan  2 09:06:25 1995
@@ -13,11 +13,21 @@
 
 #define NFDBITS			__NFDBITS
 
+#ifdef __KERNEL__
+#include <asm/bitops.h>
+#include <linux/string.h>
+#define FD_SETSIZE		__FD_SETSIZE
+#define FD_SET(fd,fdsetp)	set_bit(fd,fdsetp)
+#define FD_CLR(fd,fdsetp)	clear_bit(fd,fdsetp)
+#define FD_ISSET(fd,fdsetp)	(0 != test_bit(fd,fdsetp))
+#define FD_ZERO(fdsetp)		memset(fdsetp, 0, sizeof(struct fd_set))
+#else
 #define FD_SETSIZE		__FD_SETSIZE
 #define FD_SET(fd,fdsetp)	__FD_SET(fd,fdsetp)
 #define FD_CLR(fd,fdsetp)	__FD_CLR(fd,fdsetp)
 #define FD_ISSET(fd,fdsetp)	__FD_ISSET(fd,fdsetp)
 #define FD_ZERO(fdsetp)		__FD_ZERO(fdsetp)
+#endif
 
 /*
  * Names of the interval timers, and structure
diff -u --recursive --new-file v1.1.75/linux/include/linux/tpqic02.h linux/include/linux/tpqic02.h
--- v1.1.75/linux/include/linux/tpqic02.h	Wed Aug 10 19:26:44 1994
+++ linux/include/linux/tpqic02.h	Sun Jan  1 19:49:19 1995
@@ -2,7 +2,7 @@
  *
  * Include file for QIC-02 driver for Linux.
  *
- * Copyright (c) 1992, 1993, 1994 by H. H. Bergman. All rights reserved.
+ * Copyright (c) 1992--1995 by H. H. Bergman. All rights reserved.
  *
  * ******* USER CONFIG SECTION BELOW (Near line 70) *******
  */
@@ -504,7 +504,8 @@
 
 #define TPQD_ALWAYS	0x8000
 
-#define TPQD_DEFAULT_FLAGS	0x01fc
+#define TPQD_DEFAULT_FLAGS	0x00fc
+
 
 #define TPQDBG(f)	((QIC02_TAPE_DEBUG) & (TPQD_##f))
 
diff -u --recursive --new-file v1.1.75/linux/init/main.c linux/init/main.c
--- v1.1.75/linux/init/main.c	Thu Dec 29 20:15:59 1994
+++ linux/init/main.c	Sun Jan  1 16:28:20 1995
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/utsname.h>
 #include <linux/ioport.h>
+#include <linux/hdreg.h>
 
 #include <asm/bugs.h>
 
@@ -80,7 +81,15 @@
 unsigned long net_dev_init(unsigned long, unsigned long);
 extern long bios32_init(long, long);
 
+#ifdef CONFIG_BLK_DEV_IDE
+extern void ide_setup(char *str, int *ints);
+extern void hda_setup(char *str, int *ints);
+extern void hdb_setup(char *str, int *ints);
+extern void hdc_setup(char *str, int *ints);
+extern void hdd_setup(char *str, int *ints);
+#else
 extern void hd_setup(char *str, int *ints);
+#endif /* CONFIG_BLK_DEV_IDE */
 extern void bmouse_setup(char *str, int *ints);
 extern void eth_setup(char *str, int *ints);
 extern void xd_setup(char *str, int *ints);
@@ -191,7 +200,13 @@
 #ifdef CONFIG_SCSI
 	{ "max_scsi_luns=", scsi_luns_setup },
 #endif
-#ifdef CONFIG_BLK_DEV_HD
+#ifdef CONFIG_BLK_DEV_IDE
+	{ "hda=", hda_setup },
+	{ "hdb=", hdb_setup },
+	{ "hdc=", hdc_setup },
+	{ "hdd=", hdd_setup },
+	{ "hd=",  ide_setup },
+#elif defined(CONFIG_BLK_DEV_HD)
 	{ "hd=", hd_setup },
 #endif
 #ifdef CONFIG_CHR_DEV_ST
@@ -303,15 +318,14 @@
  * variable if it contains the character '='.
  *
  *
- * This routine also checks for options meant for the kernel - currently
- * only the "root=XXXX" option is recognized. These options are not given
- * to init - they are for internal kernel use only.
+ * This routine also checks for options meant for the kernel.
+ * These options are not given to init - they are for internal kernel use only.
  */
 static void parse_options(char *line)
 {
 	char *next;
-	char *devnames[] = { "hda", "hdb", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
-	int devnums[]    = { 0x300, 0x340, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
+	char *devnames[] = { "hda", "hdb", "hdc", "hdd", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
+	int devnums[]    = { 0x300, 0x340, 0x1600, 0x1640, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
 	int args, envs;
 
 	if (!*line)
diff -u --recursive --new-file v1.1.75/linux/init/version.c linux/init/version.c
--- v1.1.75/linux/init/version.c	Thu Jan  1 02:00:00 1970
+++ linux/init/version.c	Thu Dec 29 19:58:43 1994
@@ -0,0 +1,20 @@
+/*
+ *  linux/version.c
+ *
+ *  Copyright (C) 1992  Theodore Ts'o
+ *
+ *  May be freely distributed as part of Linux.
+ */
+
+#include <linux/config.h>
+#include <linux/utsname.h>
+#include <linux/version.h>
+
+struct new_utsname system_utsname = {
+	UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION,
+	UTS_MACHINE, UTS_DOMAINNAME
+};
+
+char *linux_banner = 
+	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
diff -u --recursive --new-file v1.1.75/linux/kernel/dma.c linux/kernel/dma.c
--- v1.1.75/linux/kernel/dma.c	Tue Aug 23 09:49:08 1994
+++ linux/kernel/dma.c	Sun Jan  1 19:49:19 1995
@@ -1,6 +1,13 @@
-/* $Id: dma.c,v 1.5 1992/11/18 02:49:05 root Exp root $
+/* $Id: dma.c,v 1.7 1994/12/28 03:35:33 root Exp root $
  * linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c.
- * Written by Hennus Bergman, 1992. 
+ *
+ * Written by Hennus Bergman, 1992.
+ *
+ * 1994/12/26: Changes by Alex Nash to fix a minor bug in /proc/dma.
+ *   In the previous version the reported device could end up being wrong,
+ *   if a device requested a DMA channel that was already in use.
+ *   [It also happened to remove the sizeof(char *) == sizeof(int)
+ *   assumption introduced because of those /proc/dma patches. -- Hennus]
  */
 
 #include <linux/kernel.h>
@@ -15,7 +22,7 @@
  *
  * In order to avoid problems, all processes should allocate resources in
  * the same sequence and release them in the reverse order.
- * 
+ *
  * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA.
  * When releasing them, first release the DMA, then release the IRQ.
  * If you don't, you may cause allocation requests to fail unnecessarily.
@@ -29,20 +36,21 @@
  * DMA0 used to be reserved for DRAM refresh, but apparently not any more...
  * DMA4 is reserved for cascading.
  */
-/*
-static volatile unsigned int dma_chan_busy[MAX_DMA_CHANNELS] = {
-	0, 0, 0, 0, 1, 0, 0, 0
+
+struct dma_chan {
+	int  lock;
+	char *device_id;
 };
-*/
-static volatile char * dma_chan_busy[MAX_DMA_CHANNELS] = {
-	0,
-	0,
-	0,
-	0,
-	"cascade",
-	0,
-	0,
-	0
+
+static volatile struct dma_chan dma_chan_busy[MAX_DMA_CHANNELS] = {
+	{ 0, 0 },
+	{ 0, 0 },
+	{ 0, 0 },
+	{ 0, 0 },
+	{ 1, "cascade" },
+	{ 0, 0 },
+	{ 0, 0 },
+	{ 0, 0 }
 };
 
 /* Atomically swap memory location [32 bits] with `newval'.
@@ -63,9 +71,9 @@
 	 */
 
 	asm __volatile__ ("xchgl %2, %0\n"
-			: /* outputs: semval   */ "=r" (semval)
-			: /* inputs: newval, p */ "0" (semval), "m" (*p)
-			);	/* p is a var, containing an address */
+			  : /* outputs: semval   */ "=r" (semval)
+			  : /* inputs: newval, p */ "0" (semval), "m" (*p)
+			 );	/* p is a var, containing an address */
 	return semval;
 } /* mutex_atomic_swap */
 
@@ -75,23 +83,26 @@
 	int i, len = 0;
 
 	for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) {
-		if (dma_chan_busy[i]) {
+		if (dma_chan_busy[i].lock) {
 		    len += sprintf(buf+len, "%2d: %s\n",
-				i,
-				dma_chan_busy[i]);
+				   i,
+				   dma_chan_busy[i].device_id);
 		}
 	}
 	return len;
-}
+} /* get_dma_list */
+
 
-int request_dma(unsigned int dmanr, char * deviceID)
+int request_dma(unsigned int dmanr, char * device_id)
 {
 	if (dmanr >= MAX_DMA_CHANNELS)
 		return -EINVAL;
 
-	if (mutex_atomic_swap((unsigned int *) &dma_chan_busy[dmanr], (unsigned int) deviceID) != 0) 
+	if (mutex_atomic_swap((unsigned int *) &dma_chan_busy[dmanr].lock, 1) != 0)
 		return -EBUSY;
 
+	dma_chan_busy[dmanr].device_id = device_id;
+
 	/* old flag was 0, now contains 1 to indicate busy */
 	return 0;
 } /* request_dma */
@@ -104,10 +115,9 @@
 		return;
 	}
 
-	if (mutex_atomic_swap((unsigned int *) &dma_chan_busy[dmanr], 0) == 0) {
+	if (mutex_atomic_swap((unsigned int *) &dma_chan_busy[dmanr].lock, 0) == 0) {
 		printk("Trying to free free DMA%d\n", dmanr);
 		return;
 	}	
 
 } /* free_dma */
-
diff -u --recursive --new-file v1.1.75/linux/kernel/fork.c linux/kernel/fork.c
--- v1.1.75/linux/kernel/fork.c	Thu Dec 29 20:15:59 1994
+++ linux/kernel/fork.c	Fri Dec 30 08:29:42 1994
@@ -201,6 +201,7 @@
 	p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
 	p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
 	p->leader = 0;		/* process leadership doesn't inherit */
+	p->tty_old_pgrp = 0;
 	p->utime = p->stime = 0;
 	p->cutime = p->cstime = 0;
 	p->start_time = jiffies;
diff -u --recursive --new-file v1.1.75/linux/kernel/irq.c linux/kernel/irq.c
--- v1.1.75/linux/kernel/irq.c	Tue Dec 27 09:56:47 1994
+++ linux/kernel/irq.c	Sun Jan  1 16:28:20 1995
@@ -32,6 +32,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/bitops.h>
 
 #define CR0_NE 32
 
@@ -234,6 +235,8 @@
 	sa->sa_handler(irq);
 }
 
+#define SA_PROBE SA_ONESHOT
+
 /*
  * Using "struct sigaction" is slightly silly, but there
  * are historical reasons and it works well, so..
@@ -253,10 +256,12 @@
 	save_flags(flags);
 	cli();
 	*sa = *new_sa;
-	if (sa->sa_flags & SA_INTERRUPT)
-		set_intr_gate(0x20+irq,fast_interrupt[irq]);
-	else
-		set_intr_gate(0x20+irq,interrupt[irq]);
+	if (!(sa->sa_flags & SA_PROBE)) { /* SA_ONESHOT is used by probing */
+		if (sa->sa_flags & SA_INTERRUPT)
+			set_intr_gate(0x20+irq,fast_interrupt[irq]);
+		else
+			set_intr_gate(0x20+irq,interrupt[irq]);
+	}
 	if (irq < 8) {
 		cache_21 &= ~(1<<irq);
 		outb(cache_21,0x21);
@@ -332,6 +337,58 @@
 }
 
 static void no_action(int cpl) { }
+
+unsigned int probe_irq_on (void)
+{
+	unsigned int i, irqs = 0, irqmask;
+	unsigned long delay;
+
+	/* first, snaffle up any unassigned irqs */
+	for (i = 15; i > 0; i--) {
+		if (!request_irq(i, no_action, SA_PROBE, "probe")) {
+			enable_irq(i);
+			irqs |= (1 << i);
+		}
+	}
+
+	/* wait for spurious interrupts to mask themselves out again */
+	for (delay = jiffies + 2; delay > jiffies; );	/* min 10ms delay */
+
+	/* now filter out any obviously spurious interrupts */
+	irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
+	for (i = 15; i > 0; i--) {
+		if (irqs & (1 << i) & irqmask) {
+			irqs ^= (1 << i);
+			free_irq(i);
+		}
+	}
+#ifdef DEBUG
+	printk("probe_irq_on:  irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
+#endif
+	return irqs;
+}
+
+int probe_irq_off (unsigned int irqs)
+{
+	unsigned int i, irqmask;
+
+	irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
+	for (i = 15; i > 0; i--) {
+		if (irqs & (1 << i)) {
+			free_irq(i);
+		}
+	}
+#ifdef DEBUG
+	printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
+#endif
+	irqs &= irqmask;
+	if (!irqs)
+		return 0;
+	i = ffz(~irqs);
+	if (irqs != (irqs & (1 << i)))
+		i = -i;
+	return i;
+}
 
 void init_IRQ(void)
 {
diff -u --recursive --new-file v1.1.75/linux/kernel/printk.c linux/kernel/printk.c
--- v1.1.75/linux/kernel/printk.c	Mon Dec  5 18:47:56 1994
+++ linux/kernel/printk.c	Fri Dec 30 08:16:08 1994
@@ -129,7 +129,7 @@
 			console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
 			return 0;
 		case 8:
-			if (len < 0 || len > 8)
+			if (len < 1 || len > 8)
 				return -EINVAL;
 			console_loglevel = len;
 			return 0;
diff -u --recursive --new-file v1.1.75/linux/kernel/sys.c linux/kernel/sys.c
--- v1.1.75/linux/kernel/sys.c	Thu Dec  1 19:15:05 1994
+++ linux/kernel/sys.c	Fri Dec 30 08:20:19 1994
@@ -152,6 +152,7 @@
 }
 
 extern void hard_reset_now(void);
+extern asmlinkage sys_kill(int, int);
 
 /*
  * Reboot system call: for obvious reasons only root may call it,
@@ -173,7 +174,11 @@
 		C_A_D = 1;
 	else if (!flag)
 		C_A_D = 0;
-	else
+	else if (flag == 0xCDEF0123) {
+		printk(KERN_EMERG "System halted\n");
+		sys_kill(-1, SIGKILL);
+		do_exit(0);
+	} else
 		return -EINVAL;
 	return (0);
 }
diff -u --recursive --new-file v1.1.75/linux/kernel/traps.c linux/kernel/traps.c
--- v1.1.75/linux/kernel/traps.c	Thu Dec 29 20:15:59 1994
+++ linux/kernel/traps.c	Thu Jan  1 02:00:00 1970
@@ -1,310 +0,0 @@
-/*
- *  linux/kernel/traps.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-/*
- * 'Traps.c' handles hardware traps and faults after we have saved some
- * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
- * to mainly kill the offending process (probably by giving it a signal,
- * but possibly by killing it outright if necessary).
- */
-#include <linux/head.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/config.h>
-#include <linux/timer.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-
-asmlinkage int system_call(void);
-asmlinkage void lcall7(void);
-struct desc_struct default_ldt;
-
-static inline void console_verbose(void)
-{
-	extern int console_loglevel;
-	console_loglevel = 15;
-}
-
-#define DO_ERROR(trapnr, signr, str, name, tsk) \
-asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
-{ \
-	tsk->tss.error_code = error_code; \
-	tsk->tss.trap_no = trapnr; \
-	if (signr == SIGTRAP && current->flags & PF_PTRACED) \
-		current->blocked &= ~(1 << (SIGTRAP-1)); \
-	send_sig(signr, tsk, 1); \
-	die_if_kernel(str,regs,error_code); \
-}
-
-#define get_seg_byte(seg,addr) ({ \
-register unsigned char __res; \
-__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
-	:"=a" (__res):"0" (seg),"m" (*(addr))); \
-__res;})
-
-#define get_seg_long(seg,addr) ({ \
-register unsigned long __res; \
-__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \
-	:"=a" (__res):"0" (seg),"m" (*(addr))); \
-__res;})
-
-#define _fs() ({ \
-register unsigned short __res; \
-__asm__("mov %%fs,%%ax":"=a" (__res):); \
-__res;})
-
-void page_exception(void);
-
-asmlinkage void divide_error(void);
-asmlinkage void debug(void);
-asmlinkage void nmi(void);
-asmlinkage void int3(void);
-asmlinkage void overflow(void);
-asmlinkage void bounds(void);
-asmlinkage void invalid_op(void);
-asmlinkage void device_not_available(void);
-asmlinkage void double_fault(void);
-asmlinkage void coprocessor_segment_overrun(void);
-asmlinkage void invalid_TSS(void);
-asmlinkage void segment_not_present(void);
-asmlinkage void stack_segment(void);
-asmlinkage void general_protection(void);
-asmlinkage void page_fault(void);
-asmlinkage void coprocessor_error(void);
-asmlinkage void reserved(void);
-asmlinkage void alignment_check(void);
-
-/*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err)
-{
-	int i;
-	unsigned long esp;
-	unsigned short ss;
-
-	esp = (unsigned long) &regs->esp;
-	ss = KERNEL_DS;
-	if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3)
-		return;
-	if (regs->cs & 3) {
-		esp = regs->esp;
-		ss = regs->ss;
-	}
-	console_verbose();
-	printk("%s: %04lx\n", str, err & 0xffff);
-	printk("EIP:    %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags);
-	printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
-		regs->eax, regs->ebx, regs->ecx, regs->edx);
-	printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
-		regs->esi, regs->edi, regs->ebp, esp);
-	printk("ds: %04x   es: %04x   fs: %04x   gs: %04x   ss: %04x\n",
-		regs->ds, regs->es, regs->fs, regs->gs, ss);
-	store_TR(i);
-	if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
-		printk("Corrupted stack page\n");
-	printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ",
-		current->comm, current->pid, 0xffff & i, current->kernel_stack_page);
-	for(i=0;i<5;i++)
-		printk("%08lx ", get_seg_long(ss,(i+(unsigned long *)esp)));
-	printk("\nCode: ");
-	for(i=0;i<20;i++)
-		printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip)));
-	printk("\n");
-	do_exit(SIGSEGV);
-}
-
-DO_ERROR( 0, SIGFPE,  "divide error", divide_error, current)
-DO_ERROR( 3, SIGTRAP, "int3", int3, current)
-DO_ERROR( 4, SIGSEGV, "overflow", overflow, current)
-DO_ERROR( 5, SIGSEGV, "bounds", bounds, current)
-DO_ERROR( 6, SIGILL,  "invalid operand", invalid_op, current)
-DO_ERROR( 7, SIGSEGV, "device not available", device_not_available, current)
-DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current)
-DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math)
-DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
-DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present, current)
-DO_ERROR(12, SIGBUS,  "stack segment", stack_segment, current)
-DO_ERROR(15, SIGSEGV, "reserved", reserved, current)
-DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
-
-asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
-{
-	int signr = SIGSEGV;
-
-	if (regs->eflags & VM_MASK) {
-		handle_vm86_fault((struct vm86_regs *) regs, error_code);
-		return;
-	}
-	die_if_kernel("general protection",regs,error_code);
-	switch (get_seg_byte(regs->cs, (char *)regs->eip)) {
-		case 0xCD: /* INT */
-		case 0xF4: /* HLT */
-		case 0xFA: /* CLI */
-		case 0xFB: /* STI */
-			signr = SIGILL;
-	}
-	current->tss.error_code = error_code;
-	current->tss.trap_no = 13;
-	send_sig(signr, current, 1);	
-}
-
-asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
-{
-	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
-	printk("You probably have a hardware problem with your RAM chips\n");
-}
-
-asmlinkage void do_debug(struct pt_regs * regs, long error_code)
-{
-	if (regs->eflags & VM_MASK) {
-		handle_vm86_debug((struct vm86_regs *) regs, error_code);
-		return;
-	}
-	if (current->flags & PF_PTRACED)
-		current->blocked &= ~(1 << (SIGTRAP-1));
-	send_sig(SIGTRAP, current, 1);
-	current->tss.trap_no = 1;
-	current->tss.error_code = error_code;
-	if ((regs->cs & 3) == 0) {
-		/* If this is a kernel mode trap, then reset db7 and allow us to continue */
-		__asm__("movl %0,%%db7"
-			: /* no output */
-			: "r" (0));
-		return;
-	}
-	die_if_kernel("debug",regs,error_code);
-}
-
-/*
- * Allow the process which triggered the interrupt to recover the error
- * condition.
- *  - the status word is saved in the cs selector.
- *  - the tag word is saved in the operand selector.
- *  - the status word is then cleared and the tags all set to Empty.
- *
- * This will give sufficient information for complete recovery provided that
- * the affected process knows or can deduce the code and data segments
- * which were in force when the exception condition arose.
- *
- * Note that we play around with the 'TS' bit to hopefully get
- * the correct behaviour even in the presence of the asynchronous
- * IRQ13 behaviour
- */
-void math_error(void)
-{
-	struct i387_hard_struct * env;
-
-	clts();
-	if (!last_task_used_math) {
-		__asm__("fnclex");
-		return;
-	}
-	env = &last_task_used_math->tss.i387.hard;
-	send_sig(SIGFPE, last_task_used_math, 1);
-	last_task_used_math->tss.trap_no = 16;
-	last_task_used_math->tss.error_code = 0;
-	__asm__ __volatile__("fnsave %0":"=m" (*env));
-	last_task_used_math = NULL;
-	stts();
-	env->fcs = (env->swd & 0x0000ffff) | (env->fcs & 0xffff0000);
-	env->fos = env->twd;
-	env->swd &= 0xffff3800;
-	env->twd = 0xffffffff;
-}
-
-asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
-{
-	ignore_irq13 = 1;
-	math_error();
-}
-
-/*
- *  'math_state_restore()' saves the current math information in the
- * old math state array, and gets the new ones from the current task
- *
- * Careful.. There are problems with IBM-designed IRQ13 behaviour.
- * Don't touch unless you *really* know how it works.
- */
-asmlinkage void math_state_restore(void)
-{
-	__asm__ __volatile__("clts");
-	if (last_task_used_math == current)
-		return;
-	timer_table[COPRO_TIMER].expires = jiffies+50;
-	timer_active |= 1<<COPRO_TIMER;	
-	if (last_task_used_math)
-		__asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
-	else
-		__asm__("fnclex");
-	last_task_used_math = current;
-	if (current->used_math) {
-		__asm__("frstor %0": :"m" (current->tss.i387));
-	} else {
-		__asm__("fninit");
-		current->used_math=1;
-	}
-	timer_active &= ~(1<<COPRO_TIMER);
-}
-
-#ifndef CONFIG_MATH_EMULATION
-
-asmlinkage void math_emulate(long arg)
-{
-  printk("math-emulation not enabled and no coprocessor found.\n");
-  printk("killing %s.\n",current->comm);
-  send_sig(SIGFPE,current,1);
-  schedule();
-}
-
-#endif /* CONFIG_MATH_EMULATION */
-
-void trap_init(void)
-{
-	int i;
-	struct desc_struct * p;
-
-	set_call_gate(&default_ldt,lcall7);
-	set_trap_gate(0,&divide_error);
-	set_trap_gate(1,&debug);
-	set_trap_gate(2,&nmi);
-	set_system_gate(3,&int3);	/* int3-5 can be called from all */
-	set_system_gate(4,&overflow);
-	set_system_gate(5,&bounds);
-	set_trap_gate(6,&invalid_op);
-	set_trap_gate(7,&device_not_available);
-	set_trap_gate(8,&double_fault);
-	set_trap_gate(9,&coprocessor_segment_overrun);
-	set_trap_gate(10,&invalid_TSS);
-	set_trap_gate(11,&segment_not_present);
-	set_trap_gate(12,&stack_segment);
-	set_trap_gate(13,&general_protection);
-	set_trap_gate(14,&page_fault);
-	set_trap_gate(15,&reserved);
-	set_trap_gate(16,&coprocessor_error);
-	set_trap_gate(17,&alignment_check);
-	for (i=18;i<48;i++)
-		set_trap_gate(i,&reserved);
-	set_system_gate(0x80,&system_call);
-/* set up GDT task & ldt entries */
-	p = gdt+FIRST_TSS_ENTRY;
-	set_tss_desc(p, &init_task.tss);
-	p++;
-	set_ldt_desc(p, &default_ldt, 1);
-	p++;
-	for(i=1 ; i<NR_TASKS ; i++) {
-		p->a=p->b=0;
-		p++;
-		p->a=p->b=0;
-		p++;
-	}
-/* Clear NT, so that we won't have troubles with that later on */
-	__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
-	load_TR(0);
-	load_ldt(0);
-}
diff -u --recursive --new-file v1.1.75/linux/makever.sh linux/makever.sh
--- v1.1.75/linux/makever.sh	Wed Dec  1 14:44:15 1993
+++ linux/makever.sh	Thu Jan  1 02:00:00 1970
@@ -1,13 +0,0 @@
-#! /bin/sh
-
-if [ ! -f .version ]
-then
-	echo 0 > .version
-fi
-cycle=`cat .version`
-cycle=`expr $cycle + 1`
-if [ $cycle -gt 99 ]
-then
-	cycle=0
-fi
-echo $cycle > .version
diff -u --recursive --new-file v1.1.75/linux/net/inet/tcp.c linux/net/inet/tcp.c
--- v1.1.75/linux/net/inet/tcp.c	Thu Dec 29 20:16:00 1994
+++ linux/net/inet/tcp.c	Mon Jan  2 13:03:00 1995
@@ -1015,7 +1015,7 @@
 				IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
 	if (tmp < 0) 
 	{
-  		buff->free=1;
+  		buff->free = 1;
 		sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
 		return;
 	}
@@ -1482,7 +1482,7 @@
 			       IPPROTO_TCP, sk->opt, MAX_ACK_SIZE,sk->ip_tos,sk->ip_ttl);
 	if (tmp < 0) 
 	{
-  		buff->free=1;
+  		buff->free = 1;
 		sk->prot->wfree(sk, buff->mem_addr, buff->mem_len);
 		return;
 	}
@@ -1905,7 +1905,7 @@
   		 *	Enter FIN_WAIT2 on abnormal shutdown -- close before
   		 *	connection established.
   		 */
-	  	buff->free=1;
+	  	buff->free = 1;
 		prot->wfree(sk,buff->mem_addr, buff->mem_len);
 
 		if (sk->state == TCP_ESTABLISHED)
@@ -1941,7 +1941,7 @@
  	
  	if (skb_peek(&sk->write_queue) != NULL) 
  	{
-  		buff->free=0;
+  		buff->free = 0;
 		if (buff->next != NULL) 
 		{
 			printk("tcp_shutdown: next != NULL\n");
@@ -2380,7 +2380,7 @@
 	if (tmp < 0) 
 	{
 		sk->err = tmp;
-		buff->free=1;
+		buff->free = 1;
 		kfree_skb(buff,FREE_WRITE);
 		newsk->dead = 1;
 		release_sock(newsk);
@@ -2555,7 +2555,7 @@
 				return;
 			}
 			buff->sk = sk;
-			buff->free = 1;
+			buff->free = 0;
 			buff->len = sizeof(*t1);
 			buff->localroute = sk->localroute;
 			t1 =(struct tcphdr *) buff->data;
@@ -2610,7 +2610,7 @@
 			tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
 
 			tcp_statistics.TcpOutSegs++;
-	
+
 			if (skb_peek(&sk->write_queue) == NULL) 
 			{
 				sk->sent_seq = sk->write_seq;
@@ -3850,7 +3850,7 @@
 	sk->inuse = 1;
 	buff->len = 24;
 	buff->sk = sk;
-	buff->free = 1;
+	buff->free = 0;
 	buff->localroute = sk->localroute;
 	
 	t1 = (struct tcphdr *) buff->data;
diff -u --recursive --new-file v1.1.75/linux/tools/build.c linux/tools/build.c
--- v1.1.75/linux/tools/build.c	Wed Aug 10 19:23:01 1994
+++ linux/tools/build.c	Thu Jan  1 02:00:00 1970
@@ -1,238 +0,0 @@
-/*
- *  linux/tools/build.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-/*
- * This file builds a disk-image from three different files:
- *
- * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
- * - setup: 8086 machine code, sets up system parm
- * - system: 80386 code for actual system
- *
- * It does some checking that all files are of the correct type, and
- * just writes the result to stdout, removing headers and padding to
- * the right amount. It also writes some system data to stderr.
- */
-
-/*
- * Changes by tytso to allow root device specification
- */
-
-#include <stdio.h>	/* fprintf */
-#include <string.h>
-#include <stdlib.h>	/* contains exit */
-#include <sys/types.h>	/* unistd.h needs this */
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <unistd.h>	/* contains read/write */
-#include <fcntl.h>
-#include <linux/config.h>
-#include <linux/a.out.h>
-
-#define MINIX_HEADER 32
-
-#define N_MAGIC_OFFSET 1024
-static int GCC_HEADER = sizeof(struct exec);
-
-#define SYS_SIZE DEF_SYSSIZE
-
-#define DEFAULT_MAJOR_ROOT 0
-#define DEFAULT_MINOR_ROOT 0
-
-/* max nr of sectors of setup: don't change unless you also change
- * bootsect etc */
-#define SETUP_SECTS 4
-
-#define STRINGIFY(x) #x
-
-typedef union {
-	long l;
-	short s[2];
-	char b[4];
-} conv;
-
-long intel_long(long l)
-{
-	conv t;
-
-	t.b[0] = l & 0xff; l >>= 8;
-	t.b[1] = l & 0xff; l >>= 8;
-	t.b[2] = l & 0xff; l >>= 8;
-	t.b[3] = l & 0xff; l >>= 8;
-	return t.l;
-}
-
-short intel_short(short l)
-{
-	conv t;
-
-	t.b[0] = l & 0xff; l >>= 8;
-	t.b[1] = l & 0xff; l >>= 8;
-	return t.s[0];
-}
-
-void die(char * str)
-{
-	fprintf(stderr,"%s\n",str);
-	exit(1);
-}
-
-void usage(void)
-{
-	die("Usage: build bootsect setup system [rootdev] [> image]");
-}
-
-int main(int argc, char ** argv)
-{
-	int i,c,id, sz;
-	unsigned long sys_size;
-	char buf[1024];
-	struct exec *ex = (struct exec *)buf;
-	char major_root, minor_root;
-	struct stat sb;
-	unsigned char setup_sectors;
-
-	if ((argc < 4) || (argc > 5))
-		usage();
-	if (argc > 4) {
-		if (!strcmp(argv[4], "CURRENT")) {
-			if (stat("/", &sb)) {
-				perror("/");
-				die("Couldn't stat /");
-			}
-			major_root = major(sb.st_dev);
-			minor_root = minor(sb.st_dev);
-		} else if (strcmp(argv[4], "FLOPPY")) {
-			if (stat(argv[4], &sb)) {
-				perror(argv[4]);
-				die("Couldn't stat root device.");
-			}
-			major_root = major(sb.st_rdev);
-			minor_root = minor(sb.st_rdev);
-		} else {
-			major_root = 0;
-			minor_root = 0;
-		}
-	} else {
-		major_root = DEFAULT_MAJOR_ROOT;
-		minor_root = DEFAULT_MINOR_ROOT;
-	}
-	fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
-	for (i=0;i<sizeof buf; i++) buf[i]=0;
-	if ((id=open(argv[1],O_RDONLY,0))<0)
-		die("Unable to open 'boot'");
-	if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
-		die("Unable to read header of 'boot'");
-	if (((long *) buf)[0]!=intel_long(0x04100301))
-		die("Non-Minix header of 'boot'");
-	if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
-		die("Non-Minix header of 'boot'");
-	if (((long *) buf)[3] != 0)
-		die("Illegal data segment in 'boot'");
-	if (((long *) buf)[4] != 0)
-		die("Illegal bss in 'boot'");
-	if (((long *) buf)[5] != 0)
-		die("Non-Minix header of 'boot'");
-	if (((long *) buf)[7] != 0)
-		die("Illegal symbol table in 'boot'");
-	i=read(id,buf,sizeof buf);
-	fprintf(stderr,"Boot sector %d bytes.\n",i);
-	if (i != 512)
-		die("Boot block must be exactly 512 bytes");
-	if ((*(unsigned short *)(buf+510)) != (unsigned short)intel_short(0xAA55))
-		die("Boot block hasn't got boot flag (0xAA55)");
-	buf[508] = (char) minor_root;
-	buf[509] = (char) major_root;	
-	i=write(1,buf,512);
-	if (i!=512)
-		die("Write call failed");
-	close (id);
-	
-	if ((id=open(argv[2],O_RDONLY,0))<0)
-		die("Unable to open 'setup'");
-	if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
-		die("Unable to read header of 'setup'");
-	if (((long *) buf)[0]!=intel_long(0x04100301))
-		die("Non-Minix header of 'setup'");
-	if (((long *) buf)[1]!=intel_long(MINIX_HEADER))
-		die("Non-Minix header of 'setup'");
-	if (((long *) buf)[3] != 0)
-		die("Illegal data segment in 'setup'");
-	if (((long *) buf)[4] != 0)
-		die("Illegal bss in 'setup'");
-	if (((long *) buf)[5] != 0)
-		die("Non-Minix header of 'setup'");
-	if (((long *) buf)[7] != 0)
-		die("Illegal symbol table in 'setup'");
-	for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
-		if (write(1,buf,c)!=c)
-			die("Write call failed");
-	if (c != 0)
-		die("read-error on 'setup'");
-	close (id);
-	setup_sectors = (unsigned char)((i + 511) / 512);
-	/* for compatibility with LILO */
-	if (setup_sectors < SETUP_SECTS)
-		setup_sectors = SETUP_SECTS;
-	fprintf(stderr,"Setup is %d bytes.\n",i);
-	for (c=0 ; c<sizeof(buf) ; c++)
-		buf[c] = '\0';
-	while (i < setup_sectors * 512) {
-		c = setup_sectors * 512 - i;
-		if (c > sizeof(buf))
-			c = sizeof(buf);
-		if (write(1,buf,c) != c)
-			die("Write call failed");
-		i += c;
-	}
-	
-	if ((id=open(argv[3],O_RDONLY,0))<0)
-		die("Unable to open 'system'");
-	if (read(id,buf,GCC_HEADER) != GCC_HEADER)
-		die("Unable to read header of 'system'");
-	if (N_MAGIC(*ex) == ZMAGIC) {
-		GCC_HEADER = N_MAGIC_OFFSET;
-		lseek(id, GCC_HEADER, SEEK_SET);
-	} else if (N_MAGIC(*ex) != QMAGIC)
-		die("Non-GCC header of 'system'");
-	fprintf(stderr,"System is %d kB (%d kB code, %d kB data and %d kB bss)\n",
-		(ex->a_text+ex->a_data+ex->a_bss)/1024,
-		ex->a_text /1024,
-		ex->a_data /1024,
-		ex->a_bss  /1024);
-	sz = N_SYMOFF(*ex) - GCC_HEADER + 4;
-	sys_size = (sz + 15) / 16;
-	if (sys_size > SYS_SIZE)
-		die("System is too big");
-	while (sz > 0) {
-		int l, n;
-
-		l = sz;
-		if (l > sizeof(buf))
-			l = sizeof(buf);
-		if ((n=read(id, buf, l)) != l) {
-			if (n == -1) 
-				perror(argv[1]);
-			else
-				fprintf(stderr, "Unexpected EOF\n");
-			die("Can't read 'system'");
-		}
-		if (write(1, buf, l) != l)
-			die("Write failed");
-		sz -= l;
-	}
-	close(id);
-	if (lseek(1, 497, 0) == 497) {
-		if (write(1, &setup_sectors, 1) != 1)
-			die("Write of setup sectors failed");
-	}
-	if (lseek(1,500,0) == 500) {
-		buf[0] = (sys_size & 0xff);
-		buf[1] = ((sys_size >> 8) & 0xff);
-		if (write(1, buf, 2) != 2)
-			die("Write failed");
-	}
-	return(0);
-}
diff -u --recursive --new-file v1.1.75/linux/tools/version.c linux/tools/version.c
--- v1.1.75/linux/tools/version.c	Tue Dec  6 17:37:07 1994
+++ linux/tools/version.c	Thu Jan  1 02:00:00 1970
@@ -1,20 +0,0 @@
-/*
- *  linux/version.c
- *
- *  Copyright (C) 1992  Theodore Ts'o
- *
- *  May be freely distributed as part of Linux.
- */
-
-#include <linux/config.h>
-#include <linux/utsname.h>
-#include <linux/version.h>
-
-struct new_utsname system_utsname = {
-	UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION,
-	UTS_MACHINE, UTS_DOMAINNAME
-};
-
-char *linux_banner = 
-	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
-	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
diff -u --recursive --new-file v1.1.75/linux/zBoot/Makefile linux/zBoot/Makefile
--- v1.1.75/linux/zBoot/Makefile	Wed Aug 10 21:41:41 1994
+++ linux/zBoot/Makefile	Thu Jan  1 02:00:00 1970
@@ -1,32 +0,0 @@
-
-HEAD = head.o
-SYSTEM = ../tools/zSystem
-#LD = gcc
-#TEST = -DTEST_DRIVER
-
-zOBJECTS = $(HEAD) inflate.o unzip.o misc.o
-
-CFLAGS = -O2 -DSTDC_HEADERS $(TEST)
-
-.c.s:
-	$(CC) $(CFLAGS) -S $<
-.s.o:
-	$(AS) -o $*.o $<
-.c.o:
-	$(CC) $(CFLAGS) -c $<
-
-all:	zSystem
-
-zSystem:	piggy.o $(zOBJECTS)
-		$(LD) $(LOWLDFLAGS) -o zSystem $(zOBJECTS) piggy.o
-
-head.o:	head.s
-
-head.s: head.S ../include/linux/tasks.h
-	$(CPP) -traditional head.S -o head.s
-
-piggy.o:	$(SYSTEM) xtract piggyback
-		./xtract $(SYSTEM) | gzip -9 | ./piggyback > piggy.o
-
-$(SYSTEM):
-		$(MAKE) -C .. tools/zSystem
diff -u --recursive --new-file v1.1.75/linux/zBoot/crypt.h linux/zBoot/crypt.h
--- v1.1.75/linux/zBoot/crypt.h	Tue Aug  9 09:35:23 1994
+++ linux/zBoot/crypt.h	Thu Jan  1 02:00:00 1970
@@ -1,12 +0,0 @@
-/* crypt.h (dummy version) -- do not perform encryption
- * Hardly worth copyrighting :-)
- */
-
-#ifdef CRYPT
-#  undef CRYPT      /* dummy version */
-#endif
-
-#define RAND_HEAD_LEN  12  /* length of encryption random header */
-
-#define zencode
-#define zdecode
diff -u --recursive --new-file v1.1.75/linux/zBoot/gzip.h linux/zBoot/gzip.h
--- v1.1.75/linux/zBoot/gzip.h	Wed Dec  1 14:44:15 1993
+++ linux/zBoot/gzip.h	Thu Jan  1 02:00:00 1970
@@ -1,284 +0,0 @@
-/* gzip.h -- common declarations for all gzip modules
- * Copyright (C) 1992-1993 Jean-loup Gailly.
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- */
-
-#if defined(__STDC__) || defined(PROTO)
-#  define OF(args)  args
-#else
-#  define OF(args)  ()
-#endif
-
-#ifdef __STDC__
-   typedef void *voidp;
-#else
-   typedef char *voidp;
-#endif
-
-/* I don't like nested includes, but the string functions are used too often */
-#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
-#  include <string.h>
-#  define memzero(s, n)     memset ((s), 0, (n))
-#else
-#  include <strings.h>
-#  define strchr            index 
-#  define strrchr           rindex
-#  define memcpy(d, s, n)   bcopy((s), (d), (n)) 
-#  define memcmp(s1, s2, n) bcmp((s1), (s2), (n)) 
-#  define memzero(s, n)     bzero((s), (n))
-#endif
-
-#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
-#  include <memory.h>
-#endif
-
-#ifndef RETSIGTYPE
-#  define RETSIGTYPE void
-#endif
-
-#define local static
-
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-/* Return codes from gzip */
-#define OK      0
-#define ERROR   1
-#define WARNING 2
-
-/* Compression methods (see algorithm.doc) */
-#define STORED     0
-#define COMPRESSED 1
-#define PACKED     2
-/* methods 3 to 7 reserved */
-#define DEFLATED   8
-extern int method;         /* compression method */
-
-/* To save memory for 16 bit systems, some arrays are overlayed between
- * the various modules:
- * deflate:  prev+head   window      d_buf  l_buf  outbuf
- * unlzw:    tab_prefix  tab_suffix  stack  inbuf  outbuf
- * inflate:              window             inbuf
- * unpack:               window             inbuf
- * For compression, input is done in window[]. For decompression, output
- * is done in window except for unlzw.
- */
-
-#ifndef	INBUFSIZ
-#  define INBUFSIZ  0x8000  /* input buffer size */
-#endif
-#define INBUF_EXTRA  64     /* required by unlzw() */
-
-#ifndef	OUTBUFSIZ
-#  define OUTBUFSIZ  16384  /* output buffer size */
-#endif
-#define OUTBUF_EXTRA 2048   /* required by unlzw() */
-
-#define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
-
-#ifdef DYN_ALLOC
-#  define EXTERN(type, array)  extern type * near array
-#  define DECLARE(type, array, size)  type * near array
-#  define ALLOC(type, array, size) { \
-      array = (type*)fcalloc((unsigned)(((size)+1L)/2), 2*sizeof(type)); \
-      if (array == NULL) error("insufficient memory"); \
-   }
-#  define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
-#else
-#  define EXTERN(type, array)  extern type array[]
-#  define DECLARE(type, array, size)  type array[size]
-#  define ALLOC(type, array, size)
-#  define FREE(array)
-#endif
-
-EXTERN(uch, inbuf);          /* input buffer */
-EXTERN(uch, outbuf);         /* output buffer */
-EXTERN(ush, d_buf);          /* buffer for distances, see trees.c */
-EXTERN(uch, window);         /* Sliding window and suffix table (unlzw) */
-#define tab_suffix window
-#ifndef MAXSEG_64K
-#  define tab_prefix prev    /* hash link (see deflate.c) */
-#  define head (prev+WSIZE)  /* hash head (see deflate.c) */
-   EXTERN(ush, tab_prefix);  /* prefix code (see unlzw.c) */
-#else
-#  define tab_prefix0 prev
-#  define head tab_prefix1
-   EXTERN(ush, tab_prefix0); /* prefix for even codes */
-   EXTERN(ush, tab_prefix1); /* prefix for odd  codes */
-#endif
-
-extern unsigned insize; /* valid bytes in inbuf */
-extern unsigned inptr;  /* index of next byte to be processed in inbuf */
-extern unsigned outcnt; /* bytes in output buffer */
-
-extern long bytes_in;   /* number of input bytes */
-extern long bytes_out;  /* number of output bytes */
-extern long overhead;   /* number of bytes in gzip header */
-
-#define isize bytes_in
-/* for compatibility with old zip sources (to be cleaned) */
-
-extern int  ifd;        /* input file descriptor */
-extern int  ofd;        /* output file descriptor */
-extern char ifname[];   /* input filename or "stdin" */
-extern char ofname[];   /* output filename or "stdout" */
-
-extern ulg time_stamp;  /* original time stamp (modification time) */
-extern long ifile_size; /* input file size, -1 for devices (debug only) */
-
-extern int exit_code;   /* program exit code */
-
-typedef int file_t;     /* Do not use stdio */
-#define NO_FILE  (-1)   /* in memory compression */
-
-
-#define	GZIP_MAGIC     "\037\213" /* Magic header for gzip files, 1F 8B */
-#define	OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
-#define	PKZIP_MAGIC  "PK\003\004" /* Magic header for pkzip files */
-#define	PACK_MAGIC     "\037\036" /* Magic header for packed files */
-
-/* gzip flag byte */
-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-#define COMMENT      0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
-#define RESERVED     0xC0 /* bit 6,7:   reserved */
-
-/* internal file attribute */
-#define UNKNOWN (-1)
-#define BINARY  0
-#define ASCII   1
-
-#ifndef WSIZE
-#  define WSIZE 0x8000     /* window size--must be a power of two, and */
-#endif                     /*  at least 32K for zip's deflate method */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
-#define MAX_DIST  (WSIZE-MIN_LOOKAHEAD)
-/* In order to simplify the code, particularly on 16 bit machines, match
- * distances are limited to MAX_DIST instead of WSIZE.
- */
-
-extern int decrypt;        /* flag to turn on decryption */
-extern int save_orig_name; /* set if original name must be saved */
-extern int verbose;        /* be verbose (-v) */
-extern int level;          /* compression level */
-extern int test;           /* check .z file integrity */
-extern int to_stdout;      /* output to stdout (-c) */
-
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* put_byte is used for the compressed output, put_char for the
- * uncompressed output. However unlzw() uses window for its
- * suffix table instead of its output buffer, so it does not use put_char.
- * (to be cleaned up).
- */
-#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
-   flush_outbuf();}
-#define put_char(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\
-   flush_window();}
-
-/* Output a 16 bit value, lsb first */
-#define put_short(w) \
-{ if (outcnt < OUTBUFSIZ-2) { \
-    outbuf[outcnt++] = (uch) ((w) & 0xff); \
-    outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
-  } else { \
-    put_byte((uch)((w) & 0xff)); \
-    put_byte((uch)((ush)(w) >> 8)); \
-  } \
-}
-
-/* Output a 32 bit value to the bit stream, lsb first */
-#define put_long(n) { \
-    put_short((n) & 0xffff); \
-    put_short(((ulg)(n)) >> 16); \
-}
-
-#define seekable()    0  /* force sequential output */
-#define translate_eol 0  /* no option -a yet */
-
-#define tolow(c)  (isupper(c) ? (c)-'A'+'a' : (c))    /* force to lower case */
-
-/* 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))
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-	/* in zip.c: */
-extern void zip    OF((int in, int out));
-extern int file_read  OF((char *buf,  unsigned size));
-
-	/* in unzip.c */
-extern void unzip        OF((int in, int out));
-extern int check_zipfile OF((int in));
-
-	/* in unpack.c */
-extern void unpack        OF((int in, int out));
-
-	/* in gzip.c */
-RETSIGTYPE abort_gzip   OF((void));
-
-        /* in deflate.c */
-void lm_init OF((int pack_level, ush *flags));
-ulg  deflate OF((void));
-
-        /* in trees.c */
-void ct_init     OF((ush *attr, int *method));
-int  ct_tally    OF((int dist, int lc));
-ulg  flush_block OF((char *buf, ulg stored_len, int eof));
-
-        /* in bits.c */
-void     bi_init    OF((file_t zipfile));
-void     send_bits  OF((int value, int length));
-unsigned bi_reverse OF((unsigned value, int length));
-void     bi_windup  OF((void));
-void     copy_block OF((char *buf, unsigned len, int header));
-extern   int (*read_buf) OF((char *buf, unsigned size));
-
-	/* in util.c: */
-extern ulg  updcrc        OF((uch *s, unsigned n));
-extern void clear_bufs    OF((void));
-extern int  fill_inbuf    OF((void));
-extern void flush_outbuf  OF((void));
-extern void flush_window  OF((void));
-extern char *strlwr       OF((char *s));
-extern char *basename     OF((char *fname));
-extern char *add_envopt   OF((int *argcp, char ***argvp, char *env));
-extern void error         OF((char *m));
-extern void warn          OF((char *a, char *b));
-extern void read_error    OF((void));
-extern void write_error   OF((void));
-extern void display_ratio OF((long num, long den));
-extern voidp xmalloc      OF((unsigned int size));
-
-	/* in inflate.c */
-extern int inflate OF((void));
diff -u --recursive --new-file v1.1.75/linux/zBoot/head.S linux/zBoot/head.S
--- v1.1.75/linux/zBoot/head.S	Mon Nov 28 14:21:47 1994
+++ linux/zBoot/head.S	Thu Jan  1 02:00:00 1970
@@ -1,59 +0,0 @@
-/*
- *  linux/boot/head.S
- *
- *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
- */
-
-/*
- *  head.S contains the 32-bit startup code.
- *
- * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
- * the page directory will exist. The startup code will be overwritten by
- * the page directory.
- *
- * Page 0 is deliberately kept safe, since System Management Mode code in 
- * laptops may need to access the BIOS data stored there.  This is also
- * useful for future device drivers that either access the BIOS via VM86 
- * mode.
- */
-.text
-
-#define __ASSEMBLY__
-#include <asm/segment.h>
-
-startup_32:
-	cld
-	cli
-	movl $(KERNEL_DS),%eax
-	mov %ax,%ds
-	mov %ax,%es
-	mov %ax,%fs
-	mov %ax,%gs
-	lss _stack_start,%esp
-	xorl %eax,%eax
-1:	incl %eax		# check that A20 really IS enabled
-	movl %eax,0x000000	# loop forever if it isn't
-	cmpl %eax,0x100000
-	je 1b
-/*
- * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
- * confuse the debugger if this code is traced.
- * XXX - best to initialize before switching to protected mode.
- */
-	pushl $0
-	popfl
-/*
- * Clear BSS
- */
-	xorl %eax,%eax
-	movl $__edata,%edi
-	movl $__end,%ecx
-	subl %edi,%ecx
-	cld
-	rep
-	stosb
-/*
- * Do the decompression, and jump to the new kernel..
- */
-	call _decompress_kernel
-	ljmp $(KERNEL_CS), $0x100000
diff -u --recursive --new-file v1.1.75/linux/zBoot/inflate.c linux/zBoot/inflate.c
--- v1.1.75/linux/zBoot/inflate.c	Fri May 27 10:47:29 1994
+++ linux/zBoot/inflate.c	Thu Jan  1 02:00:00 1970
@@ -1,810 +0,0 @@
-#define DEBG(x)
-#define DEBG1(x)
-/* inflate.c -- Not copyrighted 1992 by Mark Adler
-   version c10p1, 10 January 1993 */
-
-/* 
- * Adapted for booting Linux by Hannu Savolainen 1993
- * based on gzip-1.0.3 
- */
-
-#ifndef lint
-static char rcsid[] = "$Id: inflate.c,v 0.10 1993/02/04 13:21:06 jloup Exp $";
-#endif
-
-#include "gzip.h"
-#define slide window
-
-#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
-#  include <sys/types.h>
-#  include <stdlib.h>
-#endif
-
-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;
-};
-
-
-/* Function prototypes */
-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));
-
-
-#define wp outcnt
-#define flush_output(w) (wp=(w),flush_window())
-
-/* 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};
-
-
-ulg bb;                         /* bit buffer */
-unsigned bk;                    /* bits in bit buffer */
-
-ush mask_bits[] = {
-    0x0000,
-    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
-    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-#ifdef CRYPT
-  uch cc;
-#  define NEXTBYTE() \
-     (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
-#else
-#  define NEXTBYTE()  (uch)get_byte()
-#endif
-#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
-#define DUMPBITS(n) {b>>=(n);k-=(n);}
-
-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 */
-
-
-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. */
-{
-  unsigned a;                   /* counter for codes of length k */
-  unsigned c[BMAX+1];           /* bit length count table */
-  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 l;                        /* bits per table (returned in m) */
-  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 */
-  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 */
-
-DEBG("huft1 ");
-
-  /* Generate counts for each bit length */
-  memzero(c, sizeof(c));
-  p = b;  i = n;
-  do {
-    c[*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;
-  }
-
-DEBG("huft2 ");
-
-  /* Find minimum and maximum length, bound *m by those */
-  l = *m;
-  for (j = 1; j <= BMAX; j++)
-    if (c[j])
-      break;
-  k = j;                        /* minimum code length */
-  if ((unsigned)l < j)
-    l = j;
-  for (i = BMAX; i; i--)
-    if (c[i])
-      break;
-  g = i;                        /* maximum code length */
-  if ((unsigned)l > i)
-    l = i;
-  *m = l;
-
-DEBG("huft3 ");
-
-  /* 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;
-
-DEBG("huft4 ");
-
-  /* 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++);
-  }
-
-DEBG("huft5 ");
-
-  /* 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);
-
-DEBG("h6 ");
-
-  /* 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;                       /* bits decoded == (l * h) */
-  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
-  q = (struct huft *)NULL;      /* ditto */
-  z = 0;                        /* ditto */
-DEBG("h6a ");
-
-  /* go through the bit lengths (k already is bits in shortest code) */
-  for (; k <= g; k++)
-  {
-DEBG("h6b ");
-    a = c[k];
-    while (a--)
-    {
-DEBG("h6b1 ");
-      /* here i is the Huffman code of length k bits for value *p */
-      /* make tables up to required level */
-      while (k > w + l)
-      {
-DEBG1("1 ");
-        h++;
-        w += l;                 /* previous table always l bits */
-
-        /* compute minimum size table less than or equal to l bits */
-        z = (z = g - w) > (unsigned)l ? l : z;  /* upper limit on table size */
-        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
-        {                       /* too few codes for k-w bit table */
-DEBG1("2 ");
-          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 */
-          }
-        }
-DEBG1("3 ");
-        z = 1 << j;             /* table entries for j-bit table */
-
-        /* allocate and link in new table */
-        q = (struct huft *)malloc((z + 1)*sizeof(struct huft));
-DEBG1("4 ");
-        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 */
-
-DEBG1("5 ");
-        /* connect to last table, if there is one */
-        if (h)
-        {
-          x[h] = i;             /* save pattern for backing up */
-          r.b = (uch)l;         /* 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 >> (w - l);     /* (get around Turbo C bug) */
-          u[h-1][j] = r;        /* connect to last table */
-        }
-DEBG1("6 ");
-      }
-DEBG("h6c ");
-
-      /* 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];
-      }
-DEBG("h6d ");
-
-      /* 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])
-      {
-        h--;                    /* don't need to update q */
-        w -= l;
-      }
-DEBG("h6e ");
-    }
-DEBG("h6f ");
-  }
-
-DEBG("huft7 ");
-
-  /* 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(p);
-    p = q;
-  } 
-  return 0;
-}
-
-
-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_bits[bl];           /* precompute masks for speed */
-  md = mask_bits[bd];
-  for (;;)                      /* 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_bits[e]))->e) > 16);
-    DUMPBITS(t->b)
-    if (e == 16)                /* then it's a literal */
-    {
-      slide[w++] = (uch)t->v.n;
-      if (w == WSIZE)
-      {
-        flush_output(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_bits[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_bits[e]))->e) > 16);
-      DUMPBITS(t->b)
-      NEEDBITS(e)
-      d = w - t->v.n - ((unsigned)b & mask_bits[e]);
-      DUMPBITS(e)
-
-      /* do the copy */
-      do {
-        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
-#if !defined(NOMEMCPY) && !defined(DEBUG)
-        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_output(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;
-}
-
-
-
-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 */
-
-DEBG("<stor");
-
-  /* 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_output(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;
-
-  DEBG(">");
-  return 0;
-}
-
-
-
-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. */
-{
-  int i;                /* temporary variable */
-  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 l[288];      /* length list for huft_build */
-
-DEBG("<fix");
-
-  /* set up 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;
-  bl = 7;
-  if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
-    return i;
-
-
-  /* set up distance table */
-  for (i = 0; i < 30; i++)      /* make an incomplete code set */
-    l[i] = 5;
-  bd = 5;
-  if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
-  {
-    huft_free(tl);
-
-    DEBG(">");
-    return i;
-  }
-
-
-  /* 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_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
-  unsigned ll[288+32];  /* literal/length and distance code lengths */
-#else
-  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 */
-
-DEBG("<dyn");
-
-  /* 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 */
-
-DEBG("dyn1 ");
-
-  /* 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;
-
-DEBG("dyn2 ");
-
-  /* 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 */
-  }
-
-DEBG("dyn3 ");
-
-  /* read in literal and distance code lengths */
-  n = nl + nd;
-  m = mask_bits[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;
-    }
-  }
-
-DEBG("dyn4 ");
-
-  /* free decoding table for trees */
-  huft_free(tl);
-
-DEBG("dyn5 ");
-
-  /* restore the global bit buffer */
-  bb = b;
-  bk = k;
-
-DEBG("dyn5a ");
-
-  /* build the decoding tables for literal/length and distance codes */
-  bl = lbits;
-  if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
-  {
-DEBG("dyn5b ");
-    if (i == 1) {
-      error(" incomplete literal tree\n");
-      huft_free(tl);
-    }
-    return i;                   /* incomplete code set */
-  }
-DEBG("dyn5c ");
-  bd = dbits;
-  if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
-  {
-DEBG("dyn5d ");
-    if (i == 1) {
-      error(" incomplete distance tree\n");
-#ifdef PKZIP_BUG_WORKAROUND
-      i = 0;
-    }
-#else
-      huft_free(td);
-    }
-    huft_free(tl);
-    return i;                   /* incomplete code set */
-#endif
-  }
-
-DEBG("dyn6 ");
-
-  /* decompress until an end-of-block code */
-  if (inflate_codes(tl, td, bl, bd))
-    return 1;
-
-DEBG("dyn7 ");
-
-  /* free the decoding tables, return */
-  huft_free(tl);
-  huft_free(td);
-
-  DEBG(">");
-  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 */
-
-  DEBG("<blk");
-
-  /* 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();
-
-  DEBG(">");
-
-  /* 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);
-
-  /* Undo too much lookahead. The next read will be byte aligned so we
-   * can discard unused bits in the last meaningful byte.
-   */
-  while (bk >= 8) {
-    bk -= 8;
-    inptr--;
-  }
-
-  /* flush out slide */
-  flush_output(wp);
-
-
-  /* return success */
-#ifdef DEBUG
-  fprintf(stderr, "<%u> ", h);
-#endif /* DEBUG */
-  return 0;
-}
diff -u --recursive --new-file v1.1.75/linux/zBoot/lzw.h linux/zBoot/lzw.h
--- v1.1.75/linux/zBoot/lzw.h	Tue Aug  9 09:35:23 1994
+++ linux/zBoot/lzw.h	Thu Jan  1 02:00:00 1970
@@ -1,42 +0,0 @@
-/* lzw.h -- define the lzw functions.
- * Copyright (C) 1992-1993 Jean-loup Gailly.
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- */
-
-#if !defined(OF) && defined(lint)
-#  include "gzip.h"
-#endif
-
-#ifndef BITS
-#  define BITS 16
-#endif
-#define INIT_BITS 9              /* Initial number of bits per code */
-
-#define	LZW_MAGIC  "\037\235"   /* Magic header for lzw files, 1F 9D */
-
-#define BIT_MASK    0x1f /* Mask for 'number of compression bits' */
-/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
- * It's a pity that old uncompress does not check bit 0x20. That makes
- * extension of the format actually undesirable because old compress
- * would just crash on the new format instead of giving a meaningful
- * error message. It does check the number of bits, but it's more
- * helpful to say "unsupported format, get a new version" than
- * "can only handle 16 bits".
- */
-
-#define BLOCK_MODE  0x80
-/* Block compression: if table is full and compression rate is dropping,
- * clear the dictionary.
- */
-
-#define LZW_RESERVED 0x60 /* reserved bits */
-
-#define	CLEAR  256       /* flush the dictionary */
-#define FIRST  (CLEAR+1) /* first free entry */
-
-extern int maxbits;      /* max bits per code for LZW */
-extern int block_mode;   /* block compress mode -C compatible with 2.0 */
-
-extern void lzw    OF((int in, int out));
-extern void unlzw  OF((int in, int out));
diff -u --recursive --new-file v1.1.75/linux/zBoot/misc.c linux/zBoot/misc.c
--- v1.1.75/linux/zBoot/misc.c	Mon Nov 28 14:21:47 1994
+++ linux/zBoot/misc.c	Thu Jan  1 02:00:00 1970
@@ -1,418 +0,0 @@
-/*
- * misc.c
- * 
- * This is a collection of several routines from gzip-1.0.3 
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- * puts by Nick Holloway 1993
- */
-
-#include "gzip.h"
-#include "lzw.h"
-
-#include <asm/segment.h>
-
-/*
- * These are set up by the setup-routine at boot-time:
- */
-
-struct screen_info {
-	unsigned char  orig_x;
-	unsigned char  orig_y;
-	unsigned char  unused1[2];
-	unsigned short orig_video_page;
-	unsigned char  orig_video_mode;
-	unsigned char  orig_video_cols;
-	unsigned short orig_video_ega_ax;
-	unsigned short orig_video_ega_bx;
-	unsigned short orig_video_ega_cx;
-	unsigned char  orig_video_lines;
-};
-
-/*
- * This is set up by the setup-routine at boot-time
- */
-#define EXT_MEM_K (*(unsigned short *)0x90002)
-#define DRIVE_INFO (*(struct drive_info *)0x90080)
-#define SCREEN_INFO (*(struct screen_info *)0x90000)
-#define RAMDISK_SIZE (*(unsigned short *)0x901F8)
-#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
-#define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
-
-#define EOF -1
-
-DECLARE(uch, inbuf, INBUFSIZ);
-DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
-DECLARE(uch, window, WSIZE);
-
-unsigned outcnt;
-unsigned insize;
-unsigned inptr;
-
-extern char input_data[];
-extern int input_len;
-
-int input_ptr;
-
-int method, exit_code, part_nb, last_member;
-int test = 0;
-int force = 0;
-int verbose = 1;
-long bytes_in, bytes_out;
-
-char *output_data;
-unsigned long output_ptr;
-
-extern int end;
-long free_mem_ptr = (long)&end;
-
-int to_stdout = 0;
-int hard_math = 0;
-
-void (*work)(int inf, int outf);
-void makecrc(void);
-
-local int get_method(int);
-
-char *vidmem = (char *)0xb8000;
-int lines, cols;
-
-static void puts(const char *);
-
-void *malloc(int size)
-{
-	void *p;
-
-	if (size <0) error("Malloc error\n");
-	if (free_mem_ptr <= 0) error("Memory error\n");
-
-   while(1) {
-	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
-
-	p = (void *)free_mem_ptr;
-	free_mem_ptr += size;
-
-	/*
-  	 * The part of the compressed kernel which has already been expanded
-	 * is no longer needed. Therefore we can reuse it for malloc.
-	 * With bigger kernels, this is necessary.
-	 */
-          
-	if (free_mem_ptr < (long)&end) {
-		if (free_mem_ptr > (long)&input_data[input_ptr])
-			error("\nOut of memory\n");
-
-		return p;
-	}
-	if (free_mem_ptr < 0x90000)
-	return p;
-	puts("memory is tight...");
-	free_mem_ptr = (long)input_data;
-	}
-}
-
-void free(void *where)
-{	/* Don't care */
-}
-
-static void scroll()
-{
-	int i;
-
-	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
-	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
-		vidmem[i] = ' ';
-}
-
-static void puts(const char *s)
-{
-	int x,y;
-	char c;
-
-	x = SCREEN_INFO.orig_x;
-	y = SCREEN_INFO.orig_y;
-
-	while ( ( c = *s++ ) != '\0' ) {
-		if ( c == '\n' ) {
-			x = 0;
-			if ( ++y >= lines ) {
-				scroll();
-				y--;
-			}
-		} else {
-			vidmem [ ( x + cols * y ) * 2 ] = c; 
-			if ( ++x >= cols ) {
-				x = 0;
-				if ( ++y >= lines ) {
-					scroll();
-					y--;
-				}
-			}
-		}
-	}
-
-	SCREEN_INFO.orig_x = x;
-	SCREEN_INFO.orig_y = y;
-}
-
-__ptr_t memset(__ptr_t s, int c, size_t n)
-{
-	int i;
-	char *ss = (char*)s;
-
-	for (i=0;i<n;i++) ss[i] = c;
-}
-
-__ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
-			    size_t __n)
-{
-	int i;
-	char *d = (char *)__dest, *s = (char *)__src;
-
-	for (i=0;i<__n;i++) d[i] = s[i];
-}
-
-extern ulg crc_32_tab[];   /* crc table, defined below */
-
-/* ===========================================================================
- * 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.
- */
-ulg updcrc(s, n)
-    uch *s;                 /* pointer to bytes to pump through */
-    unsigned n;             /* number of bytes in s[] */
-{
-    register ulg c;         /* temporary variable */
-
-    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
-
-    if (s == 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) */
-}
-
-/* ===========================================================================
- * Clear input and output buffers
- */
-void clear_bufs()
-{
-    outcnt = 0;
-    insize = inptr = 0;
-    bytes_in = bytes_out = 0L;
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-int fill_inbuf()
-{
-    int len, i;
-
-    /* Read as much as possible */
-    insize = 0;
-    do {
-	len = INBUFSIZ-insize;
-	if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1;
-        if (len == 0 || len == EOF) break;
-
-        for (i=0;i<len;i++) inbuf[insize+i] = input_data[input_ptr+i];
-	insize += len;
-	input_ptr += len;
-    } while (insize < INBUFSIZ);
-
-    if (insize == 0) {
-	error("unable to fill buffer\n");
-    }
-    bytes_in += (ulg)insize;
-    inptr = 1;
-    return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-void flush_window()
-{
-    if (outcnt == 0) return;
-    updcrc(window, outcnt);
-
-    memcpy(&output_data[output_ptr], (char *)window, outcnt);
-
-    bytes_out += (ulg)outcnt;
-    output_ptr += (ulg)outcnt;
-    outcnt = 0;
-}
-
-/*
- * Code to compute the CRC-32 table. Borrowed from 
- * gzip-1.0.3/makecrc.c.
- */
-
-ulg crc_32_tab[256];
-
-void
-makecrc(void)
-{
-/* Not copyrighted 1990 Mark Adler	*/
-
-  unsigned long c;      /* crc shift register */
-  unsigned long e;      /* polynomial exclusive-or pattern */
-  int i;                /* counter for all possible eight bit values */
-  int k;                /* byte being shifted into crc apparatus */
-
-  /* terms of polynomial defining this crc (except x^32): */
-  static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
-  /* Make exclusive-or pattern from polynomial */
-  e = 0;
-  for (i = 0; i < sizeof(p)/sizeof(int); i++)
-    e |= 1L << (31 - p[i]);
-
-  crc_32_tab[0] = 0;
-
-  for (i = 1; i < 256; i++)
-  {
-    c = 0;
-    for (k = i | 256; k != 1; k >>= 1)
-    {
-      c = c & 1 ? (c >> 1) ^ e : c >> 1;
-      if (k & 1)
-        c ^= e;
-    }
-    crc_32_tab[i] = c;
-  }
-}
-
-void error(char *x)
-{
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
-
-	while(1);	/* Halt */
-}
-
-#define STACK_SIZE (4096)
-
-long user_stack [STACK_SIZE];
-
-struct {
-	long * a;
-	short b;
-	} stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS };
-
-void decompress_kernel()
-{
-	if (SCREEN_INFO.orig_video_mode == 7)
-		vidmem = (char *) 0xb0000;
-	else
-		vidmem = (char *) 0xb8000;
-
-	lines = SCREEN_INFO.orig_video_lines;
-	cols = SCREEN_INFO.orig_video_cols;
-
-	if (EXT_MEM_K < 1024) error("<2M of mem\n");
-
-	output_data = (char *)0x100000;	/* Points to 1M */
-	output_ptr = 0;
-
-	exit_code = 0;
-	test = 0;
-	input_ptr = 0;
-	part_nb = 0;
-
-	clear_bufs();
-	makecrc();
-
-	puts("Uncompressing Linux...");
-
-	method = get_method(0);
-
-	work(0, 0);
-
-	puts("done.\n");
-
-	puts("Now booting the kernel\n");
-}
-
-/* ========================================================================
- * Check the magic number of the input file and update ofname if an
- * original name was given and to_stdout is not set.
- * Return the compression method, -1 for error, -2 for warning.
- * Set inptr to the offset of the next byte to be processed.
- * This function may be called repeatedly for an input file consisting
- * of several contiguous gzip'ed members.
- * IN assertions: there is at least one remaining compressed member.
- *   If the member is a zip file, it must be the only one.
- */
-local int get_method(in)
-    int in;        /* input file descriptor */
-{
-    uch flags;
-    char magic[2]; /* magic header */
-
-    magic[0] = (char)get_byte();
-    magic[1] = (char)get_byte();
-
-    method = -1;                 /* unknown yet */
-    part_nb++;                   /* number of parts in gzip file */
-    last_member = 0;
-    /* assume multiple members in gzip file except for record oriented I/O */
-
-    if (memcmp(magic, GZIP_MAGIC, 2) == 0
-        || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
-
-	work = unzip;
-	method = (int)get_byte();
-	flags  = (uch)get_byte();
-	if ((flags & ENCRYPTED) != 0)
-	    error("Input is encrypted\n");
-	if ((flags & CONTINUATION) != 0)
-	       error("Multi part input\n");
-	if ((flags & RESERVED) != 0) {
-	    error("Input has invalid flags\n");
-	    exit_code = ERROR;
-	    if (force <= 1) return -1;
-	}
-	(ulg)get_byte();	/* Get timestamp */
-	((ulg)get_byte()) << 8;
-	((ulg)get_byte()) << 16;
-	((ulg)get_byte()) << 24;
-
-	(void)get_byte();  /* Ignore extra flags for the moment */
-	(void)get_byte();  /* Ignore OS type for the moment */
-
-	if ((flags & EXTRA_FIELD) != 0) {
-	    unsigned len = (unsigned)get_byte();
-	    len |= ((unsigned)get_byte())<<8;
-	    while (len--) (void)get_byte();
-	}
-
-	/* Get original file name if it was truncated */
-	if ((flags & ORIG_NAME) != 0) {
-	    if (to_stdout || part_nb > 1) {
-		/* Discard the old name */
-		while (get_byte() != 0) /* null */ ;
-	    } else {
-	    } /* to_stdout */
-	} /* orig_name */
-
-	/* Discard file comment if any */
-	if ((flags & COMMENT) != 0) {
-	    while (get_byte() != 0) /* null */ ;
-	}
-    } else
-	error("unknown compression method");
-    return method;
-}
diff -u --recursive --new-file v1.1.75/linux/zBoot/piggyback.c linux/zBoot/piggyback.c
--- v1.1.75/linux/zBoot/piggyback.c	Wed Dec  1 14:44:15 1993
+++ linux/zBoot/piggyback.c	Thu Jan  1 02:00:00 1970
@@ -1,81 +0,0 @@
-/*
- *	linux/zBoot/piggyback.c
- *
- *	(C) 1993 Hannu Savolainen
- */
-
-/*
- *	This program reads the compressed system image from stdin and
- *	encapsulates it into an object file written to the stdout.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <a.out.h>
-
-int main(int argc, char *argv[])
-{
-	int c, n=0, len=0;
-	char tmp_buf[512*1024];
-	
-	struct exec obj = {0x00640107};	/* object header */
-	char string_names[] = {"_input_data\0_input_len\0"};
-
-	struct nlist var_names[2] = /* Symbol table */
-		{	
-			{	/* _input_data	*/
-				(char *)4, 7, 0, 0, 0
-			},
-			{	/* _input_len */
-				(char *)16, 7, 0, 0, 0
-			}
-		};
-
-
-	len = 0;
-	while ((n = read(0, &tmp_buf[len], sizeof(tmp_buf)-len+1)) > 0)
-	      len += n;
-
-	if (n==-1)
-	{
-		perror("stdin");
-		exit(-1);
-	}
-
-	if (len >= sizeof(tmp_buf))
-	{
-		fprintf(stderr, "%s: Input too large\n", argv[0]);
-		exit(-1);
-	}
-
-	fprintf(stderr, "Compressed size %d.\n", len);
-
-/*
- *	Output object header
- */
-	obj.a_data = len + sizeof(long);
-	obj.a_syms = sizeof(var_names);
-	write(1, (char *)&obj, sizeof(obj));
-
-/*
- *	Output data segment (compressed system & len)
- */
-	write(1, tmp_buf, len);
-	write(1, (char *)&len, sizeof(len));
-
-/*
- *	Output symbol table
- */
-	var_names[1].n_value = len;
-	write(1, (char *)&var_names, sizeof(var_names));
-
-/*
- *	Output string table
- */
-	len = sizeof(string_names) + sizeof(len);
-	write(1, (char *)&len, sizeof(len));
-	write(1, string_names, sizeof(string_names));
-
-	exit(0);
-
-}
diff -u --recursive --new-file v1.1.75/linux/zBoot/unzip.c linux/zBoot/unzip.c
--- v1.1.75/linux/zBoot/unzip.c	Wed Dec  1 14:44:15 1993
+++ linux/zBoot/unzip.c	Thu Jan  1 02:00:00 1970
@@ -1,180 +0,0 @@
-/* unzip.c -- decompress files in gzip or pkzip format.
- * Copyright (C) 1992-1993 Jean-loup Gailly
- *
- * Adapted for Linux booting by Hannu Savolainen 1993
- *
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- *
- * The code in this file is derived from the file funzip.c written
- * and put in the public domain by Mark Adler.
- */
-
-/*
-   This version can extract files in gzip or pkzip format.
-   For the latter, only the first entry is extracted, and it has to be
-   either deflated or stored.
- */
-
-#ifndef lint
-static char rcsid[] = "$Id: unzip.c,v 0.9 1993/02/10 16:07:22 jloup Exp $";
-#endif
-
-#include "gzip.h"
-#include "crypt.h"
-
-#include <stdio.h>
-
-/* PKZIP header definitions */
-#define LOCSIG 0x04034b50L      /* four-byte lead-in (lsb first) */
-#define LOCFLG 6                /* offset of bit flag */
-#define  CRPFLG 1               /*  bit for encrypted entry */
-#define  EXTFLG 8               /*  bit for extended local header */
-#define LOCHOW 8                /* offset of compression method */
-#define LOCTIM 10               /* file mod time (for decryption) */
-#define LOCCRC 14               /* offset of crc */
-#define LOCSIZ 18               /* offset of compressed size */
-#define LOCLEN 22               /* offset of uncompressed length */
-#define LOCFIL 26               /* offset of file name field length */
-#define LOCEXT 28               /* offset of extra field length */
-#define LOCHDR 30               /* size of local header, including sig */
-#define EXTHDR 16               /* size of extended local header, inc sig */
-
-
-/* Globals */
-
-int decrypt;      /* flag to turn on decryption */
-char *key;        /* not used--needed to link crypt.c */
-int pkzip = 0;    /* set for a pkzip file */
-int extended = 0; /* set if extended local header */
-
-/* ===========================================================================
- * Check zip file and advance inptr to the start of the compressed data.
- * Get ofname from the local header if necessary.
- */
-int check_zipfile(in)
-    int in;   /* input file descriptors */
-{
-    uch *h = inbuf + inptr; /* first local header */
-
-    /* ifd = in; */
-
-    /* Check validity of local header, and skip name and extra fields */
-    inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
-
-    if (inptr > insize || LG(h) != LOCSIG) {
-	error("input not a zip");
-    }
-    method = h[LOCHOW];
-    if (method != STORED && method != DEFLATED) {
-	error("first entry not deflated or stored--can't extract");
-    }
-
-    /* If entry encrypted, decrypt and validate encryption header */
-    if ((decrypt = h[LOCFLG] & CRPFLG) != 0) {
-	error("encrypted file\n");
-	exit_code = ERROR;
-	return -1;
-    }
-
-    /* Save flags for unzip() */
-    extended = (h[LOCFLG] & EXTFLG) != 0;
-    pkzip = 1;
-
-    /* Get ofname and time stamp from local header (to be done) */
-    return 0;
-}
-
-/* ===========================================================================
- * Unzip in to out.  This routine works on both gzip and pkzip files.
- *
- * IN assertions: the buffer inbuf contains already the beginning of
- *   the compressed data, from offsets inptr to insize-1 included.
- *   The magic header has already been checked. The output buffer is cleared.
- */
-void unzip(in, out)
-    int in, out;   /* input and output file descriptors */
-{
-    ulg orig_crc = 0;       /* original crc */
-    ulg orig_len = 0;       /* original uncompressed length */
-    int n;
-    uch buf[EXTHDR];        /* extended local header */
-
-    /* ifd = in;
-    ofd = out; */
-
-    updcrc(NULL, 0);           /* initialize crc */
-
-    if (pkzip && !extended) {  /* crc and length at the end otherwise */
-	orig_crc = LG(inbuf + LOCCRC);
-	orig_len = LG(inbuf + LOCLEN);
-    }
-
-    /* Decompress */
-    if (method == DEFLATED)  {
-
-	int res = inflate();
-
-	if (res == 3) {
-	    error("out of memory");
-	} else if (res != 0) {
-	    error("invalid compressed format");
-	}
-
-    } else if (pkzip && method == STORED) {
-
-	register ulg n = LG(inbuf + LOCLEN);
-
-	if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) {
-
-	    error("length mismatch");
-	}
-	while (n--) {
-	    uch c = (uch)get_byte();
-#ifdef CRYPT
-	    if (decrypt) zdecode(c);
-#endif
-	    if (!test) put_char(c);
-	}
-    } else {
-	error("internal error, invalid method");
-    }
-
-    /* Get the crc and original length */
-    if (!pkzip) {
-        /* crc32  (see algorithm.doc)
-	 * uncompressed input size modulo 2^32
-         */
-	for (n = 0; n < 8; n++) {
-	    buf[n] = (uch)get_byte(); /* may cause an error if EOF */
-	}
-	orig_crc = LG(buf);
-	orig_len = LG(buf+4);
-
-    } else if (extended) {  /* If extended header, check it */
-	/* signature - 4bytes: 0x50 0x4b 0x07 0x08
-	 * CRC-32 value
-         * compressed size 4-bytes
-         * uncompressed size 4-bytes
-	 */
-	for (n = 0; n < EXTHDR; n++) {
-	    buf[n] = (uch)get_byte(); /* may cause an error if EOF */
-	}
-	orig_crc = LG(buf+4);
-	orig_len = LG(buf+12);
-    }
-
-    /* Validate decompression */
-    if (orig_crc != updcrc(outbuf, 0)) {
-	error("crc error");
-    }
-    if (orig_len != bytes_out) {
-	error("length error");
-    }
-
-    /* Check if there are more entries in a pkzip file */
-    if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
-	    error("zip file has more than one entry");
-    }
-    extended = pkzip = 0; /* for next file */
-}
diff -u --recursive --new-file v1.1.75/linux/zBoot/xtract.c linux/zBoot/xtract.c
--- v1.1.75/linux/zBoot/xtract.c	Fri Jul 22 13:34:18 1994
+++ linux/zBoot/xtract.c	Thu Jan  1 02:00:00 1970
@@ -1,87 +0,0 @@
-/*
- *  linux/zBoot/xtract.c
- *
- *  Copyright (C) 1993  Hannu Savolainen
- *
- *	Extracts the system image and writes it to the stdout.
- *	based on tools/build.c by Linus Torvalds
- */
-
-#include <stdio.h>	/* fprintf */
-#include <string.h>
-#include <stdlib.h>	/* contains exit */
-#include <sys/types.h>	/* unistd.h needs this */
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <unistd.h>	/* contains read/write */
-#include <fcntl.h>
-#include <a.out.h>
-#include <linux/config.h>
-
-#define N_MAGIC_OFFSET 1024
-
-static int GCC_HEADER = sizeof(struct exec);
-
-#define STRINGIFY(x) #x
-
-void die(char * str)
-{
-	fprintf(stderr,"%s\n",str);
-	exit(1);
-}
-
-void usage(void)
-{
-	die("Usage: xtract system [ | gzip | piggyback > piggy.s]");
-}
-
-int main(int argc, char ** argv)
-{
-	int i,c,id, sz;
-	char buf[1024];
-	char major_root, minor_root;
-	struct stat sb;
-
-	struct exec *ex = (struct exec *)buf;
-
-	if (argc  != 2)
-		usage();
-	
-	if ((id=open(argv[1],O_RDONLY,0))<0)
-		die("Unable to open 'system'");
-	if (read(id,buf,GCC_HEADER) != GCC_HEADER)
-		die("Unable to read header of 'system'");
-	if (N_MAGIC(*ex) == ZMAGIC) {
-		GCC_HEADER = N_MAGIC_OFFSET;
-		lseek(id, GCC_HEADER, SEEK_SET);
-	} else if (N_MAGIC(*ex) != QMAGIC)
-		die("Non-GCC header of 'system'");
-
-	sz = N_SYMOFF(*ex) - GCC_HEADER + 4;	/* +4 to get the same result than tools/build */
-
-	fprintf(stderr, "System size is %d\n", sz);
-
-	while (sz)
-	{
-		int l, n;
-
-		l = sz;
-		if (l > sizeof(buf)) l = sizeof(buf);
-
-		if ((n=read(id, buf, l)) !=l)
-		{
-			if (n == -1) 
-			   perror(argv[1]);
-			else
-			   fprintf(stderr, "Unexpected EOF\n");
-
-			die("Can't read system");
-		}
-
-		write(1, buf, l);
-		sz -= l;
-	}
-
-	close(id);
-	return(0);
-}
