diff -u --recursive --new-file v1.3.47/linux/Documentation/filesystems/hpfs.txt linux/Documentation/filesystems/hpfs.txt
--- v1.3.47/linux/Documentation/filesystems/hpfs.txt	Sun Sep  3 12:26:47 1995
+++ linux/Documentation/filesystems/hpfs.txt	Sun Dec 17 11:17:20 1995
@@ -9,10 +9,12 @@
   conv=text     (Carriage return, line feed) is replaced with newline.
   conv=auto     Chooses, file by file, conv=binary or conv=text (by guessing)
 
-There is one mount option unique to HPFS.
+There are mount options unique to HPFS.
 
   case=lower	Convert file names to lower case.  [default]
   case=asis     Return file names as is, in mixed case.
+
+  nocheck	Proceed even if "Improperly stopped flag is set"
 
 Case is not significant in filename matching, like real HPFS.
 
diff -u --recursive --new-file v1.3.47/linux/Makefile linux/Makefile
--- v1.3.47/linux/Makefile	Wed Dec 13 09:02:45 1995
+++ linux/Makefile	Sun Dec 17 10:39:27 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 47
+SUBLEVEL = 48
 
 ARCH = i386
 
@@ -171,11 +171,9 @@
 oldconfig: symlinks
 	$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
 
-xconfig: symlinks scripts/kconfig.tk
-	wish -f scripts/kconfig.tk
-
-scripts/kconfig.tk:
+xconfig: symlinks
 	$(MAKE) -C scripts kconfig.tk
+	wish -f scripts/kconfig.tk
 
 config: symlinks
 	$(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in
diff -u --recursive --new-file v1.3.47/linux/arch/alpha/boot/main.c linux/arch/alpha/boot/main.c
--- v1.3.47/linux/arch/alpha/boot/main.c	Sun Oct 29 11:38:47 1995
+++ linux/arch/alpha/boot/main.c	Fri Dec 15 07:31:29 1995
@@ -229,7 +229,7 @@
 			  envval, sizeof(envval));
 	if (nbytes > 0) {
 		envval[nbytes] = '\0';
-		strcpy((char*)ZERO_PGE, envval);
+		strcpy((char*)ZERO_PAGE, envval);
 	}
 
 	printk(" Ok\nNow booting the kernel\n");
diff -u --recursive --new-file v1.3.47/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v1.3.47/linux/arch/alpha/defconfig	Sat Nov 25 19:04:35 1995
+++ linux/arch/alpha/defconfig	Fri Dec 15 07:31:29 1995
@@ -40,7 +40,7 @@
 #
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDEATAPI is not set
 # CONFIG_BLK_DEV_TRITON is not set
 # CONFIG_BLK_DEV_XD is not set
 
@@ -48,6 +48,7 @@
 # Networking options
 #
 # CONFIG_FIREWALL is not set
+# CONFIG_NET_ALIAS is not set
 CONFIG_INET=y
 # CONFIG_IP_FORWARD is not set
 # CONFIG_IP_MULTICAST is not set
@@ -166,6 +167,7 @@
 # CONFIG_MS_BUSMOUSE is not set
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_QIC02_TAPE is not set
+# CONFIG_APM is not set
 
 #
 # Sound
diff -u --recursive --new-file v1.3.47/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v1.3.47/linux/arch/alpha/kernel/bios32.c	Wed Nov  8 07:11:29 1995
+++ linux/arch/alpha/kernel/bios32.c	Sun Dec 17 11:17:19 1995
@@ -427,6 +427,14 @@
 		pcibios_write_config_byte(dev->bus->number, dev->devfn,
 					  PCI_INTERRUPT_LINE, dev->irq);
 #endif
+		/*
+		 * if its a VGA, enable its BIOS ROM at C0000
+		 */
+		if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
+			pcibios_write_config_dword(dev->bus->number, dev->devfn,
+						   PCI_ROM_ADDRESS,
+						   0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
+		}
 	}
 	if (ide_base) {
 		enable_ide(ide_base);
@@ -612,6 +620,14 @@
 		if (pirq < 0) {
 			continue;
 		}
+		/*
+		 * if its a VGA, enable its BIOS ROM at C0000
+		 */
+		if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
+			pcibios_write_config_dword(dev->bus->number, dev->devfn,
+						   PCI_ROM_ADDRESS,
+						   0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
+		}
 		if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
 			continue; /* for now, displays get no IRQ */
 		}
@@ -620,7 +636,6 @@
 		/* must set the PCI IRQs to level triggered */
 		/* assume they are all >= 8 */
 		level_bits |= (1 << (dev->irq - 8));
-		outb(level_bits, 0x4d1);
 
 #if PCI_MODIFY
 		/* tell the device: */
@@ -628,6 +643,10 @@
 					  PCI_INTERRUPT_LINE, dev->irq);
 #endif
 	}
+	/* now, set any level-triggered IRQs */
+	if (level_bits)
+		outb(level_bits, 0x4d1);
+
 
 #if PCI_MODIFY
 	{
diff -u --recursive --new-file v1.3.47/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v1.3.47/linux/arch/alpha/kernel/setup.c	Mon Nov 13 12:36:42 1995
+++ linux/arch/alpha/kernel/setup.c	Fri Dec 15 07:31:30 1995
@@ -24,6 +24,7 @@
 #include <linux/config.h>	/* CONFIG_ALPHA_LCA etc */
 
 #include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/hwrpb.h>
 #include <asm/dma.h>
@@ -44,7 +45,7 @@
  * initialized, we need to copy things out into a more permanent
  * place.
  */
-#define PARAM			ZERO_PGE
+#define PARAM			ZERO_PAGE
 #define COMMAND_LINE		((char*)(PARAM + 0x0000))
 #define COMMAND_LINE_SIZE	256
 
diff -u --recursive --new-file v1.3.47/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- v1.3.47/linux/arch/alpha/mm/fault.c	Tue Nov 21 13:22:05 1995
+++ linux/arch/alpha/mm/fault.c	Thu Dec 14 20:15:35 1995
@@ -20,10 +20,6 @@
 #include <asm/pgtable.h>
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
-extern void tbi(unsigned long type, unsigned long arg);
-#define tbisi(x) tbi(1,(x))
-#define tbisd(x) tbi(2,(x))
-#define tbis(x)  tbi(3,(x))
 
 /*
  * This routine handles page faults.  It determines the address,
diff -u --recursive --new-file v1.3.47/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- v1.3.47/linux/arch/alpha/mm/init.c	Sun Oct 29 11:38:48 1995
+++ linux/arch/alpha/mm/init.c	Fri Dec 15 07:31:30 1995
@@ -50,12 +50,6 @@
 	return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED));
 }
 
-unsigned long __zero_page(void)
-{
-	memset((void *) ZERO_PGE, 0, PAGE_SIZE);
-	return (unsigned long) ZERO_PGE;
-}
-
 void show_mem(void)
 {
 	int i,free = 0,total = 0,reserved = 0;
@@ -131,7 +125,7 @@
 
 	/* unmap the console stuff: we don't need it, and we don't want it */
 	/* Also set up the real kernel PCB while we're at it.. */
-	memset((void *) ZERO_PGE, 0, PAGE_SIZE);
+	memset((void *) ZERO_PAGE, 0, PAGE_SIZE);
 	memset(swapper_pg_dir, 0, PAGE_SIZE);
 	newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
 	pgd_val(swapper_pg_dir[1023]) = (newptbr << 32) | pgprot_val(PAGE_KERNEL);
diff -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile
--- v1.3.47/linux/arch/i386/boot/compressed/Makefile	Fri Nov 17 08:42:24 1995
+++ linux/arch/i386/boot/compressed/Makefile	Thu Dec 14 08:16:53 1995
@@ -7,7 +7,7 @@
 HEAD = head.o
 SYSTEM = $(TOPDIR)/vmlinux
 
-OBJECTS = $(HEAD) inflate.o unzip.o misc.o
+OBJECTS = $(HEAD) misc.o
 
 CFLAGS = -O2 -DSTDC_HEADERS
 
diff -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/Makefile.debug linux/arch/i386/boot/compressed/Makefile.debug
--- v1.3.47/linux/arch/i386/boot/compressed/Makefile.debug	Thu Jan  1 02:00:00 1970
+++ linux/arch/i386/boot/compressed/Makefile.debug	Thu Dec 14 08:16:52 1995
@@ -0,0 +1,21 @@
+#
+# linux/arch/i386/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+OBJECTS = misc.o 
+
+CFLAGS = -g -O2 -DSTDC_HEADERS -DSTANDALONE_DEBUG -Wall
+
+test-gzip: piggy.o $(OBJECTS)
+	$(CC) -g -o test-gzip $(OBJECTS) piggy.o
+
+clean: 
+	$(RM) inflate.o misc.o test-gzip
+
+inflate.o: inflate.c gzip.h
+
+misc.o: misc.c gzip.h
+
+
diff -u --recursive --new-file v1.3.47/linux/arch/i386/boot/compressed/crypt.h linux/arch/i386/boot/compressed/crypt.h
--- v1.3.47/linux/arch/i386/boot/compressed/crypt.h	Thu Dec 29 19:58:41 1994
+++ linux/arch/i386/boot/compressed/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.3.47/linux/arch/i386/boot/compressed/gzip.h linux/arch/i386/boot/compressed/gzip.h
--- v1.3.47/linux/arch/i386/boot/compressed/gzip.h	Thu Dec 29 19:58:41 1994
+++ linux/arch/i386/boot/compressed/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.3.47/linux/arch/i386/boot/compressed/inflate.c linux/arch/i386/boot/compressed/inflate.c
--- v1.3.47/linux/arch/i386/boot/compressed/inflate.c	Thu Dec 29 19:58:41 1994
+++ linux/arch/i386/boot/compressed/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.3.47/linux/arch/i386/boot/compressed/lzw.h linux/arch/i386/boot/compressed/lzw.h
--- v1.3.47/linux/arch/i386/boot/compressed/lzw.h	Thu Dec 29 19:58:41 1994
+++ linux/arch/i386/boot/compressed/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.3.47/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c
--- v1.3.47/linux/arch/i386/boot/compressed/misc.c	Tue Nov 21 13:22:05 1995
+++ linux/arch/i386/boot/compressed/misc.c	Thu Dec 14 08:16:53 1995
@@ -8,13 +8,69 @@
  * puts by Nick Holloway 1993, better puts by Martin Mares 1995
  */
 
-#include "gzip.h"
-#include "lzw.h"
+#include <string.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
 
 /*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+#define STATIC static
+
+#define memzero(s, n)     memset ((s), 0, (n))
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define WSIZE 0x8000		/* Window size must be at least 32k, */
+				/* and a power of two */
+
+static uch *inbuf;	     /* input buffer */
+static uch window[WSIZE];    /* Sliding window buffer */
+
+static unsigned insize = 0;  /* valid bytes in inbuf */
+static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0;  /* bytes in output buffer */
+
+/* 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 */
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+		
+/* 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
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+  
+/*
  * These are set up by the setup-routine at boot-time:
  */
 
@@ -42,83 +98,63 @@
 #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;
-
+static long bytes_out = 0;
+static uch *output_data;
+static unsigned long output_ptr = 0;
+ 
+static void *malloc(int size);
+static void free(void *where);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+ 
+#ifndef STANDALONE_DEBUG
+static void puts(const char *);
+  
 extern int end;
-long free_mem_ptr = (long)&end;
+static long free_mem_ptr = (long)&end;
 
-int to_stdout = 0;
-int hard_math = 0;
+static char *vidmem = (char *)0xb8000;
+static int vidport;
+static int lines, cols;
 
-void (*work)(int inf, int outf);
-void makecrc(void);
+#include "../../../../lib/inflate.c"
 
-local int get_method(int);
-
-char *vidmem = (char *)0xb8000;
-int vidport;
-int lines, cols;
-
-static void puts(const char *);
-
-void *malloc(int size)
+static 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");
+	if (free_mem_ptr >= 0x90000)
+		error("\nOut of memory\n");
 
-		return p;
-	}
-	if (free_mem_ptr < 0x90000)
 	return p;
-	puts("large kernel, low 1M tight...");
-	free_mem_ptr = (long)input_data;
-	}
 }
 
-void free(void *where)
+static void free(void *where)
 {	/* Don't care */
 }
 
+static void gzip_mark(void **ptr)
+{
+	*ptr = (void *) free_mem_ptr;
+}
+
+static void gzip_release(void **ptr)
+{
+	free_mem_ptr = (long) *ptr;
+}
+ 
 static void scroll()
 {
 	int i;
@@ -181,129 +217,47 @@
 
 	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;
-}
+#endif
 
 /* ===========================================================================
  * Fill the input buffer. This is called only when the buffer is empty
  * and at least one byte is really needed.
  */
-int fill_inbuf()
+static 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("ran out of input data\n");
+	}
 
-    if (insize == 0) {
-	error("unable to fill buffer\n");
-    }
-    bytes_in += (ulg)insize;
-    inptr = 1;
-    return inbuf[0];
+	inbuf = input_data;
+	insize = input_len;
+	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()
+static void flush_window()
 {
-    if (outcnt == 0) return;
-    updcrc(window, outcnt);
-
-    memcpy(&output_data[output_ptr], (char *)window, outcnt);
-
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, *out, ch;
+    
+    in = window;
+    out = &output_data[output_ptr]; 
+    for (n = 0; n < outcnt; n++) {
+	    ch = *out++ = *in++;
+	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
     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)
+static void error(char *x)
 {
 	puts("\n\n");
 	puts(x);
@@ -321,6 +275,34 @@
 	short b;
 	} stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS };
 
+#ifdef STANDALONE_DEBUG
+
+static void gzip_mark(void **ptr)
+{
+}
+
+static void gzip_release(void **ptr)
+{
+}
+
+char output_buffer[1024 * 800];
+
+int
+main(argc, argv)
+	int	argc;
+	char	**argv;
+{
+	output_data = output_buffer;
+
+	makecrc();
+	puts("Uncompressing Linux...");
+	gunzip();
+	puts("done.\n");
+	return 0;
+}
+
+#else
+
 void decompress_kernel()
 {
 	if (SCREEN_INFO.orig_video_mode == 7) {
@@ -337,94 +319,13 @@
 	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");
+	gunzip();
+	puts("done.\nNow booting the kernel\n");
 }
+#endif
 
-/* ========================================================================
- * 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.3.47/linux/arch/i386/boot/compressed/unzip.c linux/arch/i386/boot/compressed/unzip.c
--- v1.3.47/linux/arch/i386/boot/compressed/unzip.c	Thu Dec 29 19:58:41 1994
+++ linux/arch/i386/boot/compressed/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.3.47/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v1.3.47/linux/arch/i386/kernel/setup.c	Mon Dec 11 15:42:00 1995
+++ linux/arch/i386/kernel/setup.c	Thu Dec 14 08:16:53 1995
@@ -62,7 +62,9 @@
 #endif
 
 unsigned char aux_device_present;
-extern int ramdisk_size;
+extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;	/* starting block # of image */
 extern int root_mountflags;
 extern int _etext, _edata, _end;
 
@@ -79,12 +81,16 @@
 #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
 #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
 #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
-#define RAMDISK_SIZE (*(unsigned short *) (PARAM+0x1F8))
+#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
 #define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
 #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
 #define COMMAND_LINE ((char *) (PARAM+2048))
 #define COMMAND_LINE_SIZE 256
 
+#define RAMDISK_IMAGE_START_MASK  	0x07FF
+#define RAMDISK_PROMPT_FLAG		0x8000
+#define RAMDISK_LOAD_FLAG		0x4000	
+
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
 
 void setup_arch(char **cmdline_p,
@@ -110,7 +116,9 @@
 	aux_device_present = AUX_DEVICE_INFO;
 	memory_end = (1<<20) + (EXT_MEM_K<<10);
 	memory_end &= PAGE_MASK;
-	ramdisk_size = RAMDISK_SIZE;
+	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #ifdef CONFIG_MAX_16M
 	if (memory_end > 16*1024*1024)
 		memory_end = 16*1024*1024;
diff -u --recursive --new-file v1.3.47/linux/arch/mips/Makefile linux/arch/mips/Makefile
--- v1.3.47/linux/arch/mips/Makefile	Tue Aug 15 20:39:00 1995
+++ linux/arch/mips/Makefile	Wed Dec 13 12:39:42 1995
@@ -10,38 +10,84 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1994, 1995 by Waldorf Electronics,
-# written by Ralf Baechle
+# Copyright (C) 1994, 1995 by Ralf Baechle
 #
 
-AS		= mips-linux-as
-#ASFLAGS		= -mips3 -mcpu=r4000
-LD		= mips-linux-ld
-LINKFLAGS	= -Ttext 0xa0000000
+ifdef CONFIG_CPU_LITTLE_ENDIAN
+prefix		= mipsel-
+oformat		= a.out-mips-little-linux
+else
+prefix		= mips-
+oformat		= a.out-mips-big-linux
+endif
+
+ifdef CONFIG_EXTRA_ELF_COMPILER
+prefix		:= $(prefix)linuxelf-
+else
+prefix		:= $(prefix)linux-
+endif
+
+AS		= $(prefix)as
+LD		= $(prefix)ld
+LINKFLAGS	= -N -Ttext 0x80000000
+#LINKFLAGS	= -oformat=$(oformat) -N -Ttext 0x80000000
 #HOSTCC		= gcc
-#
-# KERNELBASE is quite useless, but I need it to work
-# around a hardware bug in my Wreckstation board. Other people
-# would burn that @#!%# thing...
-#
-CC		= mips-linux-gcc -V 2.5.8 -D__KERNEL__ -I$(TOPDIR)/include
+CC		= $(prefix)gcc -D__KERNEL__ -I$(TOPDIR)/include
 CPP		= $(CC) -E $(CFLAGS)
-AR		= mips-linux-ar
-RANLIB		= mips-linux-ranlib
-STRIP		= mips-linux-strip
+AR		= $(prefix)ar
+RANLIB		= $(prefix)ranlib
+OBJCOPY		= $(prefix)objcopy
+OBJDUMP		= $(prefix)objdump
+STRIP		= $(prefix)strip
+NM		= $(prefix)nm
 
-CFLAGS := $(CFLAGS) #-pipe
+#
+# The new ELF GCC uses -G0 -mabicalls -fpic as default.  We don't need PIC
+# code in the kernel since it only slows down the whole thing.  For the
+# old GCC these options are just the defaults.  At some point we might
+# make use of global pointer optimizations.
+#
+ifdef CONFIG_ELF_KERNEL
+CFLAGS		:= $(CFLAGS) -G0 -mno-abicalls -fno-pic
+LINKFLAGS	+= -T arch/mips/ld.script
+endif
 
-CFLAGS := $(CFLAGS) -DKERNELBASE=0xa0000000
+ifdef CONFIG_REMOTE_DEBUG
+CFLAGS		:= $(CFLAGS) -g
+endif
 
-ifdef CONFIG_R4X00
-CFLAGS := $(CFLAGS) -Wa,-mips3 -mcpu=r4000 -D__R4000__
+ifdef CONFIG_CPU_R3000
+CFLAGS		:= $(CFLAGS) -mcpu=r3000 -mips1
+#ASFLAGS		:= $(ASFLAGS) -mcpu=r3000 -mips1
+endif
+ifdef CONFIG_CPU_R6000
+CFLAGS		:= $(CFLAGS) -mcpu=r6000 -mips2
+#ASFLAGS		:= $(ASFLAGS) -mcpu=r6000 -mips2
+endif
+ifdef CONFIG_CPU_R4X00
+CFLAGS		:= $(CFLAGS) -D__R4000__ -mcpu=r4400 -mips2
+#ASFLAGS		:= $(ASFLAGS) -mcpu=r4400 -mips2
 endif
+ifdef CONFIG_CPU_R4600
+CFLAGS		:= $(CFLAGS) -D__R4000__ -mcpu=r4600 -mips2
+#ASFLAGS		:= $(ASFLAGS) -mcpu=r4600 -mips2
+endif
+ifdef CONFIG_CPU_R8000
+CFLAGS		:= $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2
+#ASFLAGS		:= $(ASFLAGS) -mcpu=r8000 -mips2
+endif
+ifdef CONFIG_CPU_R10000
+CFLAGS		:= $(CFLAGS) -D__R4000__ -mcpu=r8000 -mips2
+#ASFLAGS		:= $(ASFLAGS) -mcpu=r8000 -mips2
+endif
+
+CFLAGS		:= $(CFLAGS) -pipe
 
 HEAD := arch/mips/kernel/head.o
 
-SUBDIRS := $(SUBDIRS) arch/mips/kernel arch/mips/mm
+SUBDIRS := $(SUBDIRS) arch/mips/kernel arch/mips/mm arch/mips/lib
 ARCHIVES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(ARCHIVES)
+LIBS := arch/mips/lib/lib.a $(LIBS) arch/mips/lib/lib.a
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
@@ -55,6 +101,7 @@
 
 archclean:
 	@$(MAKEBOOT) clean
+	$(MAKE) -C arch/$(ARCH)/kernel clean
 
 archdep:
 	@$(MAKEBOOT) dep
diff -u --recursive --new-file v1.3.47/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile
--- v1.3.47/linux/arch/mips/boot/Makefile	Tue Jan 17 00:57:01 1995
+++ linux/arch/mips/boot/Makefile	Wed Dec 13 12:39:42 1995
@@ -5,20 +5,62 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1995 by  Waldorf Electronics,
-# written by Ralf Baechle
+# Copyright (C) 1995 by Ralf Baechle
 #
 
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+OBJS  = milo.o a.out.o
+
+#
+# Drop some uninteresting sections in the kernel.
+# This is only relevant for ELF kernels but doesn't hurt a.out
+#
+DROP_SECTIONS	= .reginfo .mdebug
+
+#
+# The new options of binutils 2.6 help to shrink object files alot.
+# This is especially usefull for booting from floppy.  Though we
+# don't yet require everyone to have binutils 2.6 installed.
+#
+OBJDUMP_VERSION =  $(word 4,$(shell $(OBJDUMP) --version))
+ifneq ($(OBJDUMP_VERSION),2.5.2)
+KEEP = kernel_entry boot_info screen_info _end
+STRIP_FLAGS = $(addprefix --keep-symbol=,$(KEEP))
+else
+STRIP_FLAGS = --discard-all
+endif
+
 #
 # Fake compressed boot
 #
+ifdef CONFIG_ELF_KERNEL
+zImage:	$(CONFIGURE) $(TOPDIR)/vmlinux
+	cp $(TOPDIR)/vmlinux zImage.tmp
+	$(STRIP) $(addprefix --remove-section=,$(DROP_SECTIONS)) \
+		--strip-symbol=blurb zImage.tmp
+	$(LD) -oformat=$(oformat) -N -e except_vec0 -Ttext=0x80000000 \
+		-o zImage zImage.tmp
+	rm -f zImage.tmp
+	$(STRIP) $(STRIP_FLAGS) zImage
+else
 zImage:	$(CONFIGURE) $(TOPDIR)/vmlinux
-	ln -fs $(TOPDIR)/vmlinux zImage
+	cp $(TOPDIR)/vmlinux $@
+	$(STRIP) $(STRIP_FLAGS) $@
+endif
 
 zdisk:	zImage
-	mcopy -n $(TOPDIR)/vmlinux a:vmlinux
+	mcopy -n zImage a:vmlinux
 
 dep:
+	$(CPP) -M *.[cS] > .depend
 
 clean:
-	rm -f zImage
+	rm -f zImage zImage.tmp
+
+dummy:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.47/linux/arch/mips/config.in linux/arch/mips/config.in
--- v1.3.47/linux/arch/mips/config.in	Tue Aug  8 12:31:33 1995
+++ linux/arch/mips/config.in	Wed Dec 13 12:39:43 1995
@@ -2,255 +2,107 @@
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
-
+mainmenu_name "Linux Kernel Configuration"
+  
+mainmenu_option next_comment
 comment 'Machine setup'
 
-bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE y
-bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61 y
-bool 'Support for DECstation' CONFIG_DECSTATION n
-
-bool 'Generate code for R4x00' CONFIG_R4X00 y
-
-comment 'General setup'
-
-bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
-bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 y
-if [ "$CONFIG_ST506" = "y" ]; then
-  comment 'Please see block/drivers/README.ide for help/info on IDE drives'
-  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 n
-  fi
-  if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
-    bool '   Include support for IDE CDROM (ATAPI)' CONFIG_BLK_DEV_IDECD n
-  fi
-fi
+bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
+bool 'Support for DECstation' CONFIG_DECSTATION
+bool 'Support for Deskstation RPC44' CONFIG_DESKSTATION_RPC44
+bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE
+bool 'Support for Mips Magnum 3000' CONFIG_MIPS_MAGNUM_3000
+bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000
+bool 'Support for Olivetty M700' CONFIG_OLIVETTI_M700
+if [ "$CONFIG_ACER_PICA_61" = "y" -o \
+     "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
+     "$CONFIG_OLIVETTI_M700" = "y" ]; then
+	define_bool CONFIG_MIPS_JAZZ y
+fi
+
+choice 'CPU type' \
+	"R3000 CONFIG_CPU_R3000	\
+	 R6000 CONFIG_CPU_R6000	\
+	 R4x00 CONFIG_CPU_R4X00	\
+	 R4600 CONFIG_CPU_R4600	\
+	 R8000 CONFIG_CPU_R8000	\
+	 R10000 CONFIG_CPU_R10000" R4x00
+if [ "$CONFIG_CPU_R3000" = "y" -o \
+     "$CONFIG_CPU_R6000" = "y" -o \
+     "$CONFIG_CPU_R4X00" = "y" -o \
+     "$CONFIG_CPU_R4600" = "y" -o \
+     "$CONFIG_CPU_R8000" = "y" ]; then
+	define_bool CONFIG_TLB_SHUTDOWN y
+fi
+
+define_bool CONFIG_BINFMT_ELF y
+bool 'Compile the kernel into the ELF object format' CONFIG_ELF_KERNEL
+if [ "$CONFIG_ELF_KERNEL" = "y" ]; then
+  bool 'Is your ELF compiler an extra compiler' CONFIG_EXTRA_ELF_COMPILER
+fi
+bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
+bool 'Networking support' CONFIG_NET
+#bool 'PCI bios support' CONFIG_PCI
+#if [ "$CONFIG_PCI" = "y" ]; then
+#  bool '   PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE
+#fi
+bool 'System V IPC' CONFIG_SYSVIPC
+
+mainmenu_option next_comment
+comment 'Loadable module support'
+bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
 
-bool 'XT harddisk support' CONFIG_BLK_DEV_XD n
-bool 'Networking support' CONFIG_NET y
-bool 'System V IPC' CONFIG_SYSVIPC n
-bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF n
+source drivers/block/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
-comment 'Networking options'
-bool 'TCP/IP networking' CONFIG_INET y
-if [ "$CONFIG_INET" "=" "y" ]; then
-bool 'IP forwarding/gatewaying' CONFIG_IP_FORWARD y
-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
-bool 'Assume subnets are local' CONFIG_INET_SNARL y
-bool 'Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n
-fi
-bool 'The IPX protocol' CONFIG_IPX n
-#bool 'Amateur Radio AX.25 Level 2' CONFIG_AX25 n
+  source net/Config.in
 fi
 
+mainmenu_option next_comment
 comment 'SCSI support'
 
-bool 'SCSI support?' CONFIG_SCSI n
+tristate 'SCSI support' CONFIG_SCSI
 
-if [ "$CONFIG_SCSI" = "n" ]; then
-
-comment 'Skipping SCSI configuration options...'
-
-else
-
-comment 'SCSI support type (disk, tape, CDrom)'
-
-bool 'SCSI disk support' CONFIG_BLK_DEV_SD y
-bool 'SCSI tape support' CONFIG_CHR_DEV_ST y
-bool 'SCSI CDROM support' CONFIG_BLK_DEV_SR y
-bool 'SCSI generic support' CONFIG_CHR_DEV_SG y
-
-comment 'SCSI low-level drivers'
-
-bool 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n
-bool 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 y
-bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 n
-bool 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC n
-bool 'EATA-DMA (DPT, NEC, ATT, Olivetti) support' CONFIG_SCSI_EATA_DMA y
-bool 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO n
-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
-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 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA n
-#bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n
+if [ "$CONFIG_SCSI" != "n" ]; then
+  source drivers/scsi/Config.in
 fi
 
-
 if [ "$CONFIG_NET" = "y" ]; then
+  mainmenu_option next_comment
+  comment 'Network device support'
 
-comment 'Network device support'
-
-bool 'Network device support?' CONFIG_NETDEVICES n
-if [ "$CONFIG_NETDEVICES" = "n" ]; then
-
-comment 'Skipping network driver configuration options...'
-
-else
-bool 'Dummy net driver support' CONFIG_DUMMY n
-bool 'SLIP (serial line) support' CONFIG_SLIP n
-if [ "$CONFIG_SLIP" = "y" ]; then
-  bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
-#  bool ' SLIP debugging on' SL_DUMP y
-fi
-bool 'PPP (point-to-point) support' CONFIG_PPP n
-bool 'PLIP (parallel port) support' CONFIG_PLIP n
-bool 'Load balancing support (experimental)' CONFIG_SLAVE_BALANCING n
-bool 'Do you want to be offered ALPHA test drivers' CONFIG_NET_ALPHA n
-bool 'Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC y
-if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then
-	bool 'WD80*3 support' CONFIG_WD80x3 y
-	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 y
-if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
-	bool '3c501 support' CONFIG_EL1 n
-	bool '3c503 support' CONFIG_EL2 n
-	if [ "$CONFIG_NET_ALPHA" = "y" ]; then
-		bool '3c505 support' CONFIG_ELPLUS n
-		bool '3c507 support' CONFIG_EL16 n
-	fi
-	bool '3c509/3c579 support' CONFIG_EL3 n
-fi
-bool 'Other ISA cards' CONFIG_NET_ISA n
-if [ "$CONFIG_NET_ISA" = "y" ]; then
-	bool 'Cabletron E21xx support' CONFIG_E2100 n
-	bool 'DEPCA support' CONFIG_DEPCA n
-	bool 'EtherWorks 3 support' CONFIG_EWRK3 n
-	if [ "$CONFIG_NET_ALPHA" = "y" ]; then
-		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+ (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 y
-	bool 'SK_G16 support' CONFIG_SK_G16 n
-fi
-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 '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
-
-comment 'CD-ROM drivers'
-
-bool 'Sony CDU31A/CDU33A CDROM driver support' CONFIG_CDU31A n
-bool 'Mitsumi CDROM driver support' CONFIG_MCD n
-bool 'Matsushita/Panasonic CDROM driver support' CONFIG_SBPCD n
-if [ "$CONFIG_SBPCD" = "y" ]; then
-  bool 'Matsushita/Panasonic second CDROM controller support' CONFIG_SBPCD2 n
-  if [ "$CONFIG_SBPCD2" = "y" ]; then
-    bool 'Matsushita/Panasonic third CDROM controller support' CONFIG_SBPCD3 n
-    if [ "$CONFIG_SBPCD3" = "y" ]; then
-      bool 'Matsushita/Panasonic fourth CDROM controller support' CONFIG_SBPCD4 n
-    fi
+  bool 'Network device support' CONFIG_NETDEVICES
+  if [ "$CONFIG_NETDEVICES" = "y" ]; then
+    source drivers/net/Config.in
   fi
 fi
 
-comment 'Filesystems'
+mainmenu_option next_comment
+comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
 
-bool 'Standard (minix) fs support' CONFIG_MINIX_FS y
-bool 'Extended fs support' CONFIG_EXT_FS n
-bool 'Second extended fs support' CONFIG_EXT2_FS n
-bool 'xiafs filesystem support' CONFIG_XIA_FS n
-bool 'msdos fs support' CONFIG_MSDOS_FS n
-if [ "$CONFIG_MSDOS_FS" = "y" ]; then
-bool 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS n
-fi
-bool '/proc filesystem support' CONFIG_PROC_FS n
-if [ "$CONFIG_INET" = "y" ]; then
-bool 'NFS filesystem support' CONFIG_NFS_FS y
-fi
-if [ "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_CDU31A" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_BLK_DEV_IDECD" = "y" ]; then
-	bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS y
-else
-	bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
-fi
-bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n
-bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
-
-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 n
-if [ "$CONFIG_PSMOUSE" = "y" ]; then
-bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE n
+bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
+if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+  source drivers/cdrom/Config.in
 fi
-bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
-bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-  
-bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
-if [ "$CONFIG_QIC02_TAPE" = "y" ]; then
-bool 'Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF n
-if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then
 
-comment '>>> Edit configuration parameters in ./include/linux/tpqic02.h!'
+source fs/Config.in
 
-else
-
-comment '>>> Setting runtime QIC-02 configuration is done with qic02conf'
-comment '>>> Which is available from ftp://ftp.funet.fi/pub/OS/Linux/BETA/QIC-02/'
-
-fi
-fi
-
-bool 'QIC-117 tape support' CONFIG_FTAPE n
-if [ "$CONFIG_FTAPE" = "y" ]; then
-int ' number of ftape buffers' NR_FTAPE_BUFFERS 3
-fi
+source drivers/char/Config.in
+bool 'Standard serial device support' CONFIG_SERIAL n
 
+mainmenu_option next_comment
 comment 'Sound'
 
-bool 'Sound card support' CONFIG_SOUND n
+tristate 'Sound card support' CONFIG_SOUND
+if [ "$CONFIG_SOUND" != "n" ]; then
+  source drivers/sound/Config.in
+fi
 
+mainmenu_option next_comment
 comment 'Kernel hacking'
 
-#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
-bool 'Kernel profiling support' CONFIG_PROFILE n
+#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+bool 'Kernel profiling support' CONFIG_PROFILE
 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.3.47/linux/arch/mips/defconfig linux/arch/mips/defconfig
--- v1.3.47/linux/arch/mips/defconfig	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/defconfig	Wed Dec 13 12:39:43 1995
@@ -0,0 +1,87 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Machine setup
+#
+CONFIG_ACER_PICA_61=y
+# CONFIG_DECSTATION is not set
+# CONFIG_DESKSTATION_RPC44 is not set
+# CONFIG_DESKSTATION_TYNE is not set
+# CONFIG_MIPS_MAGNUM_3000 is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_OLIVETTI_M700 is not set
+CONFIG_MIPS_JAZZ=y
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R6000 is not set
+CONFIG_CPU_R4X00=y
+# CONFIG_CPU_R4600 is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+CONFIG_TLB_SHUTDOWN=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_ELF_KERNEL is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_NET is not set
+# CONFIG_SYSVIPC is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODVERSIONS is not set
+
+#
+# block devices
+#
+CONFIG_BLK_DEV_FD=y
+# CONFIG_ST506 is not set
+# CONFIG_BLK_DEV_XD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Filesystems
+#
+# CONFIG_MINIX_FS is not set
+# CONFIG_EXT_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_XIA_FS is not set
+# CONFIG_MSDOS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_SMB_FS is not set
+
+#
+# character devices
+#
+# CONFIG_CYCLADES is not set
+# CONFIG_STALDRV is not set
+# CONFIG_PRINTER is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_PSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_APM is not set
+# CONFIG_SERIAL is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PROFILE is not set
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile
--- v1.3.47/linux/arch/mips/kernel/Makefile	Tue Aug 15 20:39:00 1995
+++ linux/arch/mips/kernel/Makefile	Wed Dec 13 12:39:43 1995
@@ -1,53 +1,101 @@
 #
-# Makefile for the linux kernel.
+# Makefile for the Linux/MIPS kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 #
-# Note 2! The CFLAGS definitions are now in the main makefile...
 
 .S.s:
-	$(CPP) $(CFLAGS) -D__ASSEMBLY__ -traditional $< -o $*.s
+	$(CPP) $(CFLAGS) $< -o $*.s
 .S.o:
-	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+	$(CC) $(CFLAGS) -c $< -o $*.o
 
+all:	kernel.o head.o
 EXTRA_ASFLAGS = -mips3 -mcpu=r4000
-OBJS  = process.o signal.o entry.o traps.o irq.o ptrace.o cache.o resume.o \
-	ioport.o setup.o bios32.o tynedma.o
+O_TARGET := kernel.o
+O_OBJS	:= process.o signal.o entry.o traps.o irq.o ptrace.o vm86.o ioport.o \
+	setup.o syscall.o sysmips.o time.o bios32.o ipc.o
 
-all: kernel.o head.o
+#
+# Kernel debugging
+#
+ifdef CONFIG_REMOTE_DEBUG
+OBJS += gdb-low.o gdb-stub.o 
+endif
 
-cache.o: cache.s
+#
+# Board specific code
+#
+ifdef CONFIG_MIPS_JAZZ
+O_OBJS += jazzdma.o jazz-c.o
+endif
+
+ifdef CONFIG_ACER_PICA_61
+O_OBJS += pica.o
+endif
+
+ifdef CONFIG_DESKSTATION_TYNE
+O_OBJS += tyne.o tyne-c.o
+endif
+
+ifdef CONFIG_MIPS_MAGNUM_4000
+O_OBJS += magnum4000.o
+endif
 
-cache.s: cache.S $(TOPDIR)/include/asm/mipsconfig.h \
-	$(TOPDIR)/include/asm/regdef.h $(TOPDIR)/include/asm/segment.h
+#
+# CPU model specific code
+#
+ifdef CONFIG_CPU_R2000
+O_OBJS += r3000.o
+endif
+
+ifdef CONFIG_CPU_R3000
+O_OBJS += r3000.o
+endif
+
+ifdef CONFIG_CPU_R4X00
+O_OBJS += r4xx0.o
+endif
+
+ifdef CONFIG_CPU_R4600
+O_OBJS += r4xx0.o
+endif
+
+ifdef CONFIG_CPU_R6000
+	exit 1			# no detailed informations about CPU yet.
+endif
+
+ifdef CONFIG_CPU_R8000
+	exit 1			# no detailed informations about CPU yet.
+endif
+
+ifdef CONFIG_CPU_R10000
+O_OBJS += r4xx0.o
+endif
 
-entry.o: entry.s
+#
+# Since we add the same object files to O_OBJS for different configurations.
+# O_OBJS might contain duplicate files.  We correct this by filtering out
+# duplicate files.  Just to avoid users having to know about all the
+# compatibility stuff between various boards and boards.
+#
+O_OBJS := $(sort $(O_OBJS))
 
-entry.s: entry.S $(TOPDIR)/include/linux/sys.h \
-	$(TOPDIR)/include/linux/autoconf.h $(TOPDIR)/include/asm/segment.h \
-	$(TOPDIR)/include/asm/mipsregs.h $(TOPDIR)/include/asm/mipsconfig.h \
-	$(TOPDIR)/include/asm/page.h $(TOPDIR)/include/asm/stackframe.h \
-	$(TOPDIR)/include/asm/regdef.h $(TOPDIR)/include/asm/processor.h
+all: kernel.o head.o
 
-head.o: head.s
+entry.o: entry.S
 
-head.s: head.S $(TOPDIR)/include/linux/tasks.h
+head.o: head.S
 
-resume.o: resume.s
+magnum4000.o: magnum4000.S
 
-resume.s: resume.S $(TOPDIR)/include/asm/regdef.h \
-	$(TOPDIR)/include/asm/processor.h $(TOPDIR)/include/asm/mipsregs.h \
-	$(TOPDIR)/include/asm/mipsconfig.h
+pica.o: pica.S
 
-tlb.o: tlb.s
+r4xx0.o: r4xx0.S
 
-tlb.s:	tlb.S $(TOPDIR)/include/asm/regdef.h $(TOPDIR)/include/asm/mipsregs.h \
-	$(TOPDIR)/include/asm/bootinfo.h
+tyne.o: tyne.S
 
-kernel.o: $(OBJS)
-	$(LD) -r -o kernel.o $(OBJS)
-	sync
+clean:
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/cache.S linux/arch/mips/kernel/cache.S
--- v1.3.47/linux/arch/mips/kernel/cache.S	Fri Jan 13 20:27:37 1995
+++ linux/arch/mips/kernel/cache.S	Thu Jan  1 02:00:00 1970
@@ -1,81 +0,0 @@
-/*
- * arch/mips/kernel/cache.S
- *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * Written by Ralf Baechle
- *
- * Flush instruction/data caches
- *
- * Parameters: a0 - starting address to flush
- *             a1 - size of area to be flushed
- *             a2 - which caches to be flushed
- *
- * FIXME:      - ignores parameters
- *             - doesn't know about second level caches
- *             - only knows how to handle the R4600
- */
-
-#include <asm/mipsconfig.h>
-#include <asm/regdef.h>
-#include <asm/segment.h>
-
-#define PAGE_SIZE	0x1000
-
-#define CACHELINES	512             /* number of cachelines    */
-
-		.set	noreorder
-		.globl	_sys_cacheflush
-		.text
-_sys_cacheflush:
-		/*
-		 * Writeback/invalidate the data cache
-		 */
-		li	t0,KSEG0
-		li	t1,CACHELINES
-1:		cache	1,0(t0)
-		cache	1,32(t0)
-		cache	1,64(t0)
-		cache	1,96(t0)
-		cache	1,128(t0)
-		cache	1,160(t0)
-		cache	1,192(t0)
-		cache	1,224(t0)
-		cache	1,256(t0)
-		cache	1,288(t0)
-		cache	1,320(t0)
-		cache	1,352(t0)
-		cache	1,384(t0)
-		cache	1,416(t0)
-		cache	1,448(t0)
-		cache	1,480(t0)
-		subu    t1,t1,1
-		bnez	t1,1b
-		addiu	t0,t0,512			# delay slot
-
-		/*
-		 * Flush the instruction cache
-		 */
-		lui	t0,0x8000
-		li	t1,CACHELINES
-1:		cache	0,0(t0)	
-		cache	0,32(t0)
-		cache	0,64(t0)
-		cache	0,96(t0)
-		cache	0,128(t0)
-		cache	0,160(t0)
-		cache	0,192(t0)
-		cache	0,224(t0)
-		cache	0,256(t0)
-		cache	0,288(t0)
-		cache	0,320(t0)
-		cache	0,352(t0)
-		cache	0,384(t0)
-		cache	0,416(t0)
-		cache	0,448(t0)
-		cache	0,480(t0)
-		subu	t1,t1,1
-		bnez	t1,1b
-		addiu	t0,t0,512			# delay slot
-
-		j	ra
-		nop
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S
--- v1.3.47/linux/arch/mips/kernel/entry.S	Wed Jan 25 08:54:22 1995
+++ linux/arch/mips/kernel/entry.S	Wed Dec 13 12:39:43 1995
@@ -1,25 +1,31 @@
 /*
- * arch/mips/kernel/entry.S
+ * Low level exception handling
  *
- * Copyright (C) 1994, 1995 Waldorf Electronics
- * written by Ralf Baechle
+ * 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, 1995 by Ralf Baechle
  */
 
 /*
  * entry.S contains the system-call and fault low-level handling routines.
  * This also contains the timer-interrupt handler, as well as all interrupts
- * and faults that can result in a task-switch.
+ * and faults that can result in a task-switch. The ISA dependend TLB
+ * code is in arch/mips/kernel/<cputype>.S
  */
-
 #include <linux/sys.h>
-#include <linux/autoconf.h>
+
+#include <asm/asm.h>
+#include <asm/errno.h>
 #include <asm/segment.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsconfig.h>
 #include <asm/page.h>
+#include <asm/pgtable.h>
 #include <asm/stackframe.h>
-#include <asm/regdef.h>
 #include <asm/processor.h>
+#include <asm/unistd.h>
 
 /*
  * These are offsets into the task-struct.
@@ -30,944 +36,276 @@
 signal		= 12
 blocked		= 16
 flags		= 20
-errno		= 24			#/* MIPS OK */
-exec_domain	= 60			#/* ??? */
-
-ENOSYS		= 38
+errno		= 24
+exec_domain	= 60
 
-		.globl	ret_from_sys_call
-		.globl	_sys_call_table
+#ifdef __SMP__
+#error "Fix this for SMP"
+#else
+#define current current_set
+#endif
 
+/*
+ * Heia ...  The %lo, %hi and %HI stuff is too strong for the ELF assembler
+ * and the ABI to cope with ...
+ */
 		.text
 		.set	noreorder
 		.align 4
 handle_bottom_half:
-		/*
-		 * If your assembler breaks on the next line it's
-		 * time to update!
-		 */
-		lui	s0,%hi(_intr_count)
-		lw	s1,%lo(_intr_count)(s0)
-		mfc0	s3,CP0_STATUS			# Enable IRQs
+		lui	s0,%hi(intr_count)
+		lw	s1,%lo(intr_count)(s0)
+		mfc0	s3,CP0_STATUS		# Enable IRQs
 		addiu	s2,s1,1
-		sw	s2,%lo(_intr_count)(s0)
+		sw	s2,%lo(intr_count)(s0)
 		ori	t0,s3,0x1f
-		xori	t0,t0,0x1e
-		jal	_do_bottom_half
-		mtc0	t0,CP0_STATUS			# delay slot
-		mtc0	s3,CP0_STATUS			# Restore old IRQ state
-		j	9f
-		sw	s1,%lo(_intr_count)(s0)		# delay slot
-
-		.set	reorder
-reschedule:
-		la	ra,ret_from_sys_call
-		j	_schedule
-		nop
-
-		.align	5
-		.globl	_handle_sys
-_handle_sys:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		.set	at
-		STI
-		/*
-		 * Compute return address. For now we assume that syscalls never
-		 * appear in branch delay slots. For the Linux/MIPS standard
-		 * libraries this assumption is always try.
-		 */
-		lw	t3,FR_EPC(sp)
-		lw	s1,FR_REG2(sp)
-		li	t0,-ENOSYS
-		addiu	t3,t3,4
-		sw	t3,FR_EPC(sp)
-		li	t2,NR_syscalls
-		bge	s1,t2,ret_from_sys_call
-		sw	t0,FR_REG2(sp)		# delay slot
-		sll	s1,s1,2
-		lw	s1,_sys_call_table(s1)
-		lw	s0,_current
-
-		beqz	s1,ret_from_sys_call
-		lw	t0,flags(s0)
-		sll	t0,t0,2			# PF_TRACESYS
-		bltz	t0,1f
-		sw	zero,errno(s0)		# delay slot
-
-		lw	a0,FR_REG4(sp)
-		lw	a1,FR_REG5(sp)
-		lw	a2,FR_REG6(sp)
-		lw	a3,FR_REG7(sp)
-		lw	t0,FR_REG3(sp)
-		jalr	s1			# do the real work
-		sw	t0,16(sp)		# delay slot
-
-		lw	t0,errno(s0)
-		sw	v0,FR_REG2(sp)		# save the return value
-		subu	t0,zero,t0		# t0 = -t0
-		beqz	t0,ret_from_sys_call
-		nop
-		/*
-		 * Fixme: should set error flag
-		 */
-		j	ret_from_sys_call
-		sw	t0,FR_REG2(sp)		# delay slot
-
-		.align	4
-1:		jal	_syscall_trace
-		nop				# delay slot
-
-		lw	a0,FR_REG4(sp)
-		lw	a1,FR_REG5(sp)
-		lw	a2,FR_REG6(sp)
-		lw	a3,FR_REG7(sp)
-		lw	t0,FR_REG3(sp)
-		jalr	s1			# do the real work
-		sw	t0,16(sp)		# delay slot
-
-		lw	t0,errno(s0)
-		sw	v0,FR_REG2(sp)		# save the return value
-		subu	t0,zero,t0
-		beqz	t0,1f
-		nop				# delay slot
-		sw	t1,FR_REG2(sp)
-		/*
-		 * Fixme: should set error flag
-		 */
-1:		jal	_syscall_trace
-		nop
+		xori	t0,0x1e
+		jal	do_bottom_half
+		mtc0	t0,CP0_STATUS		# delay slot
+		mtc0	s3,CP0_STATUS		# Restore old IRQ state
+		b	9f
+		sw	s1,%lo(intr_count)(s0)	# delay slot
+
+reschedule:	jal	schedule 
+		nop				# delay slot
+EXPORT(ret_from_sys_call)
+		lw	t0,intr_count		# bottom half
+		bnez	t0,return
 
-		.align	4
-ret_from_sys_call:
-		lw	t0,_intr_count		# bottom half
-		bnez	t0,2f
-9:
-		lw	t0,_bh_mask		# delay slot
-		lw	t1,_bh_active		# unused delay slot
+9:		lw	t0,bh_mask		# delay slot
+		lw	t1,bh_active		# unused delay slot
 		and	t0,t1
 		bnez	t0,handle_bottom_half
 
-		lw	t0,FR_STATUS(sp)	# returning to supervisor ?
+		lw	t0,FR_STATUS(sp)	# returning to kernel mode?
 		andi	t1,t0,0x10
-		beqz	t1,2f
+		beqz	t1,return		# -> yes
 
 		mfc0	t0,CP0_STATUS		# delay slot
-		lw	t1,_need_resched
+		lw	t1,need_resched
 		ori	t0,0x1f			# enable irqs
 		xori	t0,0x1e
 		bnez	t1,reschedule
 		mtc0	t0,CP0_STATUS		# delay slot
 
-		lw	s0,_current
-		lw	t0,_task
-		lw	t1,state(s0)		# state
-		beq	s0,t0,2f		# task[0] cannot have signals
-		lw	t0,counter(s0)		# counter
-		bnez	t1,reschedule		# state == 0 ?
+		lw	s0,current
+		lw	t0,task
 		lw	a0,blocked(s0)
+		beq	s0,t0,return		# task[0] cannot have signals
 						# save blocked in a0 for
 						# signal handling
-		beqz	t0,reschedule		# counter == 0 ?
 		lw	t0,signal(s0)
 		nor	t1,zero,a0
 		and	t1,t0,t1
-		beqz	t1,skip_signal_return
+		beqz	t1,return
 		nop
 
-		jal	_do_signal
+		jal	do_signal
 		move	a1,sp			# delay slot
 		
-skip_signal_return:
-		.set	noreorder
 		.set	noat
-2:
-return:		RESTORE_ALL
-		.set	at
-
-#ifdef CONFIG_DESKSTATION_TYNE
-/*
- * Deskstation Tyne interrupt handler
- */
-		.text
-		.set	noreorder
-		.set	noat
-		.globl	_deskstation_tyne_handle_int
-		.align	5
-_deskstation_tyne_handle_int:
-		SAVE_ALL
+EXPORT(return)	RESTORE_ALL
+		ERET
 		.set	at
-		CLI
-		lui	s0,%hi(PORT_BASE)
-		li	t1,0x0f
-		sb	t1,%lo(PORT_BASE+0x20)(s0)	# poll command
-		lb	t1,%lo(PORT_BASE+0x20)(s0)	# read result
-		li	s1,1
-		bgtz	t1,Lpoll_second
-		andi	t1,t1,7
-		/*
-		 * Acknowledge first pic
-		 */
-		lb	t2,%lo(PORT_BASE+0x21)(s0)
-		lui	s4,%hi(_cache_21)
-		lb	t0,%lo(_cache_21)(s4)
-		sllv	s1,s1,t1
-		or	t0,t0,s1
-		sb	t0,%lo(_cache_21)(s4)
-		sb	t0,%lo(PORT_BASE+0x21)(s0)
-		lui	s3,%hi(_intr_count)
-		lw	t0,%lo(_intr_count)(s3)
-		li	t2,0x20
-		sb	t2,%lo(PORT_BASE+0x20)(s0)
-		/*
-		 * Now call the real handler
-		 */
-		la	t3,_IRQ_vectors
-		sll	t2,t1,2
-		addu	t3,t3,t2
-		lw	t3,(t3)
-		addiu	t0,t0,1
-		jalr	t3
-		sw	t0,%lo(_intr_count)(s3)		# delay slot
-		lw	t0,%lo(_intr_count)(s3)
-		/*
-		 * Unblock first pic
-		 */
-		lbu	t1,%lo(PORT_BASE+0x21)(s0)
-		lb	t1,%lo(_cache_21)(s4)
-		subu	t0,t0,1
-		sw	t0,%lo(_intr_count)(s3)
-		nor	s1,zero,s1
-		and	t1,t1,s1
-		sb	t1,%lo(_cache_21)(s4)
-		jr	v0
-		sb	t1,%lo(PORT_BASE+0x21)(s0)	# delay slot
-
-		.align	5
-Lpoll_second:	li	t1,0x0f
-		sb	t1,%lo(PORT_BASE+0xa0)(s0)	# poll command
-		lb	t1,%lo(PORT_BASE+0xa0)(s0)	# read result
-		lui	s4,%hi(_cache_A1)
-		bgtz	t1,Lspurious_interrupt
-		andi	t1,t1,7
-		/*
-		 * Acknowledge second pic
-		 */
-		lbu	t2,%lo(PORT_BASE+0xa1)(s0)
-		lb	t3,%lo(_cache_A1)(s4)
-		sllv	s1,s1,t1
-		or	t3,t3,s1
-		sb	t3,%lo(_cache_A1)(s4)
-		sb	t3,%lo(PORT_BASE+0xa1)(s0)
-		li	t3,0x20
-		sb	t3,%lo(PORT_BASE+0xa0)(s0)
-		lui	s3,%hi(_intr_count)
-		lw	t0,%lo(_intr_count)(s3)
-		sb	t3,%lo(PORT_BASE+0x20)(s0)
-		/*
-		 * Now call the real handler
-		 */
-		la	t0,_IRQ_vectors
-		sll	t2,t1,2
-		addu	t0,t0,t2
-		lw	t0,32(t0)
-		addiu	t0,t0,1
-		jalr	t0
-		sw	t0,%lo(_intr_count)(s3)		# delay slot
-		lw	t0,%lo(_intr_count)(s3)
-		/*
-		 * Unblock second pic
-		 */
-		lb	t1,%lo(PORT_BASE+0xa1)(s0)
-		lb	t1,%lo(_cache_A1)(s4)
-		subu	t0,t0,1
-		lw	t0,%lo(_intr_count)(s3)
-		nor	s1,zero,s1
-		and	t1,t1,s1
-		sb	t1,%lo(_cache_A1)(s4)
-		jr	v0
-		sb	t1,%lo(PORT_BASE+0xa1)(s0)	# delay slot
 
-		.align	5
-Lspurious_interrupt:
-		/*
-		 * Nothing happened... (whistle)
-		 */
-		lui	t1,%hi(_spurious_count)
-		lw	t0,%lo(_spurious_count)(t1)
-		la	v0,return
-		addiu	t0,t0,1
-		jr	ra
-		sw	t0,%lo(_spurious_count)(t1)
-#endif /* CONFIG_DESKSTATION_TYNE */
-		
-#ifdef CONFIG_ACER_PICA_61
 /*
- * Acer PICA interrupt handler dummy
+ * Beware: interrupt, fast_interrupt and bad_interrupt have unusal
+ * calling conventions to speedup the mess.
+ *
+ * t1 - interrupt number
+ * s2 - destroyed
+ * return values:
+ * v0 - return routine
  */
-		.set	noreorder
-		.set	noat
-		.globl	_acer_pica_61_handle_int
-		.align	5
-_acer_pica_61_handle_int:
-		la	a0,acer_text
-		jal	_panic
-		nop
-1:		b	1b
-		nop
-acer_text:	.asciz	"Interrupt handler for Acer PICA not written yet"
-		.align	2
-#endif /* CONFIG_ACER_PICA_61 */
-
 		.text
-		.set	noreorder
 		.set	at
-		.globl	_interrupt
 		.align	5
-_interrupt:	move	s2,ra
-		mfc0	t0,CP0_STATUS
-		ori	t0,t0,0x1f
-		xori	t0,t0,0x1e
+NESTED(interrupt, FR_SIZE, sp)
+		move	s2,ra
+		mfc0	t0,CP0_STATUS			# enable IRQs
+		ori	t0,0x1f
+		xori	t0,0x1e
 		mtc0	t0,CP0_STATUS
 		move	a0,t1
-		jal	_do_IRQ
+		jal	do_IRQ
 		move	a1,sp				# delay slot
-		mfc0	t0,CP0_STATUS
-		ori	t0,t0,1
-		xori	t0,t0,1
+		mfc0	t0,CP0_STATUS			# disable IRQs
+		ori	t0,1
+		xori	t0,1
 		la	v0,ret_from_sys_call
 		jr	s2
 		mtc0	t0,CP0_STATUS			# delay slot
+		END(interrupt)
 
-		.globl	_fast_interrupt
 		.align	5
-_fast_interrupt:
+NESTED(fast_interrupt, FR_SIZE, sp)
 		move	s2,ra
 		move	a0,t1
-		jal	_do_fast_IRQ
+		jal	do_fast_IRQ
 		move	a1,sp				# delay slot
-		la	v0,return
+		lui	v0,%hi(return)
 		jr	s2
-		nop					# delay slot
+		addiu	v0,%lo(return)			# delay slot
+		END(fast_interrupt)
 
-		.globl	_bad_interrupt
-_bad_interrupt:
+LEAF(bad_interrupt)
 		/*
 		 * Don't return & unblock the pic
 		 */
 		j	return
 		nop
+		END(bad_interrupt)
 
-		.globl	_handle_tlbl
-		.align	5
-_handle_tlbl:
+/*
+ * do_syscall calls the function in a1 with upto 7 arguments.  If over
+ * four arguments are being requested, the additional arguments will
+ * be copied from the user stack pointed to by a0->reg29.
+ * Note that this routine relies on the GNU assemblers weak instruction
+ * scheduling abilities to generate the best possible code for all MIPS CPUs.
+ *
+ * a0 (struct pt_regs *)  pointer to user registers
+ * a1 (syscall_t)         pointer to syscall to do
+ * a2 (int)               number of arguments to syscall
+ */
 		.set	noreorder
-		.set	noat
-		/*
-		 * Check whether this is a refill or an invalid exception
-		 *
-		 * NOTE: Some MIPS manuals say that the R4x00 sets the
-		 * BadVAddr only when EXL == 0. This is wrong - BadVaddr
-		 * is being set for all Reload, Invalid and Modified
-		 * exceptions.
-		 */
-		mfc0	k0,CP0_BADVADDR
-		mfc0	k1,CP0_ENTRYHI
-		ori	k0,k0,0x1fff
-		xori	k0,k0,0x1fff
-		andi	k1,k1,0xff
-		or	k0,k0,k1
-		mfc0	k1,CP0_ENTRYHI
-		mtc0	k0,CP0_ENTRYHI
-		nop					# for R4[04]00 pipeline
-		nop
-		nop
-		tlbp
-		nop					# for R4[04]00 pipeline
-		nop
-		mfc0	k0,CP0_INDEX
-		srl	k0,k0,31
-		beqz	k0,invalid_tlbl
-		mtc0	k1,CP0_ENTRYHI			# delay slot
-		/*
-		 * Not in tlb -> nested refill exception
-		 * Load the missing entry and return. This is the most
-		 * efficient way to regain the faulting address.
-		 */
-		dmfc0	k1,CP0_CONTEXT
-		dsra	k1,k1,1
-		lwu	k0,(k1)			# Never causes another exception
-		lwu	k1,4(k1)
-		dsrl	k0,k0,6			# Convert to EntryLo format
-		dsrl	k1,k1,6			# Convert to EntryLo format
-		dmtc0	k0,CP0_ENTRYLO0
-		dmtc0	k1,CP0_ENTRYLO1
-		nop				# for R4[04]00 pipeline
-		tlbwr
-		eret
-
-		/*
-		 * Handle invalid exception
-		 *
-		 * There are two possible causes for an invalid (tlbl)
-		 * exception:
-		 * 1) pages that have the present bit set but the valid bit
-		 *    unset.
-		 * 2) pages that don't exist
-		 * Case one needs fast handling, therefore don't save
-		 * registers yet.
-		 *
-		 * k0 now contains the bad virtual address.
-		 */
-invalid_tlbl:
-		/*
-		 * Remove entry so we don't need to care later
-		 */
-		mfc0	k0,CP0_INDEX
-		lui	k1,0x0008
-		or	k0,k0,k1
-		dsll	k0,k0,13
-		dmtc0	k0,CP0_ENTRYHI
-		dmtc0	zero,CP0_ENTRYLO0
-		dmtc0	zero,CP0_ENTRYLO1
-		/*
-		 * Test whether present bit in entry is set
-		 */
-		dmfc0	k0,CP0_BADVADDR
-		tlbwi						# delayed, for R4[04]00 pipeline
-		srl	k0,k0,10
-		lui	k1,%HI(TLBMAP)
-		addu	k0,k0,k1
-		ori	k0,k0,3
-		xori	k0,k0,3
-		lw	k1,(k0)
-		andi	k1,k1,_PAGE_PRESENT
-		beqz	k1,nopage_tlbl
-		/*
-		 * Present bit is set -> set valid and accessed bits
-		 */
-		lw	k1,(k0)				# delay slot
-		ori	k1,k1,_PAGE_ACCESSED
-		sw	k1,(k0)
-		eret
-
-		/*
-		 * Page doesn't exist. Lots of work which is less important
-		 * for speed needs to be done, so hand it all over to the
-		 * kernel memory management routines.
-		 */
-nopage_tlbl:
-		SAVE_ALL
-		.set	at
-		STI
-		/*
-		 * Create a Intel-style errorcode
-		 * Bit 0: P Present
-		 *        0 == Page not in memory
-		 *        1 == privilege violation
-		 * Bit 1: R/W Read/Write
-		 *        0 == ReadAccess
-		 *        1 == WriteAccess
-		 * Bit 2: U/S User/Supervisor
-		 *        0 == User mode
-		 *        1 == Kernel mode
-		 *
-		 * a0 (struct pt_regs *) regs
-		 * a1 (unsigned long)    error_code
-		 */
-		lw	a1,FR_STATUS(sp)
-		move	a0,sp
-		srl	a1,a1,4
-		andi	a1,a1,1
-		jal	_do_page_fault
-		xori	a1,a1,1				# delay slot
-		j	ret_from_sys_call
-		nop					# delay slot
-
 		.text
-		.globl	_handle_tlbs
-		.align	5
-_handle_tlbs:
-		.set	noreorder
-		.set	noat
-		/*
-		 * It is impossible that is a nested reload exception.
-		 * Therefore this must be a invalid exception.
-		 * Two possible cases:
-		 * 1) Page not used yet
-		 * 2) Page doesn't exist yet. Let the kernel handle the trouble.
-		 *
-		 * Test whether present bit in entry is set
-		 */
-		dmfc0	k0,CP0_BADVADDR
-		srl	k0,k0,10
-		lui	k1,%HI(TLBMAP)
-		addu	k0,k0,k1
-		ori	k0,k0,3
-		xori	k0,k0,3
-		lw	k1,(k0)
-		andi	k1,k1,(_PAGE_PRESENT|_PAGE_RW)
-		beqz	k1,nopage_tlbs
-		/*
-		 * Present and writable bits set -> set accessed and dirty bits.
-		 */
-		lw	k1,(k0)				# delay slot
-		ori	k1,k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
-		sw	k1,(k0)
-		/*
-		 * Now reload the entry into the tlb
-		 */
-		ori	k0,k0,0x1000
-		xori	k0,k0,0x1000
-		lw	k1,4(k0)
-		lw	k0,(k0)
-		srl	k0,k0,6
-		srl	k1,k1,6
-		dmtc0	k0,CP0_ENTRYLO0
-		dmtc0	k1,CP0_ENTRYLO1
-		tlbwi
-		eret
-
-		/*
-		 * Page doesn't exist. Lots of work which is less important
-		 * for speed needs to be done, so hand it all over to the
-		 * kernel memory management routines.
-		 */
-nopage_tlbs:
-nowrite_mod:
-		/*
-		 * Remove entry so we don't need to care later
-		 */
-		mfc0	k0,CP0_INDEX
-		lui	k1,0x0008
-		or	k0,k0,k1
-		dsll	k0,k0,13
-		dmtc0	k0,CP0_ENTRYHI
-		dmtc0	zero,CP0_ENTRYLO0
-		dmtc0	zero,CP0_ENTRYLO1
-		tlbwi
-		SAVE_ALL
-		.set	at
-		STI
-		/*
-		 * Create a Intel-style errorcode
-		 * Bit 0: P Present
-		 *        0 == Page not in memory
-		 *        1 == privilege violation
-		 * Bit 1: R/W Read/Write
-		 *        0 == ReadAccess
-		 *        1 == WriteAccess
-		 * Bit 2: U/S User/Supervisor
-		 *        0 == User mode
-		 *        1 == Kernel mode
-		 *
-		 * a0 (struct pt_regs *) regs
-		 * a1 (unsigned long)    error_code
-		 */
-		lw	a1,FR_STATUS(sp)
-		move	a0,sp
-		srl	a1,a1,4
-		andi	a1,a1,1
-		jal	_do_page_fault
-		xori	a1,a1,3				# branch delay slot
-		j	ret_from_sys_call
-		nop					# branch delay slot
-
-		.globl	_handle_mod
-		.align	5
-_handle_mod:
-		.set	noreorder
-		.set	noat
-		/*
-		 * Two possible cases:
-		 * 1) Page is rw but not dirty -> set dirty and return
-		 * 2) Page is not rw -> call C handler
-		 */
-		dmfc0	k0,CP0_BADVADDR
-		srl	k0,k0,10
-		lui	k1,%HI(TLBMAP)
-		addu	k0,k0,k1
-		ori	k0,k0,3
-		xori	k0,k0,3
-		lw	k1,(k0)
-		andi	k1,k1,_PAGE_RW
-		beqz	k1,nopage_tlbs
-		/*
-		 * Present and writable bits set -> set accessed and dirty bits.
-		 */
-		lw	k1,(k0)				# delay slot
-		ori	k1,k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
-		sw	k1,(k0)
-		/*
-		 * Now reload the entry into the tlb
-		 */
-		ori	k0,k0,0x1000
-		xori	k0,k0,0x1000
-		lw	k1,4(k0)
-		lw	k0,(k0)
-		srl	k0,k0,6
-		srl	k1,k1,6
-		dmtc0	k0,CP0_ENTRYLO0
-		dmtc0	k1,CP0_ENTRYLO1
-		tlbwi
-		eret
-
-		.globl	_handle_adel
-		.align	5
-_handle_adel:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_adel
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_ades
-		.align	5
-_handle_ades:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_ades
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_ibe
-		.align	5
-_handle_ibe:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_ibe
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_dbe
-		.align	5
-_handle_dbe:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_dbe
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_ov
-		.align	5
-_handle_ov:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_ov
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_fpe
-		.align	5
-_handle_fpe:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_fpe
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_bp
-		.align	5
-_handle_bp:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_bp
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_tr
-		.align	5
-_handle_tr:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_tr
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_ri
-		.align	5
-_handle_ri:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_ri
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_cpu
-		.align	5
-_handle_cpu:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_cpu
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
+NESTED(do_syscalls, 32, sp)
+		subu	sp,32
+		sw	ra,28(sp)
+		sll	a2,a2,PTRLOG
+		lw	t0,dst(a2)
+		move	t2,a1
+		jalr	t0
+		lw	t0,FR_REG29(a0)		# get old user stack pointer
 
-		.globl	_handle_vcei
-		.align	5
-_handle_vcei:
+		.set	reorder			# for sake of R3000
+7:		lw	t1,24(t0)		# parameter #7 from usp
+		sw	t1,24(t0)
+6:		lw	t1,20(t0)		# parameter #6 from usp
+		sw	t1,20(t0)
+5:		lw	t1,16(t0)		# parameter #5 from usp
+		sw	t1,16(t0)
+		.set	noreorder
+4:		lw	a3,FR_REG7(a0)		# 4 args
+3:		lw	a2,FR_REG6(a0)		# 3 args
+2:		lw	a1,FR_REG5(a0)		# 2 args
+1:		jalr	t2			# 1 args
+		lw	a0,FR_REG4(a0)		# delay slot
+		.set	reorder
+		lw	ra,28(sp)
+		addiu	sp,32
+		jr	ra
+0:		jalr	t2			# 0 args, just pass a0
+		lw	ra,28(sp)
+		addiu	sp,32
+		jr	ra
+		END(do_syscalls)
 		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_vcei
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
 
-		.globl	_handle_vced
-		.align	5
-_handle_vced:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_vced
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
+		.rdata
+		.align	PTRLOG
+dst:		PTR	0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
 
-		.globl	_handle_watch
-		.align	5
-_handle_watch:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_watch
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
-
-		.globl	_handle_reserved
-		.align	5
-_handle_reserved:
-		.set	noreorder
-		.set	noat
-		SAVE_ALL
-		STI
-		li	t0,-1
-		sw	t0,FR_ORIG_REG2(sp)
-		jal	_do_reserved
-		move	a0,sp			# delay slot
-		j	ret_from_sys_call
-		nop				# delay slot
+/*
+ * Build a default exception handler for the exceptions that don't need
+ * special handlers.  If you didn't know yet - I *like* playing games with
+ * the C preprocessor ...
+ */
+#define __BUILD_silent(exception)
+#define __BUILD_verbose(exception)                                      \
+		la	a1,8f;                                          \
+		TEXT	(#exception);                                   \
+		lw	a2,FR_EPC(sp);                                  \
+		PRINT("Got %s at %08x.\n")
+#define __BUILD_count(exception)                                        \
+		.set	reorder;                                        \
+		lw	t0,exception_count_##exception;                 \
+		addiu	t0,1;                                           \
+		sw	t0,exception_count_##exception;                 \
+		.set	noreorder;                                      \
+		.data;                                                  \
+EXPORT(exception_count_##exception);                                    \
+		.word	0;                                              \
+		.text;
+#define BUILD_HANDLER(exception,verbose)                                \
+		.text;                                                  \
+		.align	5;                                              \
+		NESTED(handle_##exception, FR_SIZE, sp);                \
+		.set	noat;                                           \
+		SAVE_ALL;                                               \
+		STI;                                                    \
+		.set	at;                                             \
+		__BUILD_##verbose(exception);                           \
+		li	t0,-1;                   /* not a sys call */   \
+		sw	t0,FR_ORIG_REG2(sp);                            \
+		jal	do_##exception;                                 \
+		move	a0,sp;                   /* delay slot */       \
+		j	ret_from_sys_call;                              \
+		nop;                             /* delay slot */       \
+		END(handle_##exception)
+
+		BUILD_HANDLER(adel,verbose)		/* #4  */
+		BUILD_HANDLER(ades,verbose)		/* #5  */
+		BUILD_HANDLER(ibe,verbose)		/* #6  */
+		BUILD_HANDLER(dbe,verbose)		/* #7  */
+		BUILD_HANDLER(sys,silent)		/* #8  */
+		BUILD_HANDLER(bp,verbose)		/* #9  */
+		BUILD_HANDLER(ri,verbose)		/* #10 */
+		BUILD_HANDLER(cpu,silent)		/* #11 */
+		BUILD_HANDLER(ov,verbose)		/* #12 */
+		BUILD_HANDLER(tr,verbose)		/* #13 */
+		BUILD_HANDLER(vcei,verbose)		/* #14 */
+		BUILD_HANDLER(fpe,verbose)		/* #15 */
+		BUILD_HANDLER(watch,verbose)		/* #23 */
+		BUILD_HANDLER(vced,verbose)		/* #31 */
+		BUILD_HANDLER(reserved,verbose)		/* others */
 
 /*
  * Exception handler table with 32 entries.
  * This might be extended to handle software exceptions
  */
 		.bss
-		.globl	_exception_handlers
-		.align	2
-_exception_handlers:
-		.fill	32,4,0
+		.align	PTRLOG
+EXPORT(exception_handlers)
+		.fill	32,PTRSIZE,0
+
+/*
+ * Interrupt handler table with 16 entries.
+ */
+EXPORT(IRQ_vectors)
+		.fill	16,PTRSIZE,0
 
 /*
  * Table of syscalls
  */
 		.data
-_sys_call_table:
-		.word	_sys_setup		/* 0 */
-		.word	_sys_exit
-		.word	_sys_fork
-		.word	_sys_read
-		.word	_sys_write
-		.word	_sys_open		/* 5 */
-		.word	_sys_close
-		.word	_sys_waitpid
-		.word	_sys_creat
-		.word	_sys_link
-		.word	_sys_unlink		/* 10 */
-		.word	_sys_execve
-		.word	_sys_chdir
-		.word	_sys_time
-		.word	_sys_mknod
-		.word	_sys_chmod		/* 15 */
-		.word	_sys_chown
-		.word	_sys_break
-		.word	_sys_stat
-		.word	_sys_lseek
-		.word	_sys_getpid		/* 20 */
-		.word	_sys_mount
-		.word	_sys_umount
-		.word	_sys_setuid
-		.word	_sys_getuid
-		.word	_sys_stime		/* 25 */
-		.word	_sys_ptrace
-		.word	_sys_alarm
-		.word	_sys_fstat
-		.word	_sys_pause
-		.word	_sys_utime		/* 30 */
-		.word	_sys_stty
-		.word	_sys_gtty
-		.word	_sys_access
-		.word	_sys_nice
-		.word	_sys_ftime		/* 35 */
-		.word	_sys_sync
-		.word	_sys_kill
-		.word	_sys_rename
-		.word	_sys_mkdir
-		.word	_sys_rmdir		/* 40 */
-		.word	_sys_dup
-		.word	_sys_pipe
-		.word	_sys_times
-		.word	_sys_prof
-		.word	_sys_brk		/* 45 */
-		.word	_sys_setgid
-		.word	_sys_getgid
-		.word	_sys_signal
-		.word	_sys_geteuid
-		.word	_sys_getegid		/* 50 */
-		.word	_sys_acct
-		.word	_sys_phys
-		.word	_sys_lock
-		.word	_sys_ioctl
-		.word	_sys_fcntl		/* 55 */
-		.word	_sys_mpx
-		.word	_sys_setpgid
-		.word	_sys_ulimit
-		.word	_sys_olduname
-		.word	_sys_umask		/* 60 */
-		.word	_sys_chroot
-		.word	_sys_ustat
-		.word	_sys_dup2
-		.word	_sys_getppid
-		.word	_sys_getpgrp		/* 65 */
-		.word	_sys_setsid
-		.word	_sys_sigaction
-		.word	_sys_sgetmask
-		.word	_sys_ssetmask
-		.word	_sys_setreuid		/* 70 */
-		.word	_sys_setregid
-		.word	_sys_sigsuspend
-		.word	_sys_sigpending
-		.word	_sys_sethostname
-		.word	_sys_setrlimit		/* 75 */
-		.word	_sys_getrlimit
-		.word	_sys_getrusage
-		.word	_sys_gettimeofday
-		.word	_sys_settimeofday
-		.word	_sys_getgroups		/* 80 */
-		.word	_sys_setgroups
-		.word	_sys_select
-		.word	_sys_symlink
-		.word	_sys_lstat
-		.word	_sys_readlink		/* 85 */
-		.word	_sys_uselib
-		.word	_sys_swapon
-		.word	_sys_reboot
-		.word	_sys_readdir
-		.word	_sys_mmap		/* 90 */
-		.word	_sys_munmap
-		.word	_sys_truncate
-		.word	_sys_ftruncate
-		.word	_sys_fchmod
-		.word	_sys_fchown		/* 95 */
-		.word	_sys_getpriority
-		.word	_sys_setpriority
-		.word	_sys_profil
-		.word	_sys_statfs
-		.word	_sys_fstatfs		/* 100 */
-		.word	_sys_ioperm
-		.word	_sys_socketcall
-		.word	_sys_syslog
-		.word	_sys_setitimer
-		.word	_sys_getitimer		/* 105 */
-		.word	_sys_newstat
-		.word	_sys_newlstat
-		.word	_sys_newfstat
-		.word	_sys_uname
-		.word	_sys_iopl		/* 110 */
-		.word	_sys_vhangup
-		.word	_sys_idle
-		.word	0 #_sys_vm86
-		.word	_sys_wait4
-		.word	_sys_swapoff		/* 115 */
-		.word	_sys_sysinfo
-		.word	_sys_ipc
-		.word	_sys_fsync
-		.word	_sys_sigreturn
-		.word	_sys_clone		/* 120 */
-		.word	_sys_setdomainname
-		.word	_sys_newuname
-		.word	0 #_sys_modify_ldt
-		.word	_sys_adjtimex
-		.word	_sys_mprotect		/* 125 */
-		.word	_sys_sigprocmask
-		.word	_sys_create_module
-		.word	_sys_init_module
-		.word	_sys_delete_module
-		.word	_sys_get_kernel_syms	/* 130 */
-		.word	_sys_quotactl
-		.word	_sys_getpgid
-		.word	_sys_fchdir
-		.word	_sys_bdflush
-		.word	_sys_sysfs		/* 135 */
-		.word	_sys_personality
-		.word	0			/* for afs_syscall */
-		.word	_sys_setfsuid
-		.word	_sys_setfsgid
-		.word	_sys_llseek		/* 140 */
-		.space	(NR_syscalls-140)*4
+		.align	PTRLOG
+EXPORT(sys_call_table)
+		/*
+		 * Reserved space for all the SVR4, SVR, BSD43 and POSIX
+		 * flavoured syscalls.
+		 */
+		.space	(__NR_Linux)*PTRSIZE
 
-		.bss
-		.globl	_IRQ_vectors
-_IRQ_vectors:	.fill	16,4,0
+		/*
+		 * Linux flavoured syscalls.
+		 */
+#define SYS(call, narg) PTR call
+#include "syscalls.h"
 
+/*
+ * Number of arguments of each syscall
+ */
+EXPORT(sys_narg_table)
+		/*
+		 * Reserved space for all the SVR4, SVR, BSD43 and POSIX
+		 * flavoured syscalls.
+		 */
+		.space	(__NR_Linux)
+
+		/*
+		 * Linux flavoured syscalls.
+		 */
+#undef SYS
+#define SYS(call, narg) .byte narg
+#include "syscalls.h"
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S
--- v1.3.47/linux/arch/mips/kernel/gdb-low.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/gdb-low.S	Wed Dec 13 12:39:43 1995
@@ -0,0 +1,300 @@
+/*
+ * arch/mips/kernel/gdb-low.S
+ *
+ * gdb-low.S contains the low-level trap handler for the GDB stub.
+ *
+ * Copyright (C) 1995 Andreas Busse
+ */
+
+#include <linux/sys.h>
+
+#include <asm/asm.h>
+#include <asm/segment.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsconfig.h>
+#include <asm/stackframe.h>
+#include <asm/gdb-stub.h>
+
+/*
+ * The low level trap handler
+ */
+		.align 	5
+		NESTED(trap_low, GDB_FR_SIZE, sp)
+ 		.set	noat
+		.set 	noreorder
+
+		mfc0	k0,CP0_STATUS
+		sll	k0,3     		/* extract cu0 bit */
+		bltz	k0,1f
+		move	k1,sp
+
+		/*
+		 * Called from user mode, new stack
+		 */
+		lui	k1,%hi(kernelsp)
+		lw	k1,%lo(kernelsp)(k1)
+1:		move	k0,sp
+		subu	sp,k1,GDB_FR_SIZE
+		sw	k0,GDB_FR_REG29(sp)
+		sw	v0,GDB_FR_REG2(sp)
+
+/*
+ * first save the CP0 and special registers
+ */
+
+		mfc0	v0,CP0_STATUS
+		sw	v0,GDB_FR_STATUS(sp)
+		mfc0	v0,CP0_CAUSE
+		sw	v0,GDB_FR_CAUSE(sp)
+		mfc0	v0,CP0_EPC
+		sw	v0,GDB_FR_EPC(sp)
+		mfc0	v0,CP0_BADVADDR
+		sw	v0,GDB_FR_BADVADDR(sp)
+		mfhi	v0
+		sw	v0,GDB_FR_HI(sp)
+		mflo	v0
+		sw	v0,GDB_FR_LO(sp)
+
+/*
+ * Now the integer registers
+ */
+
+		sw	zero,GDB_FR_REG0(sp)		/* I know... */
+		sw	$1,GDB_FR_REG1(sp)
+		/* v0 already saved */
+		sw	v1,GDB_FR_REG3(sp)
+		sw	a0,GDB_FR_REG4(sp)
+		sw	a1,GDB_FR_REG5(sp)
+		sw	a2,GDB_FR_REG6(sp)
+		sw	a3,GDB_FR_REG7(sp)
+		sw	t0,GDB_FR_REG8(sp)
+		sw	t1,GDB_FR_REG9(sp)
+		sw	t2,GDB_FR_REG10(sp)
+		sw	t3,GDB_FR_REG11(sp)
+		sw	t4,GDB_FR_REG12(sp)
+		sw	t5,GDB_FR_REG13(sp)
+		sw	t6,GDB_FR_REG14(sp)
+		sw	t7,GDB_FR_REG15(sp)
+		sw	s0,GDB_FR_REG16(sp)
+		sw	s1,GDB_FR_REG17(sp)
+		sw	s2,GDB_FR_REG18(sp)
+		sw	s3,GDB_FR_REG19(sp)
+		sw	s4,GDB_FR_REG20(sp)
+		sw	s5,GDB_FR_REG21(sp)
+		sw	s6,GDB_FR_REG22(sp)
+		sw	s7,GDB_FR_REG23(sp)
+		sw	t8,GDB_FR_REG24(sp)
+		sw	t9,GDB_FR_REG25(sp)
+		sw	k0,GDB_FR_REG26(sp)
+		sw	k1,GDB_FR_REG27(sp)
+		sw	gp,GDB_FR_REG28(sp)
+		/* sp already saved */
+		sw	fp,GDB_FR_REG30(sp)
+		sw	ra,GDB_FR_REG31(sp)
+
+		STI				/* disable interrupts */
+		
+/*
+ * Followed by the floating point registers
+ */
+		mfc0	v0,CP0_STATUS		/* check if the FPU is enabled */
+		srl	v0,v0,16
+		andi	v0,v0,(ST0_CU1 >> 16)
+		beqz	v0,2f			/* disabled, skip */
+		nop
+
+		swc1	$0,GDB_FR_FPR0(sp)
+		swc1	$1,GDB_FR_FPR1(sp)
+		swc1	$2,GDB_FR_FPR2(sp)
+		swc1	$3,GDB_FR_FPR3(sp)
+		swc1	$4,GDB_FR_FPR4(sp)
+		swc1	$5,GDB_FR_FPR5(sp)
+		swc1	$6,GDB_FR_FPR6(sp)
+		swc1	$7,GDB_FR_FPR7(sp)
+		swc1	$8,GDB_FR_FPR8(sp)
+		swc1	$9,GDB_FR_FPR9(sp)
+		swc1	$10,GDB_FR_FPR10(sp)
+		swc1	$11,GDB_FR_FPR11(sp)
+		swc1	$12,GDB_FR_FPR12(sp)
+		swc1	$13,GDB_FR_FPR13(sp)
+		swc1	$14,GDB_FR_FPR14(sp)
+		swc1	$15,GDB_FR_FPR15(sp)
+		swc1	$16,GDB_FR_FPR16(sp)
+		swc1	$17,GDB_FR_FPR17(sp)
+		swc1	$18,GDB_FR_FPR18(sp)
+		swc1	$19,GDB_FR_FPR19(sp)
+		swc1	$20,GDB_FR_FPR20(sp)
+		swc1	$21,GDB_FR_FPR21(sp)
+		swc1	$22,GDB_FR_FPR22(sp)
+		swc1	$23,GDB_FR_FPR23(sp)
+		swc1	$24,GDB_FR_FPR24(sp)
+		swc1	$25,GDB_FR_FPR25(sp)
+		swc1	$26,GDB_FR_FPR26(sp)
+		swc1	$27,GDB_FR_FPR27(sp)
+		swc1	$28,GDB_FR_FPR28(sp)
+		swc1	$29,GDB_FR_FPR29(sp)
+		swc1	$30,GDB_FR_FPR30(sp)
+		swc1	$31,GDB_FR_FPR31(sp)
+
+/*
+ * FPU control registers
+ */
+
+		mfc1	v0,CP1_STATUS
+		sw	v0,GDB_FR_FSR(sp)
+		mfc1	v0,CP1_REVISION
+		sw	v0,GDB_FR_FIR(sp)
+
+/*
+ * current stack frame ptr
+ */
+
+2:		sw	sp,GDB_FR_FRP(sp)
+
+/*
+ * CP0 registers (R4000/R4400 unused registers skipped)
+ */
+
+		mfc0	v0,CP0_INDEX
+		sw	v0,GDB_FR_CP0_INDEX(sp)
+		mfc0	v0,CP0_RANDOM
+		sw	v0,GDB_FR_CP0_RANDOM(sp)
+		mfc0	v0,CP0_ENTRYLO0
+		sw	v0,GDB_FR_CP0_ENTRYLO0(sp)
+		mfc0	v0,CP0_ENTRYLO1
+		sw	v0,GDB_FR_CP0_ENTRYLO1(sp)
+		mfc0	v0,CP0_PAGEMASK
+		sw	v0,GDB_FR_CP0_PAGEMASK(sp)
+		mfc0	v0,CP0_WIRED
+		sw	v0,GDB_FR_CP0_WIRED(sp)
+		mfc0	v0,CP0_ENTRYHI
+		sw	v0,GDB_FR_CP0_ENTRYHI(sp)
+		mfc0	v0,CP0_PRID
+		sw	v0,GDB_FR_CP0_PRID(sp)
+
+		.set	at
+
+/*
+ * continue with the higher level handler
+ */
+
+		move	a0,sp
+		jal	handle_exception
+		nop
+
+/*
+ * restore all writable registers, in reverse order
+ */
+
+		.set	noat
+
+		lw	v0,GDB_FR_CP0_ENTRYHI(sp)
+		lw	v1,GDB_FR_CP0_WIRED(sp)
+		mtc0	v0,CP0_ENTRYHI
+		mtc0	v1,CP0_WIRED
+		lw	v0,GDB_FR_CP0_PAGEMASK(sp)
+		lw	v1,GDB_FR_CP0_ENTRYLO1(sp)
+		mtc0	v0,CP0_PAGEMASK
+		mtc0	v1,CP0_ENTRYLO1
+		lw	v0,GDB_FR_CP0_ENTRYLO0(sp)
+		lw	v1,GDB_FR_CP0_INDEX(sp)
+		mtc0	v0,CP0_ENTRYLO0
+		mtc0	v1,CP0_INDEX
+
+/*
+ * Next, the floating point registers
+ */
+		mfc0	v0,CP0_STATUS		/* check if the FPU is enabled */
+		srl	v0,v0,16
+		andi	v0,v0,(ST0_CU1 >> 16)
+		beqz	v0,3f			/* disabled, skip */
+		nop
+
+		lwc1	$31,GDB_FR_FPR31(sp)
+		lwc1	$30,GDB_FR_FPR30(sp)
+		lwc1	$29,GDB_FR_FPR29(sp)
+		lwc1	$28,GDB_FR_FPR28(sp)
+		lwc1	$27,GDB_FR_FPR27(sp)
+		lwc1	$26,GDB_FR_FPR26(sp)
+		lwc1	$25,GDB_FR_FPR25(sp)
+		lwc1	$24,GDB_FR_FPR24(sp)
+		lwc1	$23,GDB_FR_FPR23(sp)
+		lwc1	$22,GDB_FR_FPR22(sp)
+		lwc1	$21,GDB_FR_FPR21(sp)
+		lwc1	$20,GDB_FR_FPR20(sp)
+		lwc1	$19,GDB_FR_FPR19(sp)
+		lwc1	$18,GDB_FR_FPR18(sp)
+		lwc1	$17,GDB_FR_FPR17(sp)
+		lwc1	$16,GDB_FR_FPR16(sp)
+		lwc1	$15,GDB_FR_FPR15(sp)
+		lwc1	$14,GDB_FR_FPR14(sp)
+		lwc1	$13,GDB_FR_FPR13(sp)
+		lwc1	$12,GDB_FR_FPR12(sp)
+		lwc1	$11,GDB_FR_FPR11(sp)
+		lwc1	$10,GDB_FR_FPR10(sp)
+		lwc1	$9,GDB_FR_FPR9(sp)
+		lwc1	$8,GDB_FR_FPR8(sp)
+		lwc1	$7,GDB_FR_FPR7(sp)
+		lwc1	$6,GDB_FR_FPR6(sp)
+		lwc1	$5,GDB_FR_FPR5(sp)
+		lwc1	$4,GDB_FR_FPR4(sp)
+		lwc1	$3,GDB_FR_FPR3(sp)
+		lwc1	$2,GDB_FR_FPR2(sp)
+		lwc1	$1,GDB_FR_FPR1(sp)
+		lwc1	$0,GDB_FR_FPR0(sp)
+
+/*
+ * Now the CP0 and integer registers
+ */
+
+3:		mfc0	t0,CP0_STATUS
+		ori	t0,0x1f
+		xori	t0,0x1f
+		mtc0	t0,CP0_STATUS
+
+		lw	v0,GDB_FR_STATUS(sp)
+		lw	v1,GDB_FR_EPC(sp)
+		mtc0	v0,CP0_STATUS
+		mtc0	v1,CP0_EPC
+		lw	v0,GDB_FR_HI(sp)
+		lw	v1,GDB_FR_LO(sp)
+		mthi	v0
+		mtlo	v0
+		lw	ra,GDB_FR_REG31(sp)
+		lw	fp,GDB_FR_REG30(sp)
+		lw	gp,GDB_FR_REG28(sp)
+		lw	k1,GDB_FR_REG27(sp)
+		lw	k0,GDB_FR_REG26(sp)
+		lw	t9,GDB_FR_REG25(sp)
+		lw	t8,GDB_FR_REG24(sp)
+		lw	s7,GDB_FR_REG23(sp)
+		lw	s6,GDB_FR_REG22(sp)
+		lw	s5,GDB_FR_REG21(sp)
+		lw	s4,GDB_FR_REG20(sp)
+		lw	s3,GDB_FR_REG19(sp)
+		lw	s2,GDB_FR_REG18(sp)
+		lw	s1,GDB_FR_REG17(sp)
+		lw	s0,GDB_FR_REG16(sp)
+		lw	t7,GDB_FR_REG15(sp)
+		lw	t6,GDB_FR_REG14(sp)
+		lw	t5,GDB_FR_REG13(sp)
+		lw	t4,GDB_FR_REG12(sp)
+		lw	t3,GDB_FR_REG11(sp)
+		lw	t2,GDB_FR_REG10(sp)
+		lw	t1,GDB_FR_REG9(sp)
+		lw	t0,GDB_FR_REG8(sp)
+		lw	a3,GDB_FR_REG7(sp)
+		lw	a2,GDB_FR_REG6(sp)
+		lw	a1,GDB_FR_REG5(sp)
+		lw	a0,GDB_FR_REG4(sp)
+		lw	v1,GDB_FR_REG3(sp)
+		lw	v0,GDB_FR_REG2(sp)
+		lw	$1,GDB_FR_REG1(sp)
+		lw	sp,GDB_FR_REG29(sp)		/* Deallocate stack */
+
+		ERET
+		.set	at
+		.set	reorder
+		END(trap_low)
+
+/* end of file gdb-low.S */
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c
--- v1.3.47/linux/arch/mips/kernel/gdb-stub.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/gdb-stub.c	Wed Dec 13 12:39:43 1995
@@ -0,0 +1,748 @@
+/*
+ *  arch/mips/kernel/gdb-stub.c
+ *
+ *  Originally written by Glenn Engel, Lake Stevens Instrument Division
+ *
+ *  Contributed by HP Systems
+ *
+ *  Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
+ *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
+ *
+ *  Copyright (C) 1995 Andreas Busse
+ */
+
+/*
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing a BREAK instruction.
+ *
+ *
+ *    The following gdb commands are supported:
+ *
+ * command          function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *
+ *    bBB..BB	    Set baud rate to BB..BB		   OK or BNN, then sets
+ *							   baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/segment.h>
+#include <asm/cachectl.h>
+#include <asm/system.h>
+#include <asm/gdb-stub.h>
+
+/*
+ * external low-level support routines
+ */
+
+extern int putDebugChar(char c);    /* write a single character      */
+extern char getDebugChar(void);     /* read and return a single char */
+extern void fltr_set_mem_err(void);
+extern void trap_low(void);
+
+/*
+ * breakpoint and test functions
+ */
+extern void breakpoint(void);
+extern void breakinst(void);
+extern void adel(void);
+
+/*
+ * local prototypes
+ */
+
+static void getpacket(char *buffer);
+static void putpacket(char *buffer);
+static void set_mem_fault_trap(int enable);
+static int computeSignal(int tt);
+static int hex(unsigned char ch);
+static int hexToInt(char **ptr, int *intValue);
+static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
+void handle_exception(struct gdb_regs *regs);
+static void show_gdbregs(struct gdb_regs *regs);
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+
+static char input_buffer[BUFMAX];
+static char output_buffer[BUFMAX];
+static int initialized = 0;	/* !0 means we've been initialized */
+static const char hexchars[]="0123456789abcdef";
+
+
+/*
+ * Convert ch from a hex digit to an int
+ */
+static int hex(unsigned char ch)
+{
+	if (ch >= 'a' && ch <= 'f')
+		return ch-'a'+10;
+	if (ch >= '0' && ch <= '9')
+		return ch-'0';
+	if (ch >= 'A' && ch <= 'F')
+		return ch-'A'+10;
+	return -1;
+}
+
+/*
+ * scan for the sequence $<data>#<checksum>
+ */
+static void getpacket(char *buffer)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	int i;
+	int count;
+	unsigned char ch;
+
+	do {
+		/*
+		 * wait around for the start character,
+		 * ignore all other characters
+		 */
+		while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+
+		checksum = 0;
+		xmitcsum = -1;
+		count = 0;
+	
+		/*
+		 * now, read until a # or end of buffer is found
+		 */
+		while (count < BUFMAX) {
+			ch = getDebugChar() & 0x7f;
+			if (ch == '#')
+				break;
+			checksum = checksum + ch;
+			buffer[count] = ch;
+			count = count + 1;
+		}
+
+		if (count >= BUFMAX)
+			continue;
+
+		buffer[count] = 0;
+
+		if (ch == '#') {
+			xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+			xmitcsum |= hex(getDebugChar() & 0x7f);
+
+			if (checksum != xmitcsum)
+				putDebugChar('-');	/* failed checksum */
+			else {
+				putDebugChar('+'); /* successful transfer */
+
+				/*
+				 * if a sequence char is present,
+				 * reply the sequence ID
+				 */
+				if (buffer[2] == ':') {
+					putDebugChar(buffer[0]);
+					putDebugChar(buffer[1]);
+
+					/*
+					 * remove sequence chars from buffer
+					 */
+					count = strlen(buffer);
+					for (i=3; i <= count; i++)
+						buffer[i-3] = buffer[i];
+				}
+			}
+		}
+	}
+	while (checksum != xmitcsum);
+}
+
+/*
+ * send the packet in buffer.
+ */
+static void putpacket(char *buffer)
+{
+	unsigned char checksum;
+	int count;
+	unsigned char ch;
+
+	/*
+	 * $<packet info>#<checksum>.
+	 */
+
+	do {
+		putDebugChar('$');
+		checksum = 0;
+		count = 0;
+
+		while ((ch = buffer[count]) != 0) {
+			if (!(putDebugChar(ch)))
+				return;
+			checksum += ch;
+			count += 1;
+		}
+
+		putDebugChar('#');
+		putDebugChar(hexchars[checksum >> 4]);
+		putDebugChar(hexchars[checksum & 0xf]);
+
+	}
+	while ((getDebugChar() & 0x7f) != '+');
+}
+
+
+/*
+ * Indicate to caller of mem2hex or hex2mem that there
+ * has been an error.
+ */
+static volatile int mem_err = 0;
+
+/*
+ * Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ * If MAY_FAULT is non-zero, then we will handle memory faults by returning
+ * a 0, else treat a fault like any other fault in the stub.
+ */
+static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
+{
+	unsigned char ch;
+
+/*	set_mem_fault_trap(may_fault); */
+
+	while (count-- > 0) {
+		ch = *(mem++);
+		if (mem_err)
+			return 0;
+		*buf++ = hexchars[ch >> 4];
+		*buf++ = hexchars[ch & 0xf];
+	}
+
+	*buf = 0;
+
+/*	set_mem_fault_trap(0); */
+
+	return buf;
+}
+
+/*
+ * convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written
+ */
+static char *hex2mem(char *buf, char *mem, int count, int may_fault)
+{
+	int i;
+	unsigned char ch;
+
+/*	set_mem_fault_trap(may_fault); */
+
+	for (i=0; i<count; i++)
+	{
+		ch = hex(*buf++) << 4;
+		ch |= hex(*buf++);
+		*(mem++) = ch;
+		if (mem_err)
+			return 0;
+	}
+
+/*	set_mem_fault_trap(0); */
+
+	return mem;
+}
+
+/*
+ * This table contains the mapping between SPARC hardware trap types, and
+ * signals, which are primarily what GDB understands.  It also indicates
+ * which hardware traps we need to commandeer when initializing the stub.
+ */
+static struct hard_trap_info
+{
+	unsigned char tt;		/* Trap type code for MIPS R3xxx and R4xxx */
+	unsigned char signo;		/* Signal that we map this trap into */
+} hard_trap_info[] = {
+	{ 4, SIGBUS },			/* address error (load) */
+	{ 5, SIGBUS },			/* address error (store) */
+	{ 6, SIGBUS },			/* instruction bus error */
+	{ 7, SIGBUS },			/* data bus error */
+	{ 9, SIGTRAP },			/* break */
+	{ 10, SIGILL },			/* reserved instruction */
+/*	{ 11, SIGILL },		*/	/* cpu unusable */
+	{ 12, SIGFPE },			/* overflow */
+	{ 13, SIGTRAP },		/* trap */
+	{ 14, SIGSEGV },		/* virtual instruction cache coherency */
+	{ 15, SIGFPE },			/* floating point exception */
+	{ 23, SIGSEGV },		/* watch */
+	{ 31, SIGSEGV },		/* virtual data cache coherency */
+	{ 0, 0}				/* Must be last */
+};
+
+
+/*
+ * Set up exception handlers for tracing and breakpoints
+ */
+void set_debug_traps(void)
+{
+	struct hard_trap_info *ht;
+
+	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+		set_except_vector(ht->tt, trap_low);
+  
+	/*
+	 * In case GDB is started before us, ack any packets
+	 * (presumably "$?#xx") sitting there.
+	 */
+
+	putDebugChar ('+');
+	initialized = 1;
+
+	breakpoint();
+}
+
+
+/*
+ * Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
+ * assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
+ * 0 would ever contain code that could mem fault.  This routine will skip
+ * past the faulting instruction after setting mem_err.
+ */
+extern void fltr_set_mem_err(void)
+{
+  /* FIXME: Needs to be written... */
+}
+
+
+static void set_mem_fault_trap(int enable)
+{
+  mem_err = 0;
+
+#if 0
+  if (enable)
+    exceptionHandler(9, fltr_set_mem_err);
+  else
+    exceptionHandler(9, trap_low);
+#endif  
+}
+
+/*
+ * Convert the MIPS hardware trap type code to a unix signal number.
+ */
+static int computeSignal(int tt)
+{
+	struct hard_trap_info *ht;
+
+	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+		if (ht->tt == tt)
+			return ht->signo;
+
+	return SIGHUP;		/* default for things we don't know about */
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+static int hexToInt(char **ptr, int *intValue)
+{
+	int numChars = 0;
+	int hexValue;
+
+	*intValue = 0;
+
+	while (**ptr)
+	{
+		hexValue = hex(**ptr);
+		if (hexValue < 0)
+			break;
+
+		*intValue = (*intValue << 4) | hexValue;
+		numChars ++;
+
+		(*ptr)++;
+	}
+
+	return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.  It
+ * returns 1 if you should skip the instruction at the trap address, 0
+ * otherwise.
+ */
+void handle_exception (struct gdb_regs *regs)
+{
+	int trap;			/* Trap type */
+	int sigval;
+	int addr;
+	int length;
+	char *ptr;
+	unsigned long *stack;
+
+#if 0	
+	printk("in handle_exception()\n");
+	show_gdbregs(regs);
+#endif
+	
+	/*
+	 * First check trap type. If this is CPU_UNUSABLE and CPU_ID is 1,
+	 * the simply switch the FPU on and return since this is no error
+	 * condition. kernel/traps.c does the same.
+	 * FIXME: This doesn't work yet, so we don't catch CPU_UNUSABLE
+	 * traps for now.
+	 */
+	trap = (regs->cp0_cause & 0x7c) >> 2;
+/*	printk("trap=%d\n",trap); */
+	if (trap == 11) {
+		if (((regs->cp0_cause >> CAUSEB_CE) & 3) == 1) {
+			regs->cp0_status |= ST0_CU1;
+			return;
+		}
+	}
+
+	/*
+	 * If we're in breakpoint() increment the PC
+	 */
+	if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst)		
+		regs->cp0_epc += 4;
+
+	stack = (long *)regs->reg29;			/* stack ptr */
+	sigval = computeSignal(trap);
+
+	/*
+	 * reply to host that an exception has occurred
+	 */
+	ptr = output_buffer;
+
+	/*
+	 * Send trap type (converted to signal)
+	 */
+	*ptr++ = 'T';
+	*ptr++ = hexchars[sigval >> 4];
+	*ptr++ = hexchars[sigval & 0xf];
+
+	/*
+	 * Send Error PC
+	 */
+	*ptr++ = hexchars[REG_EPC >> 4];
+	*ptr++ = hexchars[REG_EPC & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex((char *)&regs->cp0_epc, ptr, 4, 0);
+	*ptr++ = ';';
+
+	/*
+	 * Send frame pointer
+	 */
+	*ptr++ = hexchars[REG_FP >> 4];
+	*ptr++ = hexchars[REG_FP & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex((char *)&regs->reg30, ptr, 4, 0);
+	*ptr++ = ';';
+
+	/*
+	 * Send stack pointer
+	 */
+	*ptr++ = hexchars[REG_SP >> 4];
+	*ptr++ = hexchars[REG_SP & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex((char *)&regs->reg29, ptr, 4, 0);
+	*ptr++ = ';';
+
+	*ptr++ = 0;
+	putpacket(output_buffer);	/* send it off... */
+
+	/*
+	 * Wait for input from remote GDB
+	 */
+	while (1) {
+		output_buffer[0] = 0;
+		getpacket(input_buffer);
+
+		switch (input_buffer[0])
+		{
+		case '?':
+			output_buffer[0] = 'S';
+			output_buffer[1] = hexchars[sigval >> 4];
+			output_buffer[2] = hexchars[sigval & 0xf];
+			output_buffer[3] = 0;
+			break;
+
+		case 'd':
+			/* toggle debug flag */
+			break;
+
+		/*
+		 * Return the value of the CPU registers
+		 */
+		case 'g':
+			ptr = output_buffer;
+			ptr = mem2hex((char *)&regs->reg0, ptr, 32*4, 0); /* r0...r31 */
+			ptr = mem2hex((char *)&regs->cp0_status, ptr, 6*4, 0); /* cp0 */
+			ptr = mem2hex((char *)&regs->fpr0, ptr, 32*4, 0); /* f0...31 */
+			ptr = mem2hex((char *)&regs->cp1_fsr, ptr, 2*4, 0); /* cp1 */
+			ptr = mem2hex((char *)&regs->frame_ptr, ptr, 2*4, 0); /* frp */
+			ptr = mem2hex((char *)&regs->cp0_index, ptr, 16*4, 0); /* cp0 */
+			break;
+	  
+		/*
+		 * set the value of the CPU registers - return OK
+		 * FIXME: Needs to be written
+		 */
+		case 'G':
+		{
+#if 0
+			unsigned long *newsp, psr;
+
+			ptr = &input_buffer[1];
+			hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
+
+			/*
+			 * See if the stack pointer has moved. If so, then copy the
+			 * saved locals and ins to the new location.
+			 */
+
+			newsp = (unsigned long *)registers[SP];
+			if (sp != newsp)
+				sp = memcpy(newsp, sp, 16 * 4);
+
+#endif
+			strcpy(output_buffer,"OK");
+		 }
+		break;
+
+		/*
+		 * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
+		 */
+		case 'm':
+			ptr = &input_buffer[1];
+
+			if (hexToInt(&ptr, &addr)
+				&& *ptr++ == ','
+				&& hexToInt(&ptr, &length)) {
+				if (mem2hex((char *)addr, output_buffer, length, 1))
+					break;
+				strcpy (output_buffer, "E03");
+			} else
+				strcpy(output_buffer,"E01");
+			break;
+
+		/*
+		 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
+		 */
+		case 'M': 
+			ptr = &input_buffer[1];
+
+			if (hexToInt(&ptr, &addr)
+				&& *ptr++ == ','
+				&& hexToInt(&ptr, &length)
+				&& *ptr++ == ':') {
+				if (hex2mem(ptr, (char *)addr, length, 1))
+					strcpy(output_buffer, "OK");
+				else
+					strcpy(output_buffer, "E03");
+			}
+			else
+				strcpy(output_buffer, "E02");
+			break;
+
+		/*
+		 * cAA..AA    Continue at address AA..AA(optional)
+		 */
+		case 'c':    
+			/* try to read optional parameter, pc unchanged if no parm */
+
+			ptr = &input_buffer[1];
+			if (hexToInt(&ptr, &addr))
+				regs->cp0_epc = addr;
+	  
+			/*
+			 * Need to flush the instruction cache here, as we may
+			 * have deposited a breakpoint, and the icache probably
+			 * has no way of knowing that a data ref to some location
+			 * may have changed something that is in the instruction
+			 * cache.
+			 * NB: We flush both caches, just to be sure...
+			 */
+
+			sys_cacheflush((void *)KSEG0,KSEG1-KSEG0,BCACHE);
+			return;
+			/* NOTREACHED */
+			break;
+
+
+		/*
+		 * kill the program
+		 */
+		case 'k' :
+			break;		/* do nothing */
+
+
+		/*
+		 * Reset the whole machine (FIXME: system dependent)
+		 */
+		case 'r':
+			break;
+
+
+		/*
+		 * Step to next instruction
+		 * FIXME: Needs to be written
+		 */
+		case 's':
+			strcpy (output_buffer, "S01");
+			break;
+
+		/*
+		 * Set baud rate (bBB)
+		 * FIXME: Needs to be written
+		 */
+		case 'b':
+		{
+#if 0				
+			int baudrate;
+			extern void set_timer_3();
+
+			ptr = &input_buffer[1];
+			if (!hexToInt(&ptr, &baudrate))
+			{
+				strcpy(output_buffer,"B01");
+				break;
+			}
+
+			/* Convert baud rate to uart clock divider */
+
+			switch (baudrate)
+			{
+				case 38400:
+					baudrate = 16;
+					break;
+				case 19200:
+					baudrate = 33;
+					break;
+				case 9600:
+					baudrate = 65;
+					break;
+				default:
+					baudrate = 0;
+					strcpy(output_buffer,"B02");
+					goto x1;
+			}
+
+			if (baudrate) {
+				putpacket("OK");	/* Ack before changing speed */
+				set_timer_3(baudrate); /* Set it */
+			}
+#endif
+		}
+		break;
+
+		}			/* switch */
+
+		/*
+		 * reply to the request
+		 */
+
+		putpacket(output_buffer);
+
+	} /* while */
+}
+
+/*
+ * This function will generate a breakpoint exception.  It is used at the
+ * beginning of a program to sync up with a debugger and can be used
+ * otherwise as a quick means to stop program execution and "break" into
+ * the debugger.
+ */
+void breakpoint(void)
+{
+	if (!initialized)
+		return;
+
+	__asm__ __volatile__("
+			.globl	breakinst
+			.set	noreorder
+			nop
+breakinst:		break
+			nop
+			.set	reorder
+	");
+}
+
+void adel(void)
+{
+	__asm__ __volatile__("
+			.globl	adel
+			la	$8,0x80000001
+			lw	$9,0($8)
+	");
+}
+
+/*
+ * Print registers (on target console)
+ * Used only to debug the stub...
+ */
+void show_gdbregs(struct gdb_regs * regs)
+{
+	/*
+	 * Saved main processor registers
+	 */
+	printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       regs->reg0, regs->reg1, regs->reg2, regs->reg3,
+               regs->reg4, regs->reg5, regs->reg6, regs->reg7);
+	printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       regs->reg8, regs->reg9, regs->reg10, regs->reg11,
+               regs->reg12, regs->reg13, regs->reg14, regs->reg15);
+	printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       regs->reg16, regs->reg17, regs->reg18, regs->reg19,
+               regs->reg20, regs->reg21, regs->reg22, regs->reg23);
+	printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       regs->reg24, regs->reg25, regs->reg26, regs->reg27,
+	       regs->reg28, regs->reg29, regs->reg30, regs->reg31);
+
+	/*
+	 * Saved cp0 registers
+	 */
+	printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
+	       regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S
--- v1.3.47/linux/arch/mips/kernel/head.S	Tue Jan 31 09:39:02 1995
+++ linux/arch/mips/kernel/head.S	Wed Dec 13 12:39:43 1995
@@ -1,47 +1,28 @@
 /*
- *  mips/head.S
+ *  arch/mips/kernel/head.S
  *
- *  Copyright (C) 1994 Waldorf Electronics
+ *  Copyright (C) 1994, 1995 Waldorf Electronics
  *  Written by Ralf Baechle and Andreas Busse
  *
  *  Head.S contains the MIPS exception handler and startup code.
  */
-
-#undef DEBUGPICA /* undef this if you have a different system */
-
 #include <linux/tasks.h>
 
+#include <asm/asm.h>
 #include <asm/segment.h>
 #include <asm/cachectl.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsconfig.h>
 #include <asm/stackframe.h>
-#include <asm/regdef.h>
 #include <asm/bootinfo.h>
-#include <asm/segment.h>
 
 #define PAGE_SIZE	0x1000
 
-/*
- * For now we can't enable write caching. This would cause trouble
- * with the page aliases used by the memory management.
- * The page table's aliases even have to be uncachable, but that
- * doesn't hurt much anyway.
- */
-#define PAGE_TABLE	0x0580  /* uncachable */
-#define PAGE_SHARED	0x0580  /* cachable, writethrough, no write allocate */
+#define MODE_GLOBAL	0x0001	/* shared for all processes */
 #define MODE_ALIAS	0x0016	/* uncachable */
 
-		.globl	_empty_bad_page
-		.globl	_empty_bad_page_table
-		.globl	_pg0
-		.globl	_empty_zero_page
-		.globl	_swapper_pg_dir
-
 		.text
-		.globl	_kernelbase
-_kernelbase:
-
+		.set	mips3
 /*
  * This is space for the interrupt handlers.
  * They are located at virtual address KSEG[01] (physical 0x0)
@@ -51,92 +32,80 @@
 		 */
 		.set	noreorder
 		.set	noat
-except_vec0:
-#if KERNELBASE == KSEG1
-		la	k0,1f
-		jr	k0
-		nop
-1:
-#endif
+		LEAF(except_vec0)
 		dmfc0	k1,CP0_CONTEXT
-		dsra	k1,k1,1
+		dsra	k1,1
 		lwu	k0,(k1)			# May cause another exception
 		lwu	k1,4(k1)
-		dsrl	k0,k0,6			# Convert to EntryLo format
-		dsrl	k1,k1,6			# Convert to EntryLo format
+		dsrl	k0,6			# Convert to EntryLo format
+		dsrl	k1,6			# Convert to EntryLo format
 		dmtc0	k0,CP0_ENTRYLO0
 		dmtc0	k1,CP0_ENTRYLO1
+		nop				# Needed for R4[04]00 pipeline
 		tlbwr
+		nop				# Needed for R4[04]00 pipeline
+		nop
+		nop
+		eret
+		/*
+		 * Workaround for R4000 bug.  For explanation see MIPS
+		 * docs.  Note that this that obscure that it wont almost
+		 * never happen.  Well, but Mips writes about it's bugs.
+		 */
+		nop
 		eret
+		END(except_vec0)
 
 		/*
 		 * XTLB refill, EXL == 0
 		 * Should never be reached
 		 */
 		.org	except_vec0+0x80
-except_vec1:	
-#if KERNELBASE == KSEG1
-		la	k0,1f
-		jr	k0
-		nop
-1:
-#endif
-		la	a0,xtlb_text
-		jal	_panic
-		nop
+		LEAF(except_vec1)
+		PANIC("XTLB Refill exception.\n")
 1:		j	1b
 		nop
-xtlb_text:	.asciz	"XTLB Refill exception.\n"
+		END(except_vec1)
 
 		/*
 		 * Cache Error
 		 */
 		.org	except_vec1+0x80
-except_vec2:
-#if KERNELBASE == KSEG1
-		la	k0,1f
-		jr	k0
-		nop
-1:
-#endif
+		LEAF(except_vec2)
 		/*
-		 * Should never be reached
+		 * Famous last words: unreached
 		 */
-		la	a0,xtlb_text
-		jal	_panic
-		nop
+		mfc0	a1,CP0_ERROREPC
+		PRINT("Cache error exception: c0_errorepc == %08x\n")
 1:		j	1b
 		nop
-cache_text:	.asciz	"Cache error exception\n"
+		END(except_vec2)
 
 		/*
 		 * General exception vector.
 		 */
 		.org	except_vec2+0x80
-except_vec3:	/*
+		NESTED(except_vec3, 0, sp)
+		.set	noat
+		/*
 		 * Register saving is delayed as long as we don't know
 		 * which registers really need to be saved.
 		 */
-#if KERNELBASE == KSEG1
-		la	k0,1f
-		jr	k0
-		nop
-1:
-#endif
-		.set	noat
 		mfc0	k1,CP0_CAUSE
-		la	k0,_exception_handlers
+		la	k0,exception_handlers
 		/*
 		 * Next lines assumes that the used CPU type has max.
 		 * 32 different types of exceptions. We might use this
 		 * to implement software exceptions in the future.
 		 */
-		andi	k1,k1,0x7c
-		addu	k0,k0,k1
+		andi	k1,0x7c
+		addu	k0,k1
 		lw	k0,(k0)
-		FILL_LDS
+		NOP
 		jr	k0
 		nop
+		END(except_vec3)
+		.set	at
 
 /******************************************************************************/
 
@@ -144,88 +113,84 @@
  * Kernel entry
  */
 		.set	noreorder
-		.set	at
-kernel_entry:
-		jal	refill
-		nop
+		NESTED(kernel_entry, 16, sp)
+		/*
+		 * The followin two symbols are used for kernel profiling.
+		 */
+		EXPORT(stext)
+		EXPORT(_stext)
 
+#ifdef CONF_DISABLE_KSEG0_CACHING
+		/*
+		 * Disable all caching for KSEG0.  This option is usefull
+		 * when cache trouble with drivers is suspected
+		 */
+		mfc0	t0,CP0_CONFIG
+		ori	t0,7
+		xori	t0,5
+		mtc0	t0,CP0_CONFIG
+#endif
 		/*
 		 * Clear BSS first so that there are no surprises...
 		 */
-		la	t0,__edata
-		la	t1,__end
+		la	t0,_edata
+		la	t1,_end
 		sw	zero,(t0)
-1:		addiu	t0,t0,4
+1:		addiu	t0,4
 		bnel	t0,t1,1b
 		sw	zero,(t0)
 
-#ifdef DEBUGPICA
-		la      t0,_boot_info
-		lw      t0,OFFSET_BOOTINFO_VRAM_BASE(t0)
-		li      t1,0x0f00 + '3'
-		sh      t1,4(t0)
-#endif
-
-		.set	noreorder
-		jal	_tlbflush
-		mtc0	zero,CP0_WIRED
 		/*
-		 * Spread some mines...
-		 */
-		la	t0,_end
-		la	t1,0x003ffffc
-		la	t2,KERNELBASE
-		or	t1,t2
-		li	t2,0xdeadbeef
-1:		sw	t2,(t0)
-		bne	t0,t1,1b
-		addiu	t0,t0,4
-		/*
-		 * Initialize memory management, map lowest 4MB
-		 */
-		.set	reorder
-		jal	setup_paging
-#if KERNELBASE == KSEG0
-		jal	_sys_cacheflush
-#endif
+		 * Initialize low level part of memory management
+		 * First flush the TLB to make shure that we don't get a
+		 * TLB shutdown during wire_mappings.
+		 */
+		jal	tlbflush
+		mtc0	zero,CP0_WIRED			# delay slot
+		jal	wire_mappings
+		nop
 
-#ifdef DEBUGPICA
-		la      t0,_boot_info
-		lw      t0,OFFSET_BOOTINFO_VRAM_BASE(t0)
-		li      t1,0x0f00 + '4'
-		sh      t1,6(t0)
-#endif
 		/*
 		 * Stack for kernel and init
 		 */
-		la	sp,_init_user_stack+PAGE_SIZE-24
-		sw	sp,_kernelsp
+		la	sp,init_user_stack+PAGE_SIZE-24
+		la	t0,init_kernel_stack+PAGE_SIZE
+		sw	t0,kernelsp
+
+		/*
+		 * Disable coprocessors; set ST0_CU0 to indicate that
+		 * we're running on the kernel stack
+		 */
+		mfc0	t0,CP0_STATUS
+		li	t1,~(ST0_CU1|ST0_CU2|ST0_CU3)
+		and	t0,t1
+		li	t1,ST0_CU0
+		or	t0,ST0_CU0
+		mtc0	t0,CP0_STATUS
 
-1:		jal	_start_kernel
+1:		jal	start_kernel
+		nop					# delay slot
 		/*
 		 * Main should never return here, but
 		 * just in case, we know what happens.
 		 */
-		j	1b
+		b	1b
+		nop					# delay slot
+		END(kernel_entry)
 
 /*
- * Setup_paging
- *
- * Wire mappings for page_tables.
- * The page tables are set up, identity-mapping
- * the first 4MB.  The rest are initialized later.
+ * wire_mappings - used to map hardware registers
  */
-		.set	noreorder
-setup_paging:
+		LEAF(wire_mappings)
 		/*
- 		 * get base address of map0 table for the
+ 		 * Get base address of map0 table for the
 		 * the board we're running on
 		 */
-		la	t0,_boot_info
+		la	t0,boot_info
 		lw	t1,OFFSET_BOOTINFO_MACHTYPE(t0)
-		sll	t1,t1,2			# machtype used as index
 		la	t0,map0table
-		addu	t0,t0,t1
+		sll	t1,PTRLOG		# machtype used as index
+		addu	t0,t1
 		lw	t0,(t0)			# get base address
 
 		/*
@@ -237,20 +202,20 @@
 		addiu	t3,t1,1			# wire one additional entry
 		beqz	t1,2f			# null, exit
 		mtc0	t3,CP0_WIRED		# delay slot
-		addiu	t0,t0,8
+		addiu	t0,8
 1:		lw	t4,24(t0)		# PageMask
 		ld	t5,0(t0)		# entryHi
 		ld	t6,8(t0)		# entryLo0
 		ld	t7,16(t0)		# entryLo1
-		addiu	t2,t2,1			# increment ctr
+		addiu	t2,1			# increment ctr
 		mtc0	t2,CP0_INDEX		# set TLB entry
 		mtc0	t4,CP0_PAGEMASK
 		dmtc0	t5,CP0_ENTRYHI
 		dmtc0	t6,CP0_ENTRYLO0
 		dmtc0	t7,CP0_ENTRYLO1
- 		tlbwi 
+		addiu	t0,32
 		bne	t1,t2,1b		# next TLB entry
-		addiu	t0,t0,32		# delay slot
+ 		tlbwi 				# delay slot
 
 		/*
 		 * We use only 4k pages. Therefore the PageMask register
@@ -259,182 +224,45 @@
 2:		li	t0,PM_4K
 		mtc0	t0,CP0_PAGEMASK
 
-		la	t1,_swapper_pg_dir	# swapper_pg_dir is at 0x1000
-		la	t2,_swapper_pg_dir+(PAGE_SIZE-4)
-1:		sw	zero,(t1)
-		bne	t1,t2,1b
-		addiu	t1,t1,4			# delay slot
-
-		/*
-		 * Setup invalid_pg_table and
-		 * clear page table for the first 4MB
-		 */
-		la	t0,_pg0			# swapper_pg_dir is at 0x1000
-		la	t1,_pg0+PAGE_SIZE
-		li	t2,KERNELBASE
-		addu	t0,t2
-		addu	t1,t2
-1:		sw	zero,(t0)
-		addiu	t0,t0,4
-		bne	t0,t1,1b
-		addiu	t2,t2,4			# delay slot
-
-		/*
-		 * Identity-map the kernel in low 4MB memory for ease
-		 * of transition. Unlike the Intel version the kernel
-		 * code/data is automagically being mapped by kseg0.
-		 */
-		la	t0,_pg0+PAGE_TABLE	# set valid bit/user r/w
-		sw	t0,_swapper_pg_dir
-
-		li	t0,PAGE_SHARED		# set valid bit/user r/w
-		la	t1,_pg0
-		la	t2,_pg0+PAGE_SIZE
-		li	t3,KERNELBASE
-		addu	t1,t3
-		addu	t2,t3
-1:		sw	t0,(t1)
-		addiu	t1,t1,4
-		bne	t1,t2,1b
-		addiu	t0,t0,PAGE_SIZE		# delay slot
-
 		/*
 		 * Now map the pagetables
 		 */
 		mtc0	zero,CP0_INDEX
 		la	t0,TLB_ROOT
 		dmtc0	t0,CP0_ENTRYHI
-		la	t0,_swapper_pg_dir
-		srl	t0,t0,6
-		ori	t0,t0,MODE_ALIAS	# uncachable, dirty, valid
+		la	t0,swapper_pg_dir-KSEG1
+		srl	t0,6
+		ori	t0,(MODE_ALIAS|MODE_GLOBAL) # uncachable, dirty, valid
 		dmtc0	t0,CP0_ENTRYLO0
-		dmtc0	zero,CP0_ENTRYLO1
-		tlbwi
-		/*
-		 * Make page zero unaccessible to catch zero references
-		 */
-		la	t0,_pg0
-		li	t0,KERNELBASE
-		addu	t0,t1
-		sw	zero,(t0)
+		li	t0,MODE_GLOBAL
+		dmtc0	t0,CP0_ENTRYLO1
+		nop
+		tlbwi				# delayed
+
 		/*
 		 * Load the context register with a value that allows
 		 * it to be used as fast as possible in tlb exceptions.
-		 * It is expected that this register's content never
-		 * will be changed.
+		 * It is expected that this register's content will
+		 * NEVER be changed.
 		 */
 		li	t0,TLBMAP
-		dsll	t0,t0,1
-		jr	ra
-		dmtc0	t0,CP0_CONTEXT		# delay slot
-
-		/*
-		 * Flush the TLB
-		 *
-		 * FIXME: knows only how to handle R4x00
-		 * Read appendix f of the R4000 manual before you change
-		 * something!
-		 */
-		.globl	_tlbflush
-_tlbflush:	li	t0,PM_4K
-		mtc0	t0,CP0_PAGEMASK
-		lw	t0,_boot_info+OFFSET_BOOTINFO_TLB_ENTRIES(t0)
-		dmtc0	zero,CP0_ENTRYLO0
-		dmtc0	zero,CP0_ENTRYLO1
-		mfc0	t2,CP0_WIRED
-1:		subu	t0,t0,1
-		mtc0	t0,CP0_INDEX
-		lui	t1,0x0008
-		or	t1,t0,t1
-		dsll	t1,t1,13
-		dmtc0	t1,CP0_ENTRYHI
-		bne	t2,t0,1b
-		tlbwi					# delay slot
-		jr	ra
-		nop
-
-/*
- * Refill icache
- */
-#include <asm/mipsconfig.h>
-#include <asm/regdef.h>
-#include <asm/segment.h>
-
-#define PAGE_SIZE	0x1000
-
-#define CACHELINES	512             /* number of cachelines    */
-
-		.set	noreorder
-		.text
-refill:
-		/*
-		 * Refill icache with cache fill command
-		 */
-		li	t0,KSEG0
-		li	t1,CACHELINES
-1:		cache	21,0(t0)
-		cache	21,32(t0)
-		cache	21,64(t0)
-		cache	21,96(t0)
-		cache	21,128(t0)
-		cache	21,160(t0)
-		cache	21,192(t0)
-		cache	21,224(t0)
-		cache	21,256(t0)
-		cache	21,288(t0)
-		cache	21,320(t0)
-		cache	21,352(t0)
-		cache	21,384(t0)
-		cache	21,416(t0)
-		cache	21,448(t0)
-		cache	21,480(t0)
-		subu    t1,t1,1
-		bnez	t1,1b
-		addiu	t0,t0,512			# delay slot
-
-		jr	ra
-		nop
-
-/*
- * Just for debugging...
- */
-		.globl	_beep
-_beep:		lw	t0,beepflag
-		nop
-		bnez	t0,1f
-		lbu	t0,0xe0000061
-		xori	t0,t0,3
-		sb	t0,0xe0000061
-		li	t0,1
-		sw	t0,beepflag
-1:		jr	ra
+		dsll	t0,1
+		dmtc0	t0,CP0_CONTEXT
+		jr	ra			# delay slot
 		nop
+		END(wire_mappings)
 
+		.data
 /*
- * Compute kernel code checksum to check kernel code against corruption
+ * Build an entry for table of wired entries
  */
-		.globl	_csum
-#if 0
-_csum:		jal	_sys_cacheflush
-		move	t8,ra			# delay slot
-#else
-_csum:		move	t8,ra
-#endif
-		li	t0,KSEG1
-		la	t1,final
-		li	t2,KSEG1
-		or	t0,t2
-		or	t1,t2
-		move	v0,zero
-1:		lw	t2,(t0)
-		addiu	t0,t0,4
-		bne	t0,t1,1b
-		xor	v0,v0,t2
-		jr	t8
-		nop
-final:
+#define MAPDATA(q1,q2,q3,w1)                                    \
+		.quad	q1;                                     \
+		.quad	q2;                                     \
+		.quad	q3;                                     \
+		.word	w1;                                     \
+		.word	0
 
-		.data
 /*
  * Initial mapping tables for supported Mips boards.
  * First item is always the number of wired TLB entries,
@@ -449,288 +277,104 @@
  * target system in bootinfo.h
  */
 
-map0table:	.word	map0_dummy		# machtype = unknown
-		.word	map0_tyne		# Deskstation Tyne
-		.word	map0_pica61		# Acer Pica-61
+map0table:	PTR	map0_dummy		# machtype = unknown
+		PTR	map0_rpc		# Deskstation rPC44
+		PTR	map0_tyne		# Deskstation Tyne
+		PTR	map0_pica61		# Acer Pica-61
+		PTR	map0_magnum4000		# MIPS Magnum 4000PC (RC4030)
 
 map0_dummy:	.word	0			# 0 entries
 
+		.align  3
 /*
- * Initial mappings for Deskstation Tyne boards.
+ * Initial mappings for Deskstation rPC boards.
+ * RB: Untested goodie - I don't have such a board.
  */
-		.align  8
-
-map0_tyne: 	.word   3			# no. of wired TLB entries
+map0_rpc: 	.word   2			# no. of wired TLB entries
 		.word	0			# pad for alignment
 
-# TLB entry 1: ISA I/O
+MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M)	# VESA DMA cache
+MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M)	# VESA I/O and memory space
 
-		.quad	0xffffffffe0000000	# TLB #0 EntryHi
-		.quad   0x24000017		# TLB #0 EntryLo0
-		.quad	0			# TLB #0 EntryLo1
-		.word   PM_64K			# page mask
-		.word   0			# pad for alignment
-
-# TLB entry 2: ISA memory space
-
-		.quad	0xffffffffe1000000	# TLB #1 EntryHi
-		.quad   0x04000017		# TLB #1 EntryLo0
-		.quad	0			# TLB #1 EntryLo1
-		.word   PM_1M
+/*
+ * Initial mappings for Deskstation Tyne boards.
+ */
+map0_tyne: 	.word   2			# no. of wired TLB entries
 		.word	0			# pad for alignment
 
-# TLB entry 3: ISA DMA cache
-
-		.quad	0xffffffffe2000000	# TLB #2 EntryHi
-		.quad 	0x04020017		# TLB #2 EntryLo0
-		.quad	0			# TLB #2 EntryLo1
-		.word	PM_1M
-		.word 	0			# pad for alignment
+MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M)	# VESA DMA cache
+MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M)	# VESA I/O and memory space
 
 /*
  * Initial mapping for ACER PICA-61 boards.
- * FIXME: These are rather preliminary since many drivers,
- * such as serial, parallel, scsi and ethernet need some
- * changes to distinguish between "local" (built-in) and
- * "optional" (ISA/PCI) I/O hardware.
- * Local video ram is mapped to the same location as the
- * bios maps it to. Console driver has been changed
+ * FIXME: These are rather preliminary since many drivers, such as serial,
+ * parallel, scsi and ethernet need some changes to distinguish between "local"
+ * (built-in) and "optional" (ISA/PCI) I/O hardware. Local video ram is mapped
+ * to the same location as the bios maps it to. Console driver has been changed
  * accordingly (new video type: VIDEO_TYPE_PICA_S3).
+ * FIXME: Remove or merge some of the mappings.
  */
-
-map0_pica61:	.word  	9			# no. wired TLB entries
+map0_pica61:	.word  	7			# no. wired TLB entries
 		.word	0			# dummy
 
-# TLB entry 1: PROM
-
-#		.quad	0xffffffffe1000000	# BIOS mapping
-		.quad	0xffffffffe4000000	# new mapping
-		.quad	0x03ffc013
-		.quad	0x00000001		# global, not valid
-		.word	PM_256K
-		.word	0
-
-# TLB entry 2: local I/O space
-
-		.quad   0xffffffffe0000000
-		.quad 	0x02000017
-		.quad	0x00000001		# global, not valid
-		.word	PM_64K
-		.word	0
-
-# TLB entry 3: DRAM config register
-
-		.quad	0xffffffffe00e0000
-		.quad	0x02003817
-		.quad	0x02003c17
-		.word	PM_64K
-		.word	0
-
-# TLB entry 4: Interrupt source register
-
-		.quad	0xffffffffe0100000
-		.quad	0x03c00017
-		.quad	0x00000001		# global, not valid
-		.word	PM_4K
-		.word	0
-
-# TLB entry 5: Local video control
-
-		.quad	0xffffffffe0200000
-		.quad	0x01800017
-		.quad	0x01804017
-		.word	PM_1M
-		.word	0
-
-# TLB entry 6: Extended video control
-
-		.quad	0xffffffffe0400000
-		.quad	0x01808017
-		.quad	0x0180c017
-		.word	PM_1M
-		.word	0
-
-# TLB entry 7: Local video memory (BIOS mapping)
-
-		.quad	0xffffffffe0800000
-		.quad	0x01000017
-		.quad	0x01010017
-		.word   PM_4M
-		.word	0
-
-# TLB entry 8: Local video memory (mapped to where Linux expects it)
-# not needed anymore
-#		.quad	0xffffffffe1000000
-#		.quad	0x01000017
-#		.quad	0x01010017
-#		.word   PM_4M
-#		.word	0
-
-# TLB entry 9: ISA I/O and ISA memory space (both 16M)
-
-		.quad	0xffffffffe2000000
-		.quad	0x02400017
-		.quad	0x02440017
-		.word	PM_16M
-		.word	0
-
-# TLB entry 10: PCR (???)
-
-		.quad	0xffffffffffffe000
-		.quad	0x00000001		# nonsense...
-		.quad	0x0001ffd7
-		.word	PM_4K
-		.word	0
-
+MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K)	# Local I/O space
+MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K)	# Interrupt source register
+MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M)	# Local video control
+MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M)	# Extended video control
+MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M)	# Local video memory (BIOS mapping)
+MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M)	# ISA I/O and ISA memory space (both 16M)
+MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K)	# PCR (???)
+
+/*
+ * Initial mapping for Mips Magnum 4000PC systems.
+ * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-)
+ * FIXME: Remove or merge some of the mappings.
+ */
 
-/* ------------------------------------------------
- * Mapping as presented by the PICA BIOS.
- * This table works. Please leave unmodified!
- * ------------------------------------------------ */
-#if 0
-map0_pica61:	.word	11			# no. wired TLB entries
+map0_magnum4000:
+		.word  	8			# no. wired TLB entries
 		.word	0			# dummy
 
-# TLB entry 0: Don't know what this is good for...
-
-		.quad	0xfffffffffffe2000
-		.quad	0x0000029e
-		.quad	0x00000000
-		.word	PM_4K
-		.word	0
-
-# TLB entry 1: PROM
-
-		.quad	0xffffffffe1000000
-		.quad	0x03ffc013
-		.quad	0x00000001		# nonsense ...
-		.word	PM_256K
-		.word	0
-
-# TLB entry 2: local I/O space
-
-		.quad   0xffffffffe0000000
-		.quad 	0x02000017
-		.quad	0x00000001		# nonsense ...
-		.word	PM_64K
-		.word	0
-
-# TLB entry 3: DRAM config register
-
-		.quad	0xffffffffe00e0000
-		.quad	0x02003817
-		.quad	0x02003c17
-		.word	PM_64K
-		.word	0
-
-# TLB entry 4: Interrupt source register
-
-		.quad	0xffffffffe0100000
-		.quad	0x03c00017
-		.quad	0x00000001		# nonsense ...
-		.word	PM_4K
-		.word	0
-
-# TLB entry 5: Local video control
-
-		.quad	0xffffffffe0200000
-		.quad	0x01800017
-		.quad	0x01804017
-		.word	PM_1M
-		.word	0
-
-# TLB entry 6: Extended video control
-
-		.quad	0xffffffffe0400000
-		.quad	0x01808017
-		.quad	0x0180c017
-		.word	PM_1M
-		.word	0
-
-# TLB entry 7: Local video memory
-
-		.quad	0xffffffffe0800000
-		.quad	0x01000017
-		.quad	0x01010017
-		.word   PM_4M
-		.word	0
-
-# TLB entry 8: ISA I/O space
-
-		.quad	0xffffffffe2000000
-		.quad	0x02400017
-		.quad	0x02440017
-		.word	PM_16M
-		.word	0
-
-# TLB entry 9: PCR (???)
+MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, 0x7e000)	# 0
+MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, 0x1e000)	# 1 local I/O
+MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, 0)		# 2 IRQ source
+MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, 0x1fe000)	# 3 local video ctrl
+MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, 0x1fe000)	# 4 ext. video ctrl
+MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, 0x7fe000)	# 5 local video mem.
+MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, 0x1ffe000)	# 6 ISA I/O and mem.
+MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, 0)		# 7 PCR
 
-		.quad	0xffffffffffffe000
-		.quad	0x00000001		# nonsense...
-		.quad	0x0001ffd7
-		.word	PM_4K
-		.word	0
-
-# TLB entry 10: Extended video prom
-
-		.quad	0xffffffff10000000
-		.quad	0x0000141f
-		.quad	0x00000001		# nonsense
-		.word   PM_64K
-		.word	0
-#endif
 
-/*
- * 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.....
- */
 			.text
 
 			.org	0x1000
-_swapper_pg_dir		=	0x1000
+			.globl	swapper_pg_dir
+swapper_pg_dir		=	. + (KSEG1-KSEG0)
+
 /*
  * The page tables are initialized to only 4MB here - the final page
  * tables are set up later depending on memory size.
  */
 			.org	0x2000
-_pg0			=	0x2000
+			EXPORT(pg0)
 
 			.org	0x3000
-_empty_bad_page		=	0x3000
+			EXPORT(empty_bad_page)
 
 			.org	0x4000
-_empty_bad_page_table	=	0x4000
+			EXPORT(empty_bad_page_table)
 
 			.org	0x5000
-_empty_zero_page	=	0x5000
+			EXPORT(empty_zero_page)
 
 			.org	0x6000
+			EXPORT(invalid_pte_table)
 
-#if defined (CONFIG_DESKSTATION_TYNE) && !defined (CONFIG_ACER_PICA_61)
-#if 0
-/*
- * tmp_floppy_area is used by the floppy-driver when DMA cannot
- * reach to a buffer-block. It needs to be aligned, so that it isn't
- * on a 64kB border.
- */
-			.globl	_tmp_floppy_area
-_tmp_floppy_area:	.fill	1024,1,0
-#endif
-/*
- * 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).
- */
-			.globl	_floppy_track_buffer
-_floppy_track_buffer:	.fill	512*2*36,1,0
-#endif /* defined (CONFIG_DESKSTATION_TYNE) && !defined (CONFIG_ACER_PICA_61) */
-			.globl	_kernelsp
-_kernelsp:		.word	0
-beepflag:		.word	0
+			.org	0x7000
+
+			EXPORT(cache_error_buffer)
+			.fill	32*4,1,0
+
+			.data
+			EXPORT(kernelsp)
+			PTR	0
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/ioport.c linux/arch/mips/kernel/ioport.c
--- v1.3.47/linux/arch/mips/kernel/ioport.c	Wed Jan 18 08:54:13 1995
+++ linux/arch/mips/kernel/ioport.c	Wed Dec 13 12:39:43 1995
@@ -7,50 +7,8 @@
 #include <linux/types.h>
 #include <linux/ioport.h>
 
-#define IOTABLE_SIZE 32
-
-typedef struct resource_entry_t {
-	u_long from, num;
-	const char *name;
-	struct resource_entry_t *next;
-} resource_entry_t;
-
-/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
-static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
-{
-	int mask;
-	unsigned long *bitmap_base = bitmap + (base >> 5);
-	unsigned short low_index = base & 0x1f;
-	int length = low_index + extent;
-
-	if (low_index != 0) {
-		mask = (~0 << low_index);
-		if (length < 32)
-				mask &= ~(~0 << length);
-		if (new_value)
-			*bitmap_base++ |= mask;
-		else
-			*bitmap_base++ &= ~mask;
-		length -= 32;
-	}
-
-	mask = (new_value ? ~0 : 0);
-	while (length >= 32) {
-		*bitmap_base++ = mask;
-		length -= 32;
-	}
-
-	if (length > 0) {
-		mask = ~(~0 << length);
-		if (new_value)
-			*bitmap_base++ |= mask;
-		else
-			*bitmap_base++ &= ~mask;
-	}
-}
-
 /*
- * this changes the io permissions bitmap in the current task.
+ * This changes the io permissions bitmap in the current task.
  */
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
@@ -75,29 +33,4 @@
 	     long eip,long cs,long eflags,long esp,long ss)
 {
 	return -ENOSYS;
-}
-
-/*
- * The workhorse function: find where to put a new entry
- */
-static resource_entry_t *find_gap(resource_entry_t *root,
-				  u_long from, u_long num)
-{
-	unsigned long flags;
-	resource_entry_t *p;
-	
-	if (from > from+num-1)
-		return NULL;
-	save_flags(flags);
-	cli();
-	for (p = root; ; p = p->next) {
-		if ((p != root) && (p->from+p->num-1 >= from)) {
-			p = NULL;
-			break;
-		}
-		if ((p->next == NULL) || (p->next->from > from+num-1))
-			break;
-	}
-	restore_flags(flags);
-	return p;
 }
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/ipc.c linux/arch/mips/kernel/ipc.c
--- v1.3.47/linux/arch/mips/kernel/ipc.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/ipc.c	Wed Dec 13 12:39:43 1995
@@ -0,0 +1,113 @@
+/*
+ * linux/arch/mips/kernel/ipc.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/i386
+ * platform.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+
+#include <asm/segment.h>
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly;  removing this will need some minor
+ * changes in libc.
+ */
+asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
+{
+#ifdef CONFIG_SYSVIPC
+	int version;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	if (call <= SEMCTL)
+		switch (call) {
+		case SEMOP:
+			return sys_semop (first, (struct sembuf *)ptr, second);
+		case SEMGET:
+			return sys_semget (first, second, third);
+		case SEMCTL: {
+			union semun fourth;
+			int err;
+			if (!ptr)
+				return -EINVAL;
+			if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
+				return err;
+			fourth.__pad = (void *) get_fs_long(ptr);
+			return sys_semctl (first, second, third, fourth);
+			}
+		default:
+			return -EINVAL;
+		}
+	if (call <= MSGCTL) 
+		switch (call) {
+		case MSGSND:
+			return sys_msgsnd (first, (struct msgbuf *) ptr, 
+					   second, third);
+		case MSGRCV:
+			switch (version) {
+			case 0: {
+				struct ipc_kludge tmp;
+				int err;
+				if (!ptr)
+					return -EINVAL;
+				if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
+					return err;
+				memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
+					       sizeof (tmp));
+				return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+				}
+			case 1: default:
+				return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+			}
+		case MSGGET:
+			return sys_msgget ((key_t) first, second);
+		case MSGCTL:
+			return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+		default:
+			return -EINVAL;
+		}
+	if (call <= SHMCTL) 
+		switch (call) {
+		case SHMAT:
+			switch (version) {
+			case 0: default: {
+				ulong raddr;
+				int err;
+				if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
+					return err;
+				err = sys_shmat (first, (char *) ptr, second, &raddr);
+				if (err)
+					return err;
+				put_fs_long (raddr, (ulong *) third);
+				return 0;
+				}
+			case 1:	/* iBCS2 emulator entry point */
+				if (get_fs() != get_ds())
+					return -EINVAL;
+				return sys_shmat (first, (char *) ptr, second, (ulong *) third);
+			}
+		case SHMDT: 
+			return sys_shmdt ((char *)ptr);
+		case SHMGET:
+			return sys_shmget (first, second, third);
+		case SHMCTL:
+			return sys_shmctl (first, second, (struct shmid_ds *) ptr);
+		default:
+			return -EINVAL;
+		}
+	return -EINVAL;
+#else /* CONFIG_SYSVIPC */
+	return -ENOSYS;
+#endif /* CONFIG_SYSVIPC */
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
--- v1.3.47/linux/arch/mips/kernel/irq.c	Tue Jan 31 09:39:02 1995
+++ linux/arch/mips/kernel/irq.c	Wed Dec 13 12:39:43 1995
@@ -16,6 +16,8 @@
  */
 
 /*
+ * Mips support by Ralf Baechle and Andreas Busse
+ *
  * The Deskstation Tyne is almost completely like an IBM compatible PC with
  * another type of microprocessor. Therefore this code is almost completely
  * the same. More work needs to be done to support Acer PICA and other
@@ -27,13 +29,18 @@
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
+#include <linux/random.h>
 
-#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/bitops.h>
+#include <asm/jazz.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
 
 unsigned char cache_21 = 0xff;
 unsigned char cache_A1 = 0xff;
@@ -117,7 +124,7 @@
 	for (i = 0 ; i < 16 ; i++, action++) {
 		if (!action->handler)
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s\n",
+		len += sprintf(buf+len, "%3d: %8d %c %s\n",
 			i, kstat.interrupts[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
@@ -137,6 +144,8 @@
 	struct irqaction * action = irq + irq_action;
 
 	kstat.interrupts[irq]++;
+	if (action->flags & SA_SAMPLE_RANDOM)
+		add_interrupt_randomness(irq);
 	action->handler(irq, regs);
 }
 
@@ -150,6 +159,8 @@
 	struct irqaction * action = irq + irq_action;
 
 	kstat.interrupts[irq]++;
+	if (action->flags & SA_SAMPLE_RANDOM)
+		add_interrupt_randomness(irq);
 	action->handler(irq, NULL);
 }
 
@@ -168,6 +179,8 @@
 		return -EBUSY;
 	if (!handler)
 		return -EINVAL;
+	if (irqflags & SA_SAMPLE_RANDOM)
+		rand_initialize_irq(irq);
 	save_flags(flags);
 	cli();
 	action->handler = handler;
@@ -179,9 +192,9 @@
 		 * FIXME: Does the SA_INTERRUPT flag make any sense on MIPS???
 		 */
 		if (action->flags & SA_INTERRUPT)
-			set_intr_gate(irq,fast_interrupt);
+			set_int_vector(irq,fast_interrupt);
 		else
-			set_intr_gate(irq,interrupt);
+			set_int_vector(irq,interrupt);
 	}
 	if (irq < 8) {
 		cache_21 &= ~(1<<irq);
@@ -218,7 +231,7 @@
 		cache_A1 |= 1 << (irq-8);
 		outb(cache_A1,0xA1);
 	}
-	set_intr_gate(irq,bad_interrupt);
+	set_int_vector(irq,bad_interrupt);
 	action->handler = NULL;
 	action->flags = 0;
 	action->mask = 0;
@@ -228,7 +241,7 @@
 
 static void no_action(int cpl, struct pt_regs * regs) { }
 
-unsigned int probe_irq_on (void)
+unsigned long probe_irq_on (void)
 {
 	unsigned int i, irqs = 0, irqmask;
 	unsigned long delay;
@@ -258,7 +271,7 @@
 	return irqs;
 }
 
-int probe_irq_off (unsigned int irqs)
+int probe_irq_off (unsigned long irqs)
 {
 	unsigned int i, irqmask;
 
@@ -284,14 +297,35 @@
 {
 	int i;
 
-	/* set the clock to 100 Hz */
-	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
-	outb_p(LATCH & 0xff , 0x40);	/* LSB */
-	outb(LATCH >> 8 , 0x40);	/* MSB */
+	switch (boot_info.machtype) {
+		case MACH_MIPS_MAGNUM_4000:
+		case MACH_ACER_PICA_61:
+	                r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+					  JAZZ_IE_ETHERNET |
+					  JAZZ_IE_SERIAL1  |
+					  JAZZ_IE_SERIAL2  |
+ 					  JAZZ_IE_PARALLEL |
+					  JAZZ_IE_FLOPPY);
+	                r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */
+			set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ1);
+			/* set the clock to 100 Hz */
+			r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
+			break;
+		case MACH_DESKSTATION_TYNE:
+			/* set the clock to 100 Hz */
+			outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
+			outb_p(LATCH & 0xff , 0x40);	/* LSB */
+			outb(LATCH >> 8 , 0x40);	/* MSB */
+
+			if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
+				printk("Unable to get IRQ2 for cascade\n");
+			break;
+		default:
+			panic("Unknown machtype in init_IRQ");
+	}
+
 	for (i = 0; i < 16 ; i++)
-		set_intr_gate(i, bad_interrupt);
-	if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
-		printk("Unable to get IRQ2 for cascade\n");
+		set_int_vector(i, bad_interrupt);
 
 	/* initialize the bottom half routines. */
 	for (i = 0; i < 32; i++) {
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/jazz-c.c linux/arch/mips/kernel/jazz-c.c
--- v1.3.47/linux/arch/mips/kernel/jazz-c.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/jazz-c.c	Wed Dec 13 12:39:43 1995
@@ -0,0 +1,99 @@
+/*
+ * Jazz specific C parts
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#include <linux/delay.h>
+
+#include <asm/cachectl.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <asm/segment.h>
+
+unsigned char jazz_fd_inb(unsigned int port)
+{
+	unsigned char c;
+
+	c = *(volatile unsigned char *) port;
+	udelay(1);
+
+	return c;
+}
+
+void jazz_fd_outb(unsigned char value, unsigned int port)
+{
+	*(volatile unsigned char *) port = value;
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+void jazz_fd_enable_dma(void)
+{
+	vdma_enable(JAZZ_FLOPPY_DMA);
+}
+
+void jazz_fd_disable_dma(void)
+{
+	vdma_disable(JAZZ_FLOPPY_DMA);
+}
+
+int jazz_fd_request_dma(void)
+{
+	return 0;
+}
+
+void jazz_fd_free_dma(void)
+{
+}
+
+void jazz_fd_clear_dma_ff(void)
+{
+}
+
+void jazz_fd_set_dma_mode(char mode)
+{
+	vdma_set_mode(JAZZ_FLOPPY_DMA, mode);
+}
+
+void jazz_fd_set_dma_addr(unsigned int a)
+{
+	vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(PHYSADDR(a)));
+}
+
+void jazz_fd_set_dma_count(unsigned int count)
+{
+	vdma_set_count(JAZZ_FLOPPY_DMA, count);
+}
+
+int jazz_fd_get_dma_residue(void)
+{
+	return vdma_get_residue(JAZZ_FLOPPY_DMA);
+}
+
+void jazz_fd_enable_irq(void)
+{
+}
+
+void jazz_fd_disable_irq(void)
+{
+}
+
+void jazz_fd_cacheflush(unsigned char *addr, unsigned int size)
+{
+	sys_cacheflush((void *)addr, size, DCACHE);
+}
+
+unsigned char jazz_rtc_read_data(void)
+{
+	return *(char *)JAZZ_RTC_BASE;
+}
+
+void jazz_rtc_write_data(unsigned char data)
+{
+	*(char *)JAZZ_RTC_BASE = data;
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/jazzdma.c linux/arch/mips/kernel/jazzdma.c
--- v1.3.47/linux/arch/mips/kernel/jazzdma.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/jazzdma.c	Wed Dec 13 12:39:43 1995
@@ -0,0 +1,513 @@
+/*
+ * jazzdma.c
+ *
+ * Mips Jazz DMA controller support
+ * (C) 1995 Andreas Busse
+ *
+ * NOTE: Some of the argument checkings could be removed when
+ * things have settled down. Also, instead of returning 0xffffffff
+ * on failure of vdma_alloc() one could leave page #0 unused
+ * and return the more usual NULL pointer as logical address.
+ * 
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsconfig.h>
+#include <asm/jazz.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/dma.h>
+#include <asm/jazzdma.h>
+
+
+static unsigned long vdma_pagetable_start = 0;
+static unsigned long vdma_pagetable_end = 0;
+
+/*
+ * Debug stuff
+ */
+#define vdma_debug     ((CONF_DEBUG_VDMA) ? debuglvl : 0)
+
+static int debuglvl = 3;
+
+/*
+ * Local prototypes
+ */
+static void vdma_pgtbl_init(void);
+
+/*
+ * Initialize the Jazz R4030 dma controller
+ */
+unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end)
+{
+    /*
+     * Allocate 32k of memory for DMA page tables.
+     * This needs to be page aligned and should be
+     * uncached to avoid cache flushing after every
+     * update.
+     */
+    vdma_pagetable_start = KSEG1ADDR((memory_start + 4095) & ~4095);
+    vdma_pagetable_end = vdma_pagetable_start + VDMA_PGTBL_SIZE;
+
+    /*
+     * Clear the R4030 translation table
+     */
+    vdma_pgtbl_init();
+
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,PHYSADDR(vdma_pagetable_start));
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM,VDMA_PGTBL_SIZE);
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+
+    printk("VDMA: R4030 DMA pagetables initialized.\n");
+    return KSEG0ADDR(vdma_pagetable_end);
+}
+
+/*
+ * Allocate DMA pagetables using a simple first-fit algorithm
+ */
+unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
+{
+    VDMA_PGTBL_ENTRY *entry = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+    int first;
+    int last;
+    int pages;
+    unsigned int frame;
+    unsigned long laddr;
+    int i;
+
+    /* check arguments */
+  
+    if (paddr > 0x1fffffff)
+    {
+        if (vdma_debug)
+            printk("vdma_alloc: Invalid physical address: %08lx\n",paddr);
+        return VDMA_ERROR;	/* invalid physical address */
+    }
+    if (size > 0x400000 || size == 0)
+    {
+        if (vdma_debug)
+            printk("vdma_alloc: Invalid size: %08lx\n",size);
+        return VDMA_ERROR;	/* invalid physical address */
+    }
+  
+  /* find free chunk */
+    pages = (size + 4095) >> 12; /* no. of pages to allocate */
+    first = 0;
+    while (1)
+    {
+        while (entry[first].owner != VDMA_PAGE_EMPTY &&
+               first < VDMA_PGTBL_ENTRIES)
+            first++;
+        if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */
+            return VDMA_ERROR;
+
+        last = first+1;
+        while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages)
+            last++;
+    
+        if (last-first == pages)
+            break;			/* found */
+    }
+  
+  /* mark pages as allocated */
+
+    laddr = (first << 12) + (paddr & (VDMA_PAGESIZE-1));
+    frame = paddr & ~(VDMA_PAGESIZE-1);
+  
+    for (i=first; i<last; i++)
+    {
+        entry[i].frame = frame;
+        entry[i].owner = laddr;
+        frame += VDMA_PAGESIZE;
+    }
+
+    /*
+     * update translation table and
+     * return logical start address
+     */
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+
+    if (vdma_debug > 1)
+        printk("vdma_alloc: Allocated %d pages starting from %08lx\n",
+               pages,laddr);
+
+    if (vdma_debug > 2)
+    {
+        printk("LADDR: ");
+        for (i=first; i<last; i++)
+            printk("%08x ",i<<12);
+        printk("\nPADDR: ");
+        for (i=first; i<last; i++)
+            printk("%08x ",entry[i].frame);
+        printk("\nOWNER: ");
+        for (i=first; i<last; i++)
+            printk("%08x ",entry[i].owner);
+        printk("\n");
+    }
+  
+    return laddr;
+}
+
+/*
+ * Free previously allocated dma translation pages
+ * Note that this does NOT change the translation table,
+ * it just marks the free'd pages as unused!
+ */
+int vdma_free(unsigned long laddr)
+{
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+    int i;
+
+    i = laddr >> 12;
+
+    if (pgtbl[i].owner != laddr)
+    {
+        printk("vdma_free: trying to free other's dma pages, laddr=%8lx\n",
+               laddr);
+        return -1;
+    }
+  
+    while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES)
+    {
+        pgtbl[i].owner = VDMA_PAGE_EMPTY;
+        i++;
+    }
+  
+    if (vdma_debug > 1)
+        printk("vdma_free: freed %ld pages starting from %08lx\n",
+               i-(laddr>>12),laddr);
+  
+    return 0;
+}
+
+/*
+ * Map certain page(s) to another physical address.
+ * Caller must have allocated the page(s) before.
+ */
+int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
+{
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+    int first;
+    int pages;
+
+    if (laddr > 0xffffff)
+    {
+        if (vdma_debug)
+            printk("vdma_map: Invalid logical address: %08lx\n",laddr);
+        return -EINVAL;		/* invalid logical address */
+    }
+    if (paddr > 0x1fffffff)
+    {
+        if (vdma_debug)
+            printk("vdma_map: Invalid physical address: %08lx\n",paddr);
+        return -EINVAL;		/* invalid physical address */
+    }
+  
+    pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
+    first = laddr >> 12;
+    if (vdma_debug)
+        printk("vdma_remap: first=%x, pages=%x\n",first,pages);
+    if (first+pages > VDMA_PGTBL_ENTRIES)
+    {
+        if (vdma_debug)
+            printk("vdma_alloc: Invalid size: %08lx\n",size);
+        return -EINVAL;
+    }
+
+    paddr &= ~(VDMA_PAGESIZE-1);
+    while (pages > 0 && first < VDMA_PGTBL_ENTRIES)
+    {
+        if (pgtbl[first].owner != laddr)
+        {
+            if (vdma_debug)
+                printk("Trying to remap other's pages.\n");
+            return -EPERM;		/* not owner */
+        }
+        pgtbl[first].frame = paddr;
+        paddr += VDMA_PAGESIZE;
+        first++;
+        pages--;
+    }
+
+    /* update translation table */
+  
+    r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
+  
+    if (vdma_debug > 2)
+    {
+        int i;
+        pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
+        first = laddr >> 12;
+        printk("LADDR: ");
+        for (i=first; i<first+pages; i++)
+            printk("%08x ",i<<12);
+        printk("\nPADDR: ");
+        for (i=first; i<first+pages; i++)
+            printk("%08x ",pgtbl[i].frame);
+        printk("\nOWNER: ");
+        for (i=first; i<first+pages; i++)
+            printk("%08x ",pgtbl[i].owner);
+        printk("\n");
+    }
+      
+    return 0;
+}
+
+/*
+ * Translate a physical address to a logical address.
+ * This will return the logical address of the first
+ * match.
+ */
+unsigned long vdma_phys2log(unsigned long paddr)
+{
+    int i;
+    int frame;
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+
+    frame = paddr & ~(VDMA_PAGESIZE-1);
+
+    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
+    {
+        if (pgtbl[i].frame == frame)
+            break;
+    }
+
+    if (i == VDMA_PGTBL_ENTRIES)
+        return 0xffffffff;
+
+    return (i<<12) + (paddr & (VDMA_PAGESIZE-1));
+}
+
+/*
+ * Translate a logical DMA address to a physical address
+ */
+unsigned long vdma_log2phys(unsigned long laddr)
+{
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+
+    return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE-1));
+}
+  
+/*
+ * Initialize the pagetable with a one-to-one mapping of
+ * the first 16 Mbytes of main memory and declare all
+ * entries to be unused. Using this method will at least
+ * allow some early device driver operations to work.
+ */
+static void vdma_pgtbl_init(void)
+{
+    int i;
+    unsigned long paddr = 0;
+    VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
+  
+    for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
+    {
+        pgtbl[i].frame = paddr;
+        pgtbl[i].owner = VDMA_PAGE_EMPTY;
+        paddr += VDMA_PAGESIZE;
+    }
+
+/*  vdma_stats(); */
+}
+
+/*
+ * Print DMA statistics
+ */
+void vdma_stats(void)
+{
+    int i;
+  
+    printk("vdma_stats: CONFIG: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_CONFIG));
+    printk("R4030 translation table base: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE));
+    printk("R4030 translation table limit: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM));
+    printk("vdma_stats: INV_ADDR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_INV_ADDR));
+    printk("vdma_stats: R_FAIL_ADDR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR));
+    printk("vdma_stats: M_FAIL_ADDR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR));
+    printk("vdma_stats: IRQ_SOURCE: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE));
+    printk("vdma_stats: I386_ERROR: %08x\n",
+           r4030_read_reg32(JAZZ_R4030_I386_ERROR));
+    printk("vdma_chnl_modes:   ");
+    for (i=0; i<8; i++)
+        printk("%04x ",
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(i<<5)));
+    printk("\n");
+    printk("vdma_chnl_enables: ");
+    for (i=0; i<8; i++)
+        printk("%04x ",
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(i<<5)));
+    printk("\n");
+}
+
+/*
+ * DMA transfer functions
+ */
+
+/*
+ * Enable a DMA channel. Also clear any error conditions.
+ */
+void vdma_enable(int channel)
+{
+    int status;
+  
+    if (vdma_debug)
+        printk("vdma_enable: channel %d\n",channel);
+  
+    /*
+     * Check error conditions first
+     */
+    status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
+    if (status & 0x400)
+        printk("VDMA: Channel %d: Address error!\n",channel);
+    if (status & 0x200)
+        printk("VDMA: Channel %d: Memory error!\n",channel);
+
+    /*
+     * Clear all interrupt flags
+     */
+    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                      R4030_TC_INTR | R4030_MEM_INTR | R4030_ADDR_INTR);
+
+    /*
+     * Enable the desired channel
+     */
+    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
+                      R4030_CHNL_ENABLE);
+}
+
+/*
+ * Disable a DMA channel
+ */
+void vdma_disable(int channel)
+{
+    if (vdma_debug)
+    {
+        int status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
+
+        printk("vdma_disable: channel %d\n",channel);
+        printk("VDMA: channel %d status: %04x (%s) mode: "
+               "%02x addr: %06x count: %06x\n",
+               channel,status,((status & 0x600) ? "ERROR" : "OK"),
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5)),
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5)),
+               (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5)));
+    }
+  
+    r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                      r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
+                      ~R4030_CHNL_ENABLE);
+
+    /*
+     * After disabling a DMA channel a remote bus register should be
+     * read to ensure that the current DMA acknowledge cycle is completed.
+     */
+    *((volatile unsigned int *)JAZZ_DUMMY_DEVICE);
+}
+
+/*
+ * Set DMA mode. This function accepts the mode values used
+ * to set a PC-style DMA controller. For the SCSI and FDC
+ * channels, we also set the default modes each time we're
+ * called.
+ * NOTE: The FAST and BURST dma modes are supported by the
+ * R4030 Rev. 2 and PICA chipsets only. I leave them disabled
+ * for now.
+ */
+void vdma_set_mode(int channel, int mode)
+{
+    if (vdma_debug)
+        printk("vdma_set_mode: channel %d, mode 0x%x\n",channel,mode);
+
+    switch(channel)
+    {
+    case JAZZ_SCSI_DMA:			/* scsi */
+        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
+/*			  R4030_MODE_FAST | */
+/*			  R4030_MODE_BURST | */
+                          R4030_MODE_INTR_EN |
+                          R4030_MODE_WIDTH_16 |
+                          R4030_MODE_ATIME_80);
+        break;
+      
+    case JAZZ_FLOPPY_DMA:	/* floppy */
+        r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
+/*			  R4030_MODE_FAST | */
+/*			  R4030_MODE_BURST | */
+                          R4030_MODE_INTR_EN |
+                          R4030_MODE_WIDTH_8 |
+                          R4030_MODE_ATIME_120);
+        break;
+
+    case JAZZ_AUDIOL_DMA:
+    case JAZZ_AUDIOR_DMA:
+        printk("VDMA: Audio DMA not supported yet.\n");
+        break;
+      
+    default:
+        printk("VDMA: vdma_set_mode() called with unsupported channel %d!\n",
+               channel);
+    }
+  
+    switch(mode)
+    {
+    case DMA_MODE_READ:
+        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
+                          ~R4030_CHNL_WRITE);
+        break;
+      
+    case DMA_MODE_WRITE:
+        r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
+                          r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
+                          R4030_CHNL_WRITE);
+      break;
+      
+    default:
+        printk("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",mode);
+    }
+}
+
+/*
+ * Set Transfer Address
+ */
+void vdma_set_addr(int channel, long addr)
+{
+    if (vdma_debug)
+        printk("vdma_set_addr: channel %d, addr %lx\n",channel,addr);
+
+    r4030_write_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5),addr);
+}
+
+/*
+ * Set Transfer Count
+ */
+void vdma_set_count(int channel, int count)
+{
+    if (vdma_debug)
+        printk("vdma_set_count: channel %d, count %08x\n",channel,(unsigned)count);
+  
+    r4030_write_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5),count);
+}
+     
+/*
+ * Get Residual
+ */
+int vdma_get_residue(int channel)
+{
+    int residual;
+  
+    residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5));
+
+    if (vdma_debug)
+        printk("vdma_get_residual: channel %d: residual=%d\n",channel,residual);
+  
+    return residual;
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/magnum4000.S linux/arch/mips/kernel/magnum4000.S
--- v1.3.47/linux/arch/mips/kernel/magnum4000.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/magnum4000.S	Wed Dec 13 12:39:43 1995
@@ -0,0 +1,275 @@
+/*
+ * arch/mips/kernel/magnum4000.S
+ *
+ * Copyright (C) 1995 Waldorf Electronics
+ * written by Ralf Baechle and Andreas Busse
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/jazz.h>
+#include <asm/stackframe.h>
+
+/*
+ * mips_magnum_4000_handle_int: Interrupt handler for Mips Magnum 4000 
+ */
+		.set	noreorder
+
+		NESTED(mips_magnum_4000_handle_int, FR_SIZE, ra)
+		.set	noat
+		SAVE_ALL
+		CLI
+		.set	at
+
+		/*
+		 * Get pending interrupts
+		 */
+		mfc0	t0,CP0_CAUSE		# get pending interrupts
+		mfc0	t1,CP0_STATUS		# get enabled interrupts
+		and	t0,t1			# isolate allowed ones
+		andi	t0,0xff00		# isolate pending bits
+		beqz	t0,spurious_interrupt
+		sll	t0,16			# delay slot
+
+		/*
+		 * Find irq with highest priority
+		 * FIXME: This is slow
+		 */
+		la	t1,ll_vectors
+1:		bltz	t0,2f			# found pending irq
+		sll	t0,1
+		b	1b
+		subu	t1,PTRSIZE		# delay slot
+
+		/*
+		 * Do the low-level stuff
+		 */
+2:		lw	t0,(t1)
+		jr	t0
+		nop				# delay slot
+		END(mips_magnum_4000_handle_int)
+
+/*
+ * Used for keyboard driver's fake_keyboard_interrupt()
+ */
+ll_sw0:		li	s1,~IE_SW0
+		mfc0	t0,CP0_CAUSE
+		and	t0,s1
+		mtc0	t0,CP0_CAUSE
+	PRINT("sw0 received...\n")
+		li	t1,1
+		b	call_real
+		li	t3,PTRSIZE	# delay slot, re-map to irq level 1
+
+ll_sw1:		li	s1,~IE_SW1
+		PANIC("Unimplemented sw1 handler")
+
+ll_local_dma:	li	s1,~IE_IRQ0
+		PANIC("Unimplemented local_dma handler")
+
+ll_local_dev:	lbu	t0,JAZZ_IO_IRQ_SOURCE
+#if __mips == 3
+		dsll	t0,1
+		ld	t0,local_vector(t0)
+#else /* 32 bit */
+		lw	t0,local_vector(t0)
+#endif
+		jr	t0
+		nop
+
+
+loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
+loc_sound:	PANIC("Unimplemented loc_sound handler")
+loc_video:	PANIC("Unimplemented loc_video handler")
+loc_scsi:	PANIC("Unimplemented loc_scsi handler")
+
+/*
+ * Keyboard interrupt handler
+ */
+loc_keyboard:	li	s1,~JAZZ_IE_KEYBOARD
+		li	t1,JAZZ_KEYBOARD_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_KEYBOARD_IRQ	# delay slot
+
+/*
+ * Ethernet interrupt handler, remapped to level 2
+ */
+loc_ethernet: /*	PRINT ("ethernet IRQ\n"); */
+		li	s1,~JAZZ_IE_ETHERNET
+		li	t1,JAZZ_ETHERNET_IRQ
+ 		b	loc_call
+		li	t3,PTRSIZE*JAZZ_ETHERNET_IRQ 	# delay slot
+
+
+loc_mouse:	PANIC("Unimplemented loc_mouse handler")
+
+/*
+ * Serial port 1 IRQ, remapped to level 3
+ */
+loc_serial1:	li	s1,~JAZZ_IE_SERIAL1
+		li	t1,JAZZ_SERIAL1_IRQ
+ 		b	loc_call
+		li	t3,PTRSIZE*JAZZ_SERIAL1_IRQ 	# delay slot
+
+/*
+ * Serial port 2 IRQ, remapped to level 4
+ */
+loc_serial2:	li	s1,~JAZZ_IE_SERIAL2
+		li	t1,JAZZ_SERIAL2_IRQ
+ 		b	loc_call
+		li	t3,PTRSIZE*JAZZ_SERIAL2_IRQ 	# delay slot
+
+/*
+ * Parallel port IRQ, remapped to level 5
+ */
+loc_parallel:	li	s1,~JAZZ_IE_PARALLEL
+		li	t1,JAZZ_PARALLEL_IRQ
+ 		b	loc_call
+		li	t3,PTRSIZE*JAZZ_PARALLEL_IRQ 	# delay slot
+
+/*
+ * Floppy IRQ, remapped to level 6
+ */
+loc_floppy:	li	s1,~JAZZ_IE_FLOPPY
+		li	t1,JAZZ_FLOPPY_IRQ
+ 		b	loc_call
+		li	t3,PTRSIZE*JAZZ_FLOPPY_IRQ 	# delay slot
+
+/*
+ * Now call the real handler
+ */
+loc_call:	lui	s3,%hi(intr_count)
+		lw	t2,%lo(intr_count)(s3)
+		la	t0,IRQ_vectors			# delay slot
+		addiu	t2,1
+		sw	t2,%lo(intr_count)(s3)
+
+		/*
+		 * Temporarily disable interrupt source
+		 */
+		lhu	t2,JAZZ_IO_IRQ_ENABLE
+		addu	t0,t3				# make ptr to IRQ handler
+		lw	t0,(t0)
+		and	t2,s1				# delay slot
+		sh	t2,JAZZ_IO_IRQ_ENABLE
+		jalr	t0				# call IRQ handler
+		nor	s1,zero,s1			# delay slot
+
+		/*
+		 * Reenable interrupt
+		 */
+		lhu	t2,JAZZ_IO_IRQ_ENABLE
+		lw	t1,%lo(intr_count)(s3)		# delay slot
+		or	t2,s1
+		sh	t2,JAZZ_IO_IRQ_ENABLE
+
+		subu	t1,1
+		jr	v0
+		sw	t1,%lo(intr_count)(s3)
+
+ll_eisa_irq:	li	s1,~IE_IRQ2
+		PANIC("Unimplemented eisa_irq handler")
+
+ll_eisa_nmi:	li	s1,~IE_IRQ3
+		PANIC("Unimplemented eisa_nmi handler")
+
+/*
+ * Timer IRQ
+ * We remap the timer irq to be more similar to a IBM compatible
+ */
+ll_timer:	lw	t0,JAZZ_TIMER_REGISTER # timer irq cleared on read
+		li	s1,~IE_IRQ4
+		li	t1,0
+		b	call_real
+		li	t3,0		# delay slot, re-map to irq level 0
+
+/*
+ * CPU count/compare IRQ (unused)
+ */
+ll_count:	j	return
+		mtc0	zero,CP0_COMPARE
+
+/*
+ * Now call the real handler
+ */
+call_real:	lui	s3,%hi(intr_count)
+		lw	t2,%lo(intr_count)(s3)
+		la	t0,IRQ_vectors			# delay slot
+		addiu	t2,1
+		sw	t2,%lo(intr_count)(s3)
+
+		/*
+		 * temporarily disable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		and	t2,s1
+
+		addu	t0,t3
+		lw	t0,(t0)
+		mtc0	t2,CP0_STATUS		# delay slot
+		jalr	t0
+		nor	s1,zero,s1		# delay slot
+
+		/*
+		 * reenable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		or	t2,s1
+		mtc0	t2,CP0_STATUS
+
+		lw	t2,%lo(intr_count)(s3)
+		subu	t2,1
+
+		jr	v0
+		sw	t2,%lo(intr_count)(s3)
+
+/*
+ * Just for debugging...
+ */
+		LEAF(drawline)
+		li	t1,0xffffffff
+		li	t2,0x100
+1:		sw	t1,(a0)
+		addiu	a0,a0,4
+		addiu	t2,t2,-1
+		bnez	t2,1b
+		nop
+		jr 	ra
+		nop
+		END(drawline)
+
+
+		.data
+		PTR	ll_sw0			# SW0
+		PTR	ll_sw1			# SW1
+		PTR	ll_local_dma		# Local DMA
+		PTR	ll_local_dev		# Local devices
+		PTR	ll_eisa_irq		# EISA IRQ
+		PTR	ll_eisa_nmi		# EISA NMI
+		PTR	ll_timer		# Timer
+ll_vectors:	PTR	ll_count		# Count/Compare IRQ
+
+local_vector:	PTR	loc_no_irq
+		PTR	loc_parallel
+		PTR	loc_floppy
+		PTR	loc_sound
+		PTR	loc_video
+		PTR	loc_ethernet
+		PTR	loc_scsi
+		PTR	loc_keyboard
+		PTR	loc_mouse
+		PTR	loc_serial1
+		PTR	loc_serial2
+
+		.align	5
+LEAF(spurious_interrupt)
+		/*
+		 * Nothing happened... (whistle)
+		 */
+		lui	t1,%hi(spurious_count)
+		lw	t0,%lo(spurious_count)(t1)
+		la	v0,return
+		addiu	t0,1
+		jr	ra
+		sw	t0,%lo(spurious_count)(t1)
+		END(spurious_interrupt)
+
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/pica.S linux/arch/mips/kernel/pica.S
--- v1.3.47/linux/arch/mips/kernel/pica.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/pica.S	Wed Dec 13 12:39:43 1995
@@ -0,0 +1,268 @@
+/*
+ * arch/mips/kernel/pica.S
+ *
+ * Copyright (C) 1995 Waldorf Electronics
+ * written by Ralf Baechle and Andreas Busse
+ *
+ * Acer PICA 61 specific stuff
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/jazz.h>
+#include <asm/pica.h>
+#include <asm/stackframe.h>
+
+/*
+ * acer_pica_61_handle_int: Interrupt handler for the ACER Pica-61 boards
+ * FIXME: this is *very* experimental!
+ */
+		.set	noreorder
+
+		NESTED(acer_pica_61_handle_int, FR_SIZE, ra)
+		.set	noat
+		SAVE_ALL
+		CLI
+		.set	at
+
+		/*
+		 * Get pending interrupts
+		 */
+		mfc0	t0,CP0_CAUSE		# get pending interrupts
+		mfc0	t1,CP0_STATUS		# get enabled interrupts
+		and	t0,t1			# isolate allowed ones
+		andi	t0,0xff00		# isolate pending bits
+		beqz	t0,spurious_interrupt
+		sll	t0,16			# delay slot
+
+		/*
+		 * Find irq with highest priority
+		 * FIXME: This is slow - use binary search
+		 */
+		la	t1,ll_vectors
+1:		bltz	t0,2f			# found pending irq
+		sll	t0,1
+		b	1b
+		subu	t1,PTRSIZE		# delay slot
+
+		/*
+		 * Do the low-level stuff
+		 */
+2:		lw	t0,(t1)
+		jr	t0
+		nop				# delay slot
+		END(acer_pica_61_handle_int)
+
+/*
+ * Used for keyboard driver's fake_keyboard_interrupt()
+ */
+ll_sw0:		li	s1,~IE_SW0
+		mfc0	t0,CP0_CAUSE
+		and	t0,s1
+		mtc0	t0,CP0_CAUSE
+	PRINT("sw0 received...\n")
+		li	t1,1
+		b	call_real
+		li	t3,PTRSIZE	# delay slot, re-map to irq level 1
+
+ll_sw1:		li	s1,~IE_SW1
+		PANIC("Unimplemented sw1 handler")
+
+ll_local_dma:	li	s1,~IE_IRQ0
+		PANIC("Unimplemented local_dma handler")
+
+ll_local_dev:	lbu	t0,JAZZ_IO_IRQ_SOURCE
+#if __mips == 3
+		dsll	t0,1
+		ld	t0,local_vector(t0)
+#else /* 32 bit */
+		lw	t0,local_vector(t0)
+#endif
+		jr	t0
+		nop
+
+
+loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
+/*
+ * Parallel port IRQ, remapped to level 5
+ */
+loc_parallel:	li	s1,~JAZZ_IE_PARALLEL
+		li	t1,JAZZ_PARALLEL_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_PARALLEL_IRQ 	# delay slot
+
+/*
+ * Floppy IRQ, remapped to level 6
+ */
+loc_floppy:	li	s1,~JAZZ_IE_FLOPPY
+		li	t1,JAZZ_FLOPPY_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_FLOPPY_IRQ 	# delay slot
+
+/*
+ * Now call the real handler
+ */
+loc_call:	lui	s3,%hi(intr_count)
+		lw	t2,%lo(intr_count)(s3)
+		la	t0,IRQ_vectors			# delay slot
+		addiu	t2,1
+		sw	t2,%lo(intr_count)(s3)
+
+		/*
+		 * Temporarily disable interrupt source
+		 */
+		lhu	t2,JAZZ_IO_IRQ_ENABLE
+		addu	t0,t3				# make ptr to IRQ handler
+		lw	t0,(t0)
+		and	t2,s1				# delay slot
+		sh	t2,JAZZ_IO_IRQ_ENABLE
+		jalr	t0				# call IRQ handler
+ 		nor	s1,zero,s1			# delay slot
+ 
+ 		/*
+ 		 * Reenable interrupt
+ 		 */
+		lhu	t2,JAZZ_IO_IRQ_ENABLE
+ 		lw	t1,%lo(intr_count)(s3)		# delay slot
+ 		or	t2,s1
+		sh	t2,JAZZ_IO_IRQ_ENABLE
+ 
+ 		subu	t1,1
+ 		jr	v0
+		sw	t1,%lo(intr_count)(s3)		# delay slot
+
+ll_isa_irq:	li	s1,~IE_IRQ2
+		PANIC("Unimplemented isa_irq handler")
+
+ll_isa_nmi:	li	s1,~IE_IRQ3
+		PANIC("Unimplemented isa_nmi handler")
+
+/*
+ * Timer IRQ
+ * We remap the timer irq to be more similar to an IBM compatible
+ */
+ll_timer:	lw	zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
+		li	s1,~IE_IRQ4
+		li	t1,0
+		b	call_real
+		li	t3,0		# delay slot, re-map to irq level 0
+
+/*
+ * CPU count/compare IRQ (unused)
+ */
+ll_count:	j	return
+		mtc0	zero,CP0_COMPARE
+
+/*
+ * Now call the real handler
+ */
+call_real:	lui	s3,%hi(intr_count)
+		lw	t2,%lo(intr_count)(s3)
+		la	t0,IRQ_vectors
+		addiu	t2,1
+		sw	t2,%lo(intr_count)(s3)
+
+		/*
+		 * temporarily disable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		and	t2,s1
+
+		addu	t0,t3
+		lw	t0,(t0)
+		mtc0	t2,CP0_STATUS		# delay slot
+		jalr	t0
+		nor	s1,zero,s1		# delay slot
+
+		/*
+		 * reenable interrupt
+		 */
+		mfc0	t2,CP0_STATUS
+		or	t2,s1
+		mtc0	t2,CP0_STATUS
+
+		lw	t2,%lo(intr_count)(s3)
+		subu	t2,1
+
+		jr	v0
+		sw	t2,%lo(intr_count)(s3)
+
+		.data
+		PTR	ll_sw0			# SW0
+		PTR	ll_sw1			# SW1
+		PTR	ll_local_dma		# Local DMA
+		PTR	ll_local_dev		# Local devices
+		PTR	ll_isa_irq		# ISA IRQ
+		PTR	ll_isa_nmi		# ISA NMI
+		PTR	ll_timer		# Timer
+ll_vectors:	PTR	ll_count		# Count/Compare IRQ
+
+
+/*
+ * Sound? What sound hardware (whistle) ???
+ */
+loc_sound:	PANIC("Unimplemented loc_sound handler")
+loc_video:	PANIC("Unimplemented loc_video handler")
+
+/*
+ * Ethernet interrupt handler, remapped to level 2
+ */
+loc_ethernet: 	li	s1,~JAZZ_IE_ETHERNET
+		li	t1,JAZZ_ETHERNET_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_ETHERNET_IRQ 	# delay slot
+
+loc_scsi:	PANIC("Unimplemented loc_scsi handler")
+
+/*
+ * Keyboard interrupt handler
+ */
+loc_keyboard:	li	s1,~JAZZ_IE_KEYBOARD
+		li	t1,JAZZ_KEYBOARD_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_KEYBOARD_IRQ	# re-map to irq level 1
+
+loc_mouse:	PANIC("Unimplemented loc_mouse handler")
+
+/*
+ * Serial port 1 IRQ, remapped to level 3
+ */
+loc_serial1:	li	s1,~JAZZ_IE_SERIAL1
+		li	t1,JAZZ_SERIAL1_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_SERIAL1_IRQ 	# delay slot
+
+/*
+ * Serial port 2 IRQ, remapped to level 4
+ */
+loc_serial2:	li	s1,~JAZZ_IE_SERIAL2
+		li	t1,JAZZ_SERIAL2_IRQ
+		b	loc_call
+		li	t3,PTRSIZE*JAZZ_SERIAL2_IRQ 	# delay slot
+
+		.data
+local_vector:	PTR	loc_no_irq
+		PTR	loc_parallel
+		PTR	loc_floppy
+		PTR	loc_sound
+		PTR	loc_video
+		PTR	loc_ethernet
+		PTR	loc_scsi
+		PTR	loc_keyboard
+		PTR	loc_mouse
+		PTR	loc_serial1
+		PTR	loc_serial2
+
+		.align	5
+		.text
+LEAF(spurious_interrupt)
+		/*
+		 * Nothing happened... (whistle)
+		 */
+		lui	t1,%hi(spurious_count)
+		lw	t0,%lo(spurious_count)(t1)
+		la	v0,return
+		addiu	t0,1
+		jr	ra
+		sw	t0,%lo(spurious_count)(t1)
+		END(spurious_interrupt)
+
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- v1.3.47/linux/arch/mips/kernel/process.c	Fri Oct  6 14:35:15 1995
+++ linux/arch/mips/kernel/process.c	Wed Dec 13 12:39:43 1995
@@ -1,14 +1,11 @@
 /*
  *  linux/arch/mips/kernel/process.c
  *
- *  Copyright (C) 1995  Waldorf Electronics,
+ *  Copyright (C) 1995 Ralf Baechle
  *  written by Ralf Baechle
+ *
+ * This file handles the architecture-dependent parts of initialization
  */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
- */
-
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -18,54 +15,80 @@
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
 #include <linux/ldt.h>
+#include <linux/mman.h>
+#include <linux/sys.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 
+#include <asm/bootinfo.h>
 #include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
+#include <asm/processor.h>
 #include <asm/stackframe.h>
+#include <asm/io.h>
 
-asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
+asmlinkage void ret_from_sys_call(void);
 
 /*
- * The idle loop on a MIPS..
+ * This routine reboots the machine by asking the keyboard
+ * controller to pulse the reset-line low. We try that for a while,
+ * and if it doesn't work, we do some other stupid things.
+ * Should be ok for Deskstation Tynes. Reseting others needs to be
+ * investigated...
  */
-asmlinkage int sys_idle(void)
+static inline void kb_wait(void)
 {
-#if 0
 	int i;
-#endif
 
-	if (current->pid != 0)
-		return -EPERM;
+	for (i=0; i<0x10000; i++)
+		if ((inb_p(0x64) & 0x02) == 0)
+			break;
+}
 
-#if 0
-	/* Map out the low memory: it's no longer needed */
-	for (i = 0 ; i < 512 ; i++)
-		pgd_clear(swapper_pg_dir + i);
-#endif
+/*
+ * Hard reset for Deskstation Tyne
+ * No hint how this works on Pica boards.
+ */
+void hard_reset_now(void)
+{
+	int i, j;
 
-	/* endless idle loop with no priority at all */
-	current->counter = -100;
+	sti();
 	for (;;) {
-		/*
-		 * R4[26]00 have wait, R4[04]00 don't.
-		 */
-		if (wait_available && !need_resched)
-			__asm__("wait");
-		schedule();
+		for (i=0; i<100; i++) {
+			kb_wait();
+			for(j = 0; j < 100000 ; j++)
+				/* nothing */;
+			outb(0xfe,0x64);	 /* pulse reset low */
+		}
 	}
 }
 
-/*
- * Do necessary setup to start up a newly executed thread.
- */
-void start_thread(struct pt_regs * regs, unsigned long eip, unsigned long esp)
+void show_regs(struct pt_regs * regs)
 {
-	regs->cp0_epc = eip;
-	regs->reg29 = esp;
+	/*
+	 * Saved main processor registers
+	 */
+	printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       0, regs->reg1, regs->reg2, regs->reg3,
+               regs->reg4, regs->reg5, regs->reg6, regs->reg7);
+	printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       regs->reg8, regs->reg9, regs->reg10, regs->reg11,
+               regs->reg12, regs->reg13, regs->reg14, regs->reg15);
+	printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+	       regs->reg16, regs->reg17, regs->reg18, regs->reg19,
+               regs->reg20, regs->reg21, regs->reg22, regs->reg23);
+	printk("$24: %08lx %08lx                   %08lx %08lx %08lx %08lx\n",
+	       regs->reg24, regs->reg25, regs->reg28, regs->reg29,
+               regs->reg30, regs->reg31);
+
+	/*
+	 * Saved cp0 registers
+	 */
+	printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
+	       regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
 }
 
 /*
@@ -91,89 +114,60 @@
 	 * Nothing to do
 	 */
 }
-
-#define IS_CLONE (regs->orig_reg2 == __NR_clone)
-
-void copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs)
+  
+void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+                 struct task_struct * p, struct pt_regs * regs)
 {
 	struct pt_regs * childregs;
+	unsigned long childksp;
 
+	childksp = p->kernel_stack_page + PAGE_SIZE - 8;
 	/*
 	 * set up new TSS
 	 */
-	p->tss.fs = KERNEL_DS;
-	p->tss.ksp = (p->kernel_stack_page + PAGE_SIZE - 4) | KSEG0;
 	childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
-	p->tss.reg29 = ((unsigned long) childregs) | KSEG0; /* new sp */
-	p->tss.reg31 = (unsigned long) ret_from_sys_call;
 	*childregs = *regs;
-	childregs->reg2 = 0;
+	childregs->reg2 = 0;		/* Child gets zero as return value */
+	childregs->reg7 = 0;		/* Clear error flag */
+	regs->reg2 = p->pid;
+	if (childregs->cp0_status & ST0_CU0)
+		childregs->reg29 = childksp;
+	else
+		childregs->reg29 = usp;
+	p->tss.ksp = childksp;
+	p->tss.reg29 = (unsigned long) childregs;	/* new sp */
+	p->tss.reg31 = (unsigned long) ret_from_sys_call;
 
 	/*
 	 * New tasks loose permission to use the fpu. This accelerates context
-	 * switching for non fp programs, which true for the most programs.
+	 * switching for most programs since they don't use the fpu.
 	 */
-	p->tss.cp0_status = regs->cp0_status &
-	                    ~(ST0_CU1|ST0_CU0|ST0_KSU|ST0_ERL|ST0_EXL);
-	childregs->cp0_status &= ~(ST0_CU1|ST0_CU0);
+	p->tss.cp0_status = read_32bit_cp0_register(CP0_STATUS) &
+                            ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU|ST0_ERL|ST0_EXL);
+	childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1);
 }
 
 /*
- * fill in the user structure for a core dump..
+ * fill in the fpu structure for a core dump..
+ *
+ * Actually this is "int dump_fpu (struct elf_fpregset_t *fpu)"
  */
-void dump_thread(struct pt_regs * regs, struct user * dump)
+int dump_fpu (int shutup_the_gcc_warning_about_elf_fpregset_t)
 {
+	int fpvalid = 0;
 	/*
-	 * Not ready yet
+	 * To do...
 	 */
-#if 0
-	int i;
 
-/* changed the size calculations - should hopefully work better. lbt */
-	dump->magic = CMAGIC;
-	dump->start_code = 0;
-	dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
-	dump->u_tsize = ((unsigned long) current->mm->end_code) >> 12;
-	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> 12;
-	dump->u_dsize -= dump->u_tsize;
-	dump->u_ssize = 0;
-	for (i = 0; i < 8; i++)
-		dump->u_debugreg[i] = current->debugreg[i];  
-
-	if (dump->start_stack < TASK_SIZE)
-		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> 12;
-
-	dump->regs = *regs;
-
-/* Flag indicating the math stuff is valid. We don't support this for the
-   soft-float routines yet */
-	if (hard_math) {
-		if ((dump->u_fpvalid = current->used_math) != 0) {
-			if (last_task_used_math == current)
-				__asm__("clts ; fnsave %0": :"m" (dump->i387));
-			else
-				memcpy(&dump->i387,&current->tss.i387.hard,sizeof(dump->i387));
-		}
-	} else {
-		/* we should dump the emulator state here, but we need to
-		   convert it into standard 387 format first.. */
-		dump->u_fpvalid = 0;
-	}
-#endif
+	return fpvalid;
 }
 
 /*
- * sys_execve() executes a new program.
+ * fill in the user structure for a core dump..
  */
-asmlinkage int sys_execve(struct pt_regs regs)
+void dump_thread(struct pt_regs * regs, struct user * dump)
 {
-	int error;
-	char * filename;
-
-	error = getname((char *) regs.reg4, &filename);
-	if (error)
-		return error;
-	error = do_execve(filename, (char **) regs.reg5, (char **) regs.reg6, &regs);
-	putname(filename);
-	return error;
+	/*
+	 * To do...
+	 */
 }
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- v1.3.47/linux/arch/mips/kernel/ptrace.c	Thu Sep  7 17:17:16 1995
+++ linux/arch/mips/kernel/ptrace.c	Wed Dec 13 12:39:44 1995
@@ -11,6 +11,7 @@
 #include <linux/user.h>
 
 #include <asm/segment.h>
+#include <asm/pgtable.h>
 #include <asm/system.h>
 
 #if 0
@@ -150,10 +151,8 @@
 		goto repeat;
 	}
 /* this is a hack for non-kernel-mapped video buffers and similar */
-	if (page < high_memory) {
-		page += addr & ~PAGE_MASK;
-		*(unsigned long *) page = data;
-	}
+	if (page < high_memory)
+		*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
 	set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
@@ -463,6 +462,8 @@
 		case PTRACE_KILL: {
 			long tmp;
 
+			if (child->state == TASK_ZOMBIE)	/* already dead */
+				return 0;
 			wake_up_process(child);
 			child->exit_code = SIGKILL;
 	/* make sure the single step bit is not set. */
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/r4xx0.S linux/arch/mips/kernel/r4xx0.S
--- v1.3.47/linux/arch/mips/kernel/r4xx0.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/r4xx0.S	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,829 @@
+/*
+ * arch/mips/kernel/r4xx0.S
+ *
+ * Copyright (C) 1994, 1995 Waldorf Electronics
+ * Written by Ralf Baechle and Andreas Busse
+ *
+ * This file contains most of the R4xx0 specific routines.  Due to the
+ * similarities this should hopefully also be fine for the R10000.  For
+ * now we especially support the R10000 by not invalidating entries out of
+ * the TLB before calling the C handlers.
+ *
+ * This code is evil magic. Read appendix f (coprozessor 0 hazards) of
+ * all R4xx0 manuals and think about that MIPS means "Microprocessor without
+ * Interlocked Pipeline Stages" before you even think about changing this code!
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/mipsregs.h>
+#include <asm/segment.h>
+#include <asm/stackframe.h>
+
+#ifdef __SMP__
+#error "Fix this for SMP"
+#else
+#define current current_set
+#endif
+
+MODE_ALIAS	=	0x0016			# uncachable
+
+		.text
+		.set	mips3
+		.set	noreorder
+
+		.align	5
+		NESTED(handle_tlbl, FR_SIZE, sp)
+		.set	noat
+		/*
+		 * Check whether this is a refill or an invalid exception
+		 *
+		 * NOTE: Some MIPS manuals say that the R4x00 sets the
+		 * BadVAddr only when EXL == 0. This is wrong - BadVAddr
+		 * is being set for all Reload, Invalid and Modified
+		 * exceptions.
+		 */
+		mfc0	k0,CP0_BADVADDR
+		mfc0	k1,CP0_ENTRYHI
+		ori	k0,0x1fff
+		xori	k0,0x1fff
+		andi	k1,0xff
+		or	k0,k1
+		mfc0	k1,CP0_ENTRYHI
+		mtc0	k0,CP0_ENTRYHI
+		nop					# for R4[04]00 pipeline
+		nop
+		nop
+		tlbp
+		nop					# for R4[04]00 pipeline
+		nop
+		mfc0	k0,CP0_INDEX
+		bgez	k0,invalid_tlbl			# bad addr in c0_badvaddr
+		mtc0	k1,CP0_ENTRYHI			# delay slot
+		/*
+		 * Damn... The next nop is required on my R4400PC V5.0, but
+		 * I don't know why - at least there is no documented
+		 * reason as for the others :-(
+		 */
+		nop
+
+#ifdef CONF_DEBUG_TLB
+		/*
+		 * OK, this is a double fault. Let's see whether this is
+		 * due to an invalid entry in the page_table.
+		 */
+		dmfc0	k0,CP0_BADVADDR
+		srl	k0,12
+		sll	k0,2
+		lui	k1,%HI(TLBMAP)
+		addu	k0,k1
+		lw	k1,(k0)
+		andi	k1,(_PAGE_PRESENT|_PAGE_ACCESSED)
+		bnez	k1,reload_pgd_entries
+		nop					# delay slot
+
+		.set	noat
+		SAVE_ALL
+		.set	at
+		PRINT("Double fault caused by invalid entries in pgd:\n")
+		dmfc0	a1,CP0_BADVADDR
+		PRINT("Double fault address     : %08lx\n")
+		dmfc0	a1,CP0_EPC
+		PRINT("c0_epc                   : %08lx\n")
+		jal	show_regs
+		move	a0,sp
+		jal	dump_tlb_all
+		nop
+		dmfc0	a0,CP0_BADVADDR
+		jal	dump_list_current
+		nop
+		.set	noat
+		STI
+		.set	at
+		PANIC("Corrupted pagedir")
+		.set	noat
+
+reload_pgd_entries:
+#endif /* CONF_DEBUG_TLB */
+
+		/*
+		 * Load missing pair of entries from the pgd and return.
+		 */
+		dmfc0	k1,CP0_CONTEXT
+		dsra	k1,1
+		lwu	k0,(k1)			# Never causes nested exception
+		lwu	k1,4(k1)
+		dsrl	k0,6			# Convert to EntryLo format
+		dsrl	k1,6			# Convert to EntryLo format
+		dmtc0	k0,CP0_ENTRYLO0
+		dmtc0	k1,CP0_ENTRYLO1
+		nop				# for R4[04]00 pipeline
+		tlbwr
+		nop				# for R4[04]00 pipeline
+		nop
+		nop
+		/*
+		 * We don't know whether the original access was read or
+		 * write, so return and see what happens...
+		 */
+		eret
+
+		/*
+		 * Handle invalid exception
+		 *
+		 * There are two possible causes for an invalid (tlbl)
+		 * exception:
+		 * 1) pages with present bit set but the valid bit clear
+		 * 2) nonexistant pages
+		 * Case one needs fast handling, therefore don't save
+		 * registers yet.
+		 *
+		 * k0 contains c0_index.
+		 */
+invalid_tlbl:
+#ifdef CONFIG_TLB_SHUTDOWN
+		/*
+		 * Remove entry so we don't need to care later
+		 * For sake of the R4000 V2.2 pipeline the tlbwi insn
+		 * has been moved down. Moving it around is juggling with
+		 * explosives...
+		 */
+		lui	k1,0x0008
+		or	k0,k1
+		dsll	k0,13
+		dmtc0	k0,CP0_ENTRYHI
+		dmtc0	zero,CP0_ENTRYLO0
+		dmtc0	zero,CP0_ENTRYLO1
+#endif
+		/*
+		 * Test present bit in entry
+		 */
+		dmfc0	k0,CP0_BADVADDR
+		srl	k0,12
+		sll	k0,2
+#ifdef CONFIG_TLB_SHUTDOWN
+		tlbwi						# do not move!
+#endif
+		lui	k1,%HI(TLBMAP)
+		addu	k0,k1
+		lw	k1,(k0)
+		andi	k1,(_PAGE_PRESENT|_PAGE_READ)
+		xori	k1,(_PAGE_PRESENT|_PAGE_READ)
+		bnez	k1,nopage_tlbl
+		/*
+		 * Present and read bits are set -> set valid and accessed bits
+		 */
+		lw	k1,(k0)					# delay slot
+		ori	k1,(_PAGE_VALID|_PAGE_ACCESSED)
+		sw	k1,(k0)
+		eret
+
+		/*
+		 * Page doesn't exist. Lots of work which is less important
+		 * for speed needs to be done, so hand it all over to the
+		 * kernel memory management routines.
+		 */
+nopage_tlbl:	SAVE_ALL
+		dmfc0	a2,CP0_BADVADDR
+		STI
+		.set	at
+		/*
+		 * a0 (struct pt_regs *) regs
+		 * a1 (unsigned long)    0 for read access
+		 * a2 (unsigned long)    faulting virtual address
+		 */
+		move	a0,sp
+		jal	do_page_fault
+		li	a1,0				# delay slot
+		j	ret_from_sys_call
+		nop					# delay slot
+		END(handle_tlbl)
+
+		.text
+		.align	5
+		NESTED(handle_tlbs, FR_SIZE, sp)
+		.set	noat
+		/*
+		 * It is impossible that is a nested reload exception.
+		 * Therefore this must be a invalid exception.
+		 * Two possible cases:
+		 * 1) Page exists but not dirty.
+		 * 2) Page doesn't exist yet. Hand over to the kernel.
+		 *
+		 * Test whether present bit in entry is set
+		 */
+		dmfc0	k0,CP0_BADVADDR
+		srl	k0,12
+		sll	k0,2
+		lui	k1,%HI(TLBMAP)
+		addu	k0,k1
+		lw	k1,(k0)
+		tlbp					# find faulting entry
+		andi	k1,(_PAGE_PRESENT|_PAGE_WRITE)
+		xori	k1,(_PAGE_PRESENT|_PAGE_WRITE)
+		bnez	k1,nopage_tlbs
+		/*
+		 * Present and writable bits set: set accessed and dirty bits.
+		 */
+		lw	k1,(k0)				# delay slot
+		ori	k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \
+			       _PAGE_VALID|_PAGE_DIRTY)
+		sw	k1,(k0)
+		/*
+		 * Now reload the entry into the TLB
+		 */
+		ori	k0,0x0004
+		xori	k0,0x0004
+		lw	k1,4(k0)
+		lw	k0,(k0)
+		srl	k1,6
+		srl	k0,6
+		dmtc0	k1,CP0_ENTRYLO1
+		dmtc0	k0,CP0_ENTRYLO0
+		nop				# for R4[04]00 pipeline
+		tlbwi
+		nop				# for R4[04]00 pipeline
+		nop
+		nop
+		eret
+
+		/*
+		 * Page doesn't exist. Lots of work which is less important
+		 * for speed needs to be done, so hand it all over to the
+		 * kernel memory management routines.
+		 */
+nopage_tlbs:
+nowrite_mod:
+#ifdef CONFIG_TLB_SHUTDOWN
+		/*
+		 * Remove entry so we don't need to care later
+		 */
+		mfc0	k0,CP0_INDEX
+#ifdef CONF_DEBUG_TLB
+		bgez	k0,2f
+		nop
+		/*
+		 * We got a tlbs exception but found no matching entry in
+		 * the tlb.  This should never happen.  Paranoia makes us
+		 * check it, though.
+		 */
+		SAVE_ALL
+		jal	show_regs
+		move	a0,sp
+		.set	at
+		mfc0	a1,CP0_BADVADDR
+		PRINT("c0_badvaddr == %08lx\n")
+		mfc0	a1,CP0_INDEX
+		PRINT("c0_index    == %08x\n")
+		mfc0	a1,CP0_ENTRYHI
+		PRINT("c0_entryhi  == %08x\n")
+		.set	noat
+		STI
+		.set	at
+		PANIC("Tlbs or tlbm exception with no matching entry in tlb")
+1:		j	1b
+		nop
+2:
+#endif /* CONF_DEBUG_TLB */
+		lui	k1,0x0008
+		or	k0,k1
+		dsll	k0,13
+		dmtc0	k0,CP0_ENTRYHI
+		dmtc0	zero,CP0_ENTRYLO0
+		dmtc0	zero,CP0_ENTRYLO1
+		nop				# for R4[04]00 pipeline
+		nop				# R4000 V2.2 requires 4 NOPs
+		nop
+		nop
+		tlbwi
+#endif
+		.set	noat
+		SAVE_ALL
+		dmfc0	a2,CP0_BADVADDR
+		STI
+		.set	at
+		/*
+		 * a0 (struct pt_regs *) regs
+		 * a1 (unsigned long)    1 for write access
+		 * a2 (unsigned long)    faulting virtual address
+		 */
+		move	a0,sp
+		jal	do_page_fault
+		li	a1,1				# delay slot
+		j	ret_from_sys_call
+		nop					# delay slot
+		END(handle_tlbs)
+
+		.align	5
+		NESTED(handle_mod, FR_SIZE, sp)
+		.set	noat
+		/*
+		 * Two possible cases:
+		 * 1) Page is writable but not dirty -> set dirty and return
+		 * 2) Page is not writable -> call C handler
+		 */
+		dmfc0	k0,CP0_BADVADDR
+		srl	k0,12
+		sll	k0,2
+		lui	k1,%HI(TLBMAP)
+		addu	k0,k1
+		lw	k1,(k0)
+		tlbp					# find faulting entry
+		andi	k1,_PAGE_WRITE
+		beqz	k1,nowrite_mod
+		/*
+		 * Present and writable bits set: set accessed and dirty bits.
+		 */
+		lw	k1,(k0)				# delay slot
+		ori	k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
+		sw	k1,(k0)
+		/*
+		 * Now reload the entry into the tlb
+		 */
+		ori	k0,0x0004
+		xori	k0,0x0004
+		lw	k1,4(k0)
+		lw	k0,(k0)
+		srl	k1,6
+		srl	k0,6
+		dmtc0	k1,CP0_ENTRYLO1
+		dmtc0	k0,CP0_ENTRYLO0
+		nop				# for R4[04]00 pipeline
+		nop
+		nop
+		tlbwi
+		nop				# for R4[04]00 pipeline
+		nop
+		nop
+		eret
+		END(handle_mod)
+		.set	at
+
+/*
+ * Until SAVE_ALL/RESTORE_ALL handle registers 64-bit wide we have to
+ * disable interrupts here.
+ */
+		.set	noreorder
+		LEAF(tlbflush)
+		mfc0	t3,CP0_STATUS
+		ori	t4,t3,1
+		xori	t4,1
+		mtc0	t4,CP0_STATUS
+		li	t0,PM_4K
+		mtc0	t0,CP0_PAGEMASK
+		la	t0,boot_info
+		lw	t0,OFFSET_BOOTINFO_TLB_ENTRIES(t0)
+		dmtc0	zero,CP0_ENTRYLO0
+		dmtc0	zero,CP0_ENTRYLO1
+		mfc0	t2,CP0_WIRED
+1:		subu	t0,1
+		mtc0	t0,CP0_INDEX
+		lui	t1,0x0008
+		or	t1,t0,t1
+		dsll	t1,13
+		dmtc0	t1,CP0_ENTRYHI
+		bne	t2,t0,1b
+		tlbwi					# delay slot
+		jr	ra
+		mtc0	t3,CP0_STATUS			# delay slot
+		END(tlbflush)
+
+		/*
+		 * Code necessary to switch tasks on an Linux/MIPS machine.
+		 */
+		.align	5
+		LEAF(resume)
+		/*
+		 * Current task's task_struct
+		 */
+		lui	t5,%hi(current)
+		lw	t0,%lo(current)(t5)
+
+		/*
+		 * Save status register
+		 */
+		mfc0	t1,CP0_STATUS
+		addu	t0,a1				# Add tss offset
+		sw	t1,TOFF_CP0_STATUS(t0)
+
+		/*
+		 * Disable interrupts
+		 */
+		ori	t2,t1,0x1f
+		xori	t2,0x1e
+		mtc0	t2,CP0_STATUS
+
+		/*
+		 * Save non-scratch registers
+		 * All other registers have been saved on the kernel stack
+		 */
+		sw	s0,TOFF_REG16(t0)
+		sw	s1,TOFF_REG17(t0)
+		sw	s2,TOFF_REG18(t0)
+		sw	s3,TOFF_REG19(t0)
+		sw	s4,TOFF_REG20(t0)
+		sw	s5,TOFF_REG21(t0)
+		sw	s6,TOFF_REG22(t0)
+		sw	s7,TOFF_REG23(t0)
+		sw	gp,TOFF_REG28(t0)
+		sw	sp,TOFF_REG29(t0)
+		sw	fp,TOFF_REG30(t0)
+
+		/*
+		 * Save floating point state
+		 */
+		sll	t2,t1,2
+		bgez	t2,2f
+		sw	ra,TOFF_REG31(t0)		# delay slot
+		sll	t2,t1,5
+		bgez	t2,1f
+		sdc1	$f0,(TOFF_FPU+0)(t0)		# delay slot
+		/*
+		 * Store the 16 odd double precision registers
+		 */
+		sdc1	$f1,(TOFF_FPU+8)(t0)
+		sdc1	$f3,(TOFF_FPU+24)(t0)
+		sdc1	$f5,(TOFF_FPU+40)(t0)
+		sdc1	$f7,(TOFF_FPU+56)(t0)
+		sdc1	$f9,(TOFF_FPU+72)(t0)
+		sdc1	$f11,(TOFF_FPU+88)(t0)
+		sdc1	$f13,(TOFF_FPU+104)(t0)
+		sdc1	$f15,(TOFF_FPU+120)(t0)
+		sdc1	$f17,(TOFF_FPU+136)(t0)
+		sdc1	$f19,(TOFF_FPU+152)(t0)
+		sdc1	$f21,(TOFF_FPU+168)(t0)
+		sdc1	$f23,(TOFF_FPU+184)(t0)
+		sdc1	$f25,(TOFF_FPU+200)(t0)
+		sdc1	$f27,(TOFF_FPU+216)(t0)
+		sdc1	$f29,(TOFF_FPU+232)(t0)
+		sdc1	$f31,(TOFF_FPU+248)(t0)
+
+		/*
+		 * Store the 16 even double precision registers
+		 */
+1:		cfc1	t1,fcr31
+		sdc1	$f2,(TOFF_FPU+16)(t0)
+		sdc1	$f4,(TOFF_FPU+32)(t0)
+		sdc1	$f6,(TOFF_FPU+48)(t0)
+		sdc1	$f8,(TOFF_FPU+64)(t0)
+		sdc1	$f10,(TOFF_FPU+80)(t0)
+		sdc1	$f12,(TOFF_FPU+96)(t0)
+		sdc1	$f14,(TOFF_FPU+112)(t0)
+		sdc1	$f16,(TOFF_FPU+128)(t0)
+		sdc1	$f18,(TOFF_FPU+144)(t0)
+		sdc1	$f20,(TOFF_FPU+160)(t0)
+		sdc1	$f22,(TOFF_FPU+176)(t0)
+		sdc1	$f24,(TOFF_FPU+192)(t0)
+		sdc1	$f26,(TOFF_FPU+208)(t0)
+		sdc1	$f28,(TOFF_FPU+224)(t0)
+		sdc1	$f30,(TOFF_FPU+240)(t0)
+		sw	t1,(TOFF_FPU+256)(t0)
+
+		/*
+		 * Switch current task
+		 */
+2:		sw	a0,%lo(current)(t5)
+		addu	a0,a1			# Add tss offset
+
+		/*
+		 * Switch address space
+		 */
+
+		/*
+		 * (Choose new ASID for process)
+		 * This isn't really required, but would speed up
+		 * context switching.
+		 */
+
+		/*
+		 * Switch the root pointer
+		 */
+		lw	t0,TOFF_PG_DIR(a0)
+		li	t1,TLB_ROOT
+		mtc0	t1,CP0_ENTRYHI
+		mtc0	zero,CP0_INDEX
+		srl	t0,6
+		ori	t0,MODE_ALIAS
+		mtc0	t0,CP0_ENTRYLO0
+		mtc0	zero,CP0_ENTRYLO1
+		lw	a2,TOFF_CP0_STATUS(a0)
+
+		/*
+		 * Flush tlb
+		 * (probably not needed, doesn't clobber a0-a3)
+		 */
+		jal	tlbflush
+		tlbwi 					# delay slot
+
+		/*
+		 * Restore fpu state:
+		 *  - cp0 status register bits
+		 *  - fp gp registers
+		 *  - cp1 status/control register
+		 */
+		ori	t1,a2,1				# pipeline magic
+		xori	t1,1
+		mtc0	t1,CP0_STATUS
+		sll	t0,a2,2
+		bgez	t0,2f
+		sll	t0,a2,5				# delay slot
+		bgez	t0,1f
+		ldc1	$f0,(TOFF_FPU+0)(a0)		# delay slot
+		/*
+		 * Restore the 16 odd double precision registers only
+		 * when enabled in the cp0 status register.
+		 */
+		ldc1	$f1,(TOFF_FPU+8)(a0)
+		ldc1	$f3,(TOFF_FPU+24)(a0)
+		ldc1	$f5,(TOFF_FPU+40)(a0)
+		ldc1	$f7,(TOFF_FPU+56)(a0)
+		ldc1	$f9,(TOFF_FPU+72)(a0)
+		ldc1	$f11,(TOFF_FPU+88)(a0)
+		ldc1	$f13,(TOFF_FPU+104)(a0)
+		ldc1	$f15,(TOFF_FPU+120)(a0)
+		ldc1	$f17,(TOFF_FPU+136)(a0)
+		ldc1	$f19,(TOFF_FPU+152)(a0)
+		ldc1	$f21,(TOFF_FPU+168)(a0)
+		ldc1	$f23,(TOFF_FPU+184)(a0)
+		ldc1	$f25,(TOFF_FPU+200)(a0)
+		ldc1	$f27,(TOFF_FPU+216)(a0)
+		ldc1	$f29,(TOFF_FPU+232)(a0)
+		ldc1	$f31,(TOFF_FPU+248)(a0)
+
+		/*
+		 * Restore the 16 even double precision registers
+		 * when cp1 was enabled in the cp0 status register.
+		 */
+1:		lw	t0,(TOFF_FPU+256)(a0)
+		ldc1	$f2,(TOFF_FPU+16)(a0)
+		ldc1	$f4,(TOFF_FPU+32)(a0)
+		ldc1	$f6,(TOFF_FPU+48)(a0)
+		ldc1	$f8,(TOFF_FPU+64)(a0)
+		ldc1	$f10,(TOFF_FPU+80)(a0)
+		ldc1	$f12,(TOFF_FPU+96)(a0)
+		ldc1	$f14,(TOFF_FPU+112)(a0)
+		ldc1	$f16,(TOFF_FPU+128)(a0)
+		ldc1	$f18,(TOFF_FPU+144)(a0)
+		ldc1	$f20,(TOFF_FPU+160)(a0)
+		ldc1	$f22,(TOFF_FPU+176)(a0)
+		ldc1	$f24,(TOFF_FPU+192)(a0)
+		ldc1	$f26,(TOFF_FPU+208)(a0)
+		ldc1	$f28,(TOFF_FPU+224)(a0)
+		ldc1	$f30,(TOFF_FPU+240)(a0)
+		ctc1	t0,fcr31
+
+		/*
+		 * Restore non-scratch registers
+		 */
+2:		lw	s0,TOFF_REG16(a0)
+		lw	s1,TOFF_REG17(a0)
+		lw	s2,TOFF_REG18(a0)
+		lw	s3,TOFF_REG19(a0)
+		lw	s4,TOFF_REG20(a0)
+		lw	s5,TOFF_REG21(a0)
+		lw	s6,TOFF_REG22(a0)
+		lw	s7,TOFF_REG23(a0)
+		lw	gp,TOFF_REG28(a0)
+		lw	sp,TOFF_REG29(a0)
+		lw	fp,TOFF_REG30(a0)
+		lw	ra,TOFF_REG31(a0)
+
+		/*
+		 * Restore status register
+		 */
+		lw	t0,TOFF_KSP(a0)
+		sw	t0,kernelsp
+
+		jr	ra
+		mtc0	a2,CP0_STATUS			# delay slot
+		END(resume)
+
+		/*
+		 * Load a new root pointer into the tlb
+		 */
+		.set	noreorder
+		LEAF(load_pgd)
+		/*
+		 * Switch the root pointer
+		 */
+		mfc0	t0,CP0_STATUS
+		ori	t1,t0,1
+		xori	t1,1
+		mtc0	t1,CP0_STATUS
+		srl	a0,6
+		ori	a0,MODE_ALIAS
+		li	t1,TLB_ROOT
+		mtc0	t1,CP0_ENTRYHI
+		mtc0	zero,CP0_INDEX
+		mtc0	a0,CP0_ENTRYLO0
+		mtc0	zero,CP0_ENTRYLO1
+		mtc0	t0,CP0_STATUS
+		j	tlbflush
+		tlbwi 					# delay slot
+		END(load_pgd)
+
+/*
+ * Some bits in the config register
+ */
+#define CONFIG_DB       (1<<4)
+#define CONFIG_IB       (1<<5)
+
+/*
+ * Flush instruction/data caches
+ *
+ * Parameters: a0 - starting address to flush
+ *             a1 - size of area to be flushed
+ *             a2 - which caches to be flushed
+ *
+ * FIXME:      - ignores parameters in a0/a1
+ *             - doesn't know about second level caches
+ */
+		.set	noreorder
+		LEAF(sys_cacheflush)
+		andi	t1,a2,DCACHE
+		beqz	t1,do_icache
+		li	t0,KSEG0			# delay slot
+
+		/*
+		 * Writeback data cache, even lines
+		 */
+		li	t1,CACHELINES-1
+1:		cache	Index_Writeback_Inv_D,0(t0)
+		cache	Index_Writeback_Inv_D,32(t0)
+		cache	Index_Writeback_Inv_D,64(t0)
+		cache	Index_Writeback_Inv_D,96(t0)
+		cache	Index_Writeback_Inv_D,128(t0)
+		cache	Index_Writeback_Inv_D,160(t0)
+		cache	Index_Writeback_Inv_D,192(t0)
+		cache	Index_Writeback_Inv_D,224(t0)
+		cache	Index_Writeback_Inv_D,256(t0)
+		cache	Index_Writeback_Inv_D,288(t0)
+		cache	Index_Writeback_Inv_D,320(t0)
+		cache	Index_Writeback_Inv_D,352(t0)
+		cache	Index_Writeback_Inv_D,384(t0)
+		cache	Index_Writeback_Inv_D,416(t0)
+		cache	Index_Writeback_Inv_D,448(t0)
+		cache	Index_Writeback_Inv_D,480(t0)
+		addiu	t0,512
+		bnez	t1,1b
+		subu	t1,1
+
+		/*
+		 * Writeback data cache, odd lines
+		 * Only needed for 16 byte line size
+		 */
+		mfc0	t1,CP0_CONFIG
+		andi	t1,CONFIG_DB
+		bnez	t1,do_icache
+		li	t1,CACHELINES-1
+1:		cache	Index_Writeback_Inv_D,16(t0)
+		cache	Index_Writeback_Inv_D,48(t0)
+		cache	Index_Writeback_Inv_D,80(t0)
+		cache	Index_Writeback_Inv_D,112(t0)
+		cache	Index_Writeback_Inv_D,144(t0)
+		cache	Index_Writeback_Inv_D,176(t0)
+		cache	Index_Writeback_Inv_D,208(t0)
+		cache	Index_Writeback_Inv_D,240(t0)
+		cache	Index_Writeback_Inv_D,272(t0)
+		cache	Index_Writeback_Inv_D,304(t0)
+		cache	Index_Writeback_Inv_D,336(t0)
+		cache	Index_Writeback_Inv_D,368(t0)
+		cache	Index_Writeback_Inv_D,400(t0)
+		cache	Index_Writeback_Inv_D,432(t0)
+		cache	Index_Writeback_Inv_D,464(t0)
+		cache	Index_Writeback_Inv_D,496(t0)
+		addiu	t0,512
+		bnez	t1,1b
+		subu	t1,1
+
+do_icache:	andi	t1,a2,ICACHE
+		beqz	t1,done
+
+		/*
+		 * Flush instruction cache, even lines
+		 */
+		lui	t0,0x8000
+		li	t1,CACHELINES-1
+1: 		cache	Index_Invalidate_I,0(t0)	
+		cache	Index_Invalidate_I,32(t0)
+		cache	Index_Invalidate_I,64(t0)
+		cache	Index_Invalidate_I,96(t0)
+		cache	Index_Invalidate_I,128(t0)
+		cache	Index_Invalidate_I,160(t0)
+		cache	Index_Invalidate_I,192(t0)
+		cache	Index_Invalidate_I,224(t0)
+		cache	Index_Invalidate_I,256(t0)
+		cache	Index_Invalidate_I,288(t0)
+		cache	Index_Invalidate_I,320(t0)
+		cache	Index_Invalidate_I,352(t0)
+		cache	Index_Invalidate_I,384(t0)
+		cache	Index_Invalidate_I,416(t0)
+		cache	Index_Invalidate_I,448(t0)
+		cache	Index_Invalidate_I,480(t0)
+		addiu	t0,512
+		bnez	t1,1b
+		subu	t1,1
+
+		/*
+		 * Flush instruction cache, even lines
+		 * Only needed for 16 byte line size
+		 */
+		mfc0	t1,CP0_CONFIG
+		andi	t1,CONFIG_IB
+		bnez	t1,done
+		li	t1,CACHELINES-1
+1:		cache	Index_Invalidate_I,16(t0)
+		cache	Index_Invalidate_I,48(t0)
+		cache	Index_Invalidate_I,80(t0)
+		cache	Index_Invalidate_I,112(t0)
+		cache	Index_Invalidate_I,144(t0)
+		cache	Index_Invalidate_I,176(t0)
+		cache	Index_Invalidate_I,208(t0)
+		cache	Index_Invalidate_I,240(t0)
+		cache	Index_Invalidate_I,272(t0)
+		cache	Index_Invalidate_I,304(t0)
+		cache	Index_Invalidate_I,336(t0)
+		cache	Index_Invalidate_I,368(t0)
+		cache	Index_Invalidate_I,400(t0)
+		cache	Index_Invalidate_I,432(t0)
+		cache	Index_Invalidate_I,464(t0)
+		cache	Index_Invalidate_I,496(t0)
+		addiu	t0,512
+		bnez	t1,1b
+		subu	t1,1
+
+done:		j	ra
+		nop
+		END(sys_cacheflush)
+
+/*
+ * Update the TLB - or how instruction scheduling makes code unreadable ...
+ *
+ * MIPS doesn't need any external MMU info: the kernel page tables contain
+ * all the necessary information.  We use this hook though to load the
+ * TLB as early as possible with uptodate information avoiding unecessary
+ * exceptions.
+ *
+ * Parameters: a0 - struct vm_area_struct *vma	(ignored)
+ *             a1 - unsigned long address
+ *             a2 - pte_t pte
+ */
+		.set	noreorder
+		LEAF(update_mmu_cache)
+		/*
+		 * Step 1: Wipe out old TLB information.  Not shure if
+		 * we really need that step; call it paranoia ...
+		 * In order to do that we need to disable interrupts.
+		 */
+		mfc0	t0,CP0_STATUS		# interrupts off
+		ori	t1,t0,1
+		xori	t1,1
+		mtc0	t1,CP0_STATUS
+		li	t3,TLBMAP		# then wait 3 cycles
+		ori	t1,a1,0xfff		# mask off low 12 bits
+		xori	t1,0xfff
+		mfc0	t2,CP0_ENTRYHI		# copy ASID into address
+		andi	t2,0xff
+		or	t2,t1
+		mtc0	t2,CP0_ENTRYHI
+		srl	t4,a1,12		# wait again three cycles
+		sll	t4,t4,PTRLOG
+		dmtc0	zero,CP0_ENTRYLO0
+		tlbp				# now query the TLB
+		addu	t3,t4			# wait another three cycles
+		ori	t3,0xffff
+		xori	t3,0xffff
+		mfc0	t1,CP0_INDEX
+		bltz	t1,1f			# No old entry?
+		dmtc0	zero,CP0_ENTRYLO1
+		or	t3,t1			# wait one cycle
+		tlbwi
+		/*
+		 * But there still might be a entry for the pgd ...
+		 */
+1:		mtc0	t3,CP0_ENTRYHI
+		nop				# wait 3 cycles
+		nop
+		nop
+		tlbp				# TLB lookup
+		nop
+		nop
+		mfc0	t1,CP0_INDEX		# wait 3 cycles
+		bltz	t1,1f			# No old entry?
+		nop		
+		tlbwi				# gotcha ...
+		/*
+		 * Step 2: Reload the TLB with new information.  We can skip
+		 * this but this should speed the mess a bit by avoiding
+		 * tlbl/tlbs exceptions. (To be done)
+		 */
+1:		jr	ra
+		mtc0	t0,CP0_STATUS		# delay slot
+		END(update_mmu_cache)
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/resume.S linux/arch/mips/kernel/resume.S
--- v1.3.47/linux/arch/mips/kernel/resume.S	Wed Jan 25 08:54:22 1995
+++ linux/arch/mips/kernel/resume.S	Thu Jan  1 02:00:00 1970
@@ -1,250 +0,0 @@
-/*
- *  linux/kernel/mips/sys_call.S
- *
- *  Copyright (C) 1994, 1995 Waldorf Electronics
- *  written by Ralf Baechle
- */
-
-/*
- * sys_call.S  contains the system-call and fault low-level handling routines.
- * This also contains the timer-interrupt handler, as well as all interrupts
- * and faults that can result in a task-switch.
- */
-
-#include <asm/regdef.h>
-#include <asm/processor.h>
-#include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
-
-/*
- * These are offsets into the task-struct.
- */
-state		=  0
-counter		=  4
-priority	=  8
-signal		= 12
-blocked		= 16
-flags		= 20
-errno		= 24			#/* MIPS OK */
-exec_domain	= 60			#/* ??? */
-
-ENOSYS		= 38
-
-/*
- * Code necessary to switch tasks on an Linux/MIPS machine.
- */
-MODE_ALIAS	=	0x0016			# uncachable
-
-		.text
-		.set	noreorder
-		.set	at
-
-		.globl	_resume
-_resume:
-		/*
-		 * current task's task_struct
-		 */
-		lui	t5,%hi(_current)
-		lw	t0,%lo(_current)(t5)
-
-		/*
-		 * Save status register
-		 */
-		mfc0	t1,CP0_STATUS
-		addu	t0,a1			# Add tss offset
-		sw	t1,TOFF_CP0_STATUS(t0)
-
-		/*
-		 * Disable interrupts
-		 */
-		ori	t2,t1,0x1f
-		xori	t2,0x1e
-		mtc0	t2,CP0_STATUS
-
-		/*
-		 * Save non-scratch registers
-		 * All other registers have been saved on the kernel stack
-		 */
-		sw	s0,TOFF_REG16(t0)
-		sw	s1,TOFF_REG17(t0)
-		sw	s2,TOFF_REG18(t0)
-		sw	s3,TOFF_REG19(t0)
-		sw	s4,TOFF_REG20(t0)
-		sw	s5,TOFF_REG21(t0)
-		sw	s6,TOFF_REG22(t0)
-		sw	s7,TOFF_REG23(t0)
-		sw	gp,TOFF_REG28(t0)
-		sw	sp,TOFF_REG29(t0)
-		sw	fp,TOFF_REG30(t0)
-		sw	ra,TOFF_REG31(t0)
-
-		/*
-		 * Save floating point state
-		 */
-		srl	t2,t1,29
-		andi	t2,1
-		beqz	t2,2f
-		srl	t2,t1,26
-		andi	t2,1
-		beqz	t2,1f
-		sdc1	$f0,(TOFF_FPU+0)(t0)	# delay slot
-		/*
-		 * Store the 16 odd double precision registers
-		 */
-		sdc1	$f1,(TOFF_FPU+8)(t0)
-		sdc1	$f3,(TOFF_FPU+24)(t0)
-		sdc1	$f5,(TOFF_FPU+40)(t0)
-		sdc1	$f7,(TOFF_FPU+56)(t0)
-		sdc1	$f9,(TOFF_FPU+72)(t0)
-		sdc1	$f11,(TOFF_FPU+88)(t0)
-		sdc1	$f13,(TOFF_FPU+104)(t0)
-		sdc1	$f15,(TOFF_FPU+120)(t0)
-		sdc1	$f17,(TOFF_FPU+136)(t0)
-		sdc1	$f19,(TOFF_FPU+152)(t0)
-		sdc1	$f21,(TOFF_FPU+168)(t0)
-		sdc1	$f23,(TOFF_FPU+184)(t0)
-		sdc1	$f25,(TOFF_FPU+200)(t0)
-		sdc1	$f27,(TOFF_FPU+216)(t0)
-		sdc1	$f29,(TOFF_FPU+232)(t0)
-		sdc1	$f31,(TOFF_FPU+248)(t0)
-
-		/*
-		 * Store the 16 even double precision registers
-		 */
-1:		cfc1	t1,$31
-		sdc1	$f2,(TOFF_FPU+16)(t0)
-		sdc1	$f4,(TOFF_FPU+32)(t0)
-		sdc1	$f6,(TOFF_FPU+48)(t0)
-		sdc1	$f8,(TOFF_FPU+64)(t0)
-		sdc1	$f10,(TOFF_FPU+80)(t0)
-		sdc1	$f12,(TOFF_FPU+96)(t0)
-		sdc1	$f14,(TOFF_FPU+112)(t0)
-		sdc1	$f16,(TOFF_FPU+128)(t0)
-		sdc1	$f18,(TOFF_FPU+144)(t0)
-		sdc1	$f20,(TOFF_FPU+160)(t0)
-		sdc1	$f22,(TOFF_FPU+176)(t0)
-		sdc1	$f24,(TOFF_FPU+192)(t0)
-		sdc1	$f26,(TOFF_FPU+208)(t0)
-		sdc1	$f28,(TOFF_FPU+224)(t0)
-		sdc1	$f30,(TOFF_FPU+240)(t0)
-		sw	t1,(TOFF_FPU+256)(t0)
-
-		/*
-		 * Switch current task
-		 */
-2:		sw	a0,%lo(_current)(t5)
-		addu	a0,a1			# Add tss offset
-
-		/*
-		 * Switch address space
-		 */
-
-		/*
-		 * (Choose new ASID for process)
-		 */
-
-		/*
-		 * Switch the root pointer
-		 */
-		lw	t0,TOFF_PG_DIR(a0)
-		la	t1,TLB_ROOT
-		mtc0	t1,CP0_ENTRYHI
-		mtc0	zero,CP0_INDEX
-		srl	t0,6
-		ori	t0,MODE_ALIAS
-		mtc0	t0,CP0_ENTRYLO0
-		mtc0	zero,CP0_ENTRYLO1
-		tlbwi
-
-		/*
-		 * Flush tlb (probably not needed)
-		 * (Doesn't clobber a0-a3)
-		 */
-		jal	_tlbflush
-		nop 					# delay slot
-
-		lw	a2,TOFF_CP0_STATUS(a0)
-
-		/*
-		 * Restore fpu state:
-		 *  - cp0 status register bits
-		 *  - fp gp registers
-		 *  - cp1 status/control register
-		 */
-		ori	t1,a2,1				# pipeline magic
-		xori	t1,1
-		mtc0	t1,CP0_STATUS
-		srl	t0,a2,29
-		andi	t0,1
-		beqz	t0,2f
-		srl	t0,a2,26
-		andi	t0,1
-		beqz	t0,1f
-		ldc1	$f0,(TOFF_FPU+0)(a0)	# delay slot
-		/*
-		 * Restore the 16 odd double precision registers only
-		 * when enabled in the cp0 status register.
-		 */
-		ldc1	$f1,(TOFF_FPU+8)(a0)
-		ldc1	$f3,(TOFF_FPU+24)(a0)
-		ldc1	$f5,(TOFF_FPU+40)(a0)
-		ldc1	$f7,(TOFF_FPU+56)(a0)
-		ldc1	$f9,(TOFF_FPU+72)(a0)
-		ldc1	$f11,(TOFF_FPU+88)(a0)
-		ldc1	$f13,(TOFF_FPU+104)(a0)
-		ldc1	$f15,(TOFF_FPU+120)(a0)
-		ldc1	$f17,(TOFF_FPU+136)(a0)
-		ldc1	$f19,(TOFF_FPU+152)(a0)
-		ldc1	$f21,(TOFF_FPU+168)(a0)
-		ldc1	$f23,(TOFF_FPU+184)(a0)
-		ldc1	$f25,(TOFF_FPU+200)(a0)
-		ldc1	$f27,(TOFF_FPU+216)(a0)
-		ldc1	$f29,(TOFF_FPU+232)(a0)
-		ldc1	$f31,(TOFF_FPU+248)(a0)
-
-		/*
-		 * Restore the 16 even double precision registers always
-		 * when cp1 was enabled in the cp0 status register.
-		 */
-1:		lw	t0,(TOFF_FPU+256)(a0)
-		ldc1	$f2,(TOFF_FPU+16)(a0)
-		ldc1	$f4,(TOFF_FPU+32)(a0)
-		ldc1	$f6,(TOFF_FPU+48)(a0)
-		ldc1	$f8,(TOFF_FPU+64)(a0)
-		ldc1	$f10,(TOFF_FPU+80)(a0)
-		ldc1	$f12,(TOFF_FPU+96)(a0)
-		ldc1	$f14,(TOFF_FPU+112)(a0)
-		ldc1	$f16,(TOFF_FPU+128)(a0)
-		ldc1	$f18,(TOFF_FPU+144)(a0)
-		ldc1	$f20,(TOFF_FPU+160)(a0)
-		ldc1	$f22,(TOFF_FPU+176)(a0)
-		ldc1	$f24,(TOFF_FPU+192)(a0)
-		ldc1	$f26,(TOFF_FPU+208)(a0)
-		ldc1	$f28,(TOFF_FPU+224)(a0)
-		ldc1	$f30,(TOFF_FPU+240)(a0)
-		ctc1	t0,$31
-
-		/*
-		 * Restore non-scratch registers
-		 */
-2:		lw	s0,TOFF_REG16(a0)
-		lw	s1,TOFF_REG17(a0)
-		lw	s2,TOFF_REG18(a0)
-		lw	s3,TOFF_REG19(a0)
-		lw	s4,TOFF_REG20(a0)
-		lw	s5,TOFF_REG21(a0)
-		lw	s6,TOFF_REG22(a0)
-		lw	s7,TOFF_REG23(a0)
-		lw	gp,TOFF_REG28(a0)
-		lw	sp,TOFF_REG29(a0)
-		lw	fp,TOFF_REG30(a0)
-		lw	ra,TOFF_REG31(a0)
-
-		/*
-		 * Restore status register
-		 */
-		lw	t0,TOFF_KSP(a0)
-		sw	t0,_kernelsp
-
-		jr	ra
-		mtc0	a2,CP0_STATUS			# delay slot
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- v1.3.47/linux/arch/mips/kernel/setup.c	Mon Sep 18 14:53:48 1995
+++ linux/arch/mips/kernel/setup.c	Wed Dec 13 12:39:44 1995
@@ -2,13 +2,16 @@
  *  linux/arch/mips/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
+ *  Copyright (C) 1995  Ralf Baechle
  */
-
+#include <linux/config.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
+#include <linux/string.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
@@ -17,11 +20,164 @@
 #include <linux/a.out.h>
 #include <linux/tty.h>
 
+#include <asm/asm.h>
 #include <asm/bootinfo.h>
+#include <asm/vector.h>
 #include <asm/segment.h>
+#include <asm/stackframe.h>
 #include <asm/system.h>
 
 /*
+ * How to handle the machine's features
+ */
+struct feature *feature;
+
+#ifdef CONFIG_ACER_PICA_61
+void acer_pica_61_handle_int(void);
+/*
+ * How to access the floppy controller's ports
+ */
+unsigned char jazz_fd_inb(unsigned int port);
+void jazz_fd_outb(unsigned char value, unsigned int port);
+/*
+ * How to access the floppy DMA functions.
+ */
+void jazz_fd_enable_dma(void);
+void jazz_fd_disable_dma(void);
+int jazz_fd_request_dma(void);
+void jazz_fd_free_dma(void);
+void jazz_fd_clear_dma_ff(void);
+void jazz_fd_set_dma_mode(char mode);
+void jazz_fd_set_dma_addr(unsigned int a);
+void jazz_fd_set_dma_count(unsigned int count);
+int jazz_fd_get_dma_residue(void);
+void jazz_fd_enable_irq(void);
+void jazz_fd_disable_irq(void);
+void jazz_fd_cacheflush(unsigned char *addr, unsigned int size);
+/*
+ * How to access the RTC functions.
+ */
+unsigned char jazz_rtc_read_data(void);
+void jazz_rtc_write_data(unsigned char data);
+
+struct feature acer_pica_61_feature = {
+	acer_pica_61_handle_int,
+	/*
+	 * How to access the floppy controller's ports
+	 */
+	jazz_fd_inb,
+	jazz_fd_outb,
+	/*
+	 * How to access the floppy DMA functions.
+	 */
+	jazz_fd_enable_dma,
+	jazz_fd_disable_dma,
+	jazz_fd_request_dma,
+	jazz_fd_free_dma,
+	jazz_fd_clear_dma_ff,
+	jazz_fd_set_dma_mode,
+	jazz_fd_set_dma_addr,
+	jazz_fd_set_dma_count,
+	jazz_fd_get_dma_residue,
+	jazz_fd_enable_irq,
+	jazz_fd_disable_irq,
+	jazz_fd_cacheflush,
+	/*
+	 * How to access the RTC functions.
+	 */
+	jazz_rtc_read_data,
+	jazz_rtc_write_data
+};
+#endif
+#ifdef CONFIG_DECSTATION
+void decstation_handle_handle_int(void);
+void isa_outb(unsigned char value, unsigned int port);
+unsigned char isa_inb(unsigned int port);
+struct feature decstation_feature = {
+	decstation_handle_handle_int,
+	isa_inb /* Dummy - dunno how to handle this yet */
+	isa_outb, /* Dummy - dunno how to handle this yet */
+};
+#endif
+#ifdef CONFIG_DESKSTATION_RPC44
+void deskstation_rpc44_handle_int(void);
+void isa_outb(unsigned char value, unsigned int port);
+unsigned char isa_inb(unsigned int port);
+struct feature deskstation_rpc44_feature = {
+	deskstation_rpc44_handle_int,
+	isa_inb
+	isa_outb,
+};
+#endif
+#ifdef CONFIG_DESKSTATION_TYNE
+void deskstation_tyne_handle_int(void);
+void isa_outb(unsigned char value, unsigned int port);
+unsigned char isa_inb(unsigned int port);
+struct feature deskstation_tyne_feature = {
+	deskstation_tyne_handle_int,
+	isa_inb,
+	isa_outb,
+};
+#endif
+#ifdef CONFIG_MIPS_MAGNUM_4000
+void mips_magnum_4000_handle_int(void);
+/*
+ * How to access the floppy controller's ports
+ */
+unsigned char jazz_fd_inb(unsigned int port);
+void jazz_fd_outb(unsigned char value, unsigned int port);
+/*
+ * How to access the floppy DMA functions.
+ */
+void jazz_fd_enable_dma(void);
+void jazz_fd_disable_dma(void);
+int jazz_fd_request_dma(void);
+void jazz_fd_free_dma(void);
+void jazz_fd_clear_dma_ff(void);
+void jazz_fd_set_dma_mode(char mode);
+void jazz_fd_set_dma_addr(unsigned int a);
+void jazz_fd_set_dma_count(unsigned int count);
+int jazz_fd_get_dma_residue(void);
+void jazz_fd_enable_irq(void);
+void jazz_fd_disable_irq(void);
+void jazz_fd_cacheflush(unsigned char *addr, unsigned int size);
+/*
+ * How to access the RTC functions.
+ */
+unsigned char jazz_rtc_read_data(void);
+void jazz_rtc_write_data(unsigned char data);
+
+struct feature mips_magnum_4000_feature = {
+	mips_magnum_4000_handle_int,
+	/*
+	 * How to access the floppy controller's ports
+	 */
+	jazz_fd_inb,
+	jazz_fd_outb,
+	/*
+	 * How to access the floppy DMA functions.
+	 */
+	jazz_fd_enable_dma,
+	jazz_fd_disable_dma,
+	jazz_fd_request_dma,
+	jazz_fd_free_dma,
+	jazz_fd_clear_dma_ff,
+	jazz_fd_set_dma_mode,
+	jazz_fd_set_dma_addr,
+	jazz_fd_set_dma_count,
+	jazz_fd_get_dma_residue,
+	jazz_fd_enable_irq,
+	jazz_fd_disable_irq,
+	jazz_fd_cacheflush,
+	/*
+	 * How to access the RTC functions.
+	 */
+	jazz_rtc_read_data,
+	jazz_rtc_write_data
+};
+#endif
+
+/*
  * Tell us the machine setup..
  */
 char wait_available;		/* set if the "wait" instruction available */
@@ -35,12 +191,12 @@
  * Setup options
  */
 struct drive_info_struct drive_info;
-struct screen_info screen_info;
+struct screen_info screen_info = SCREEN_INFO;
 
 unsigned char aux_device_present;
 extern int ramdisk_size;
 extern int root_mountflags;
-extern int end;
+extern int _end;
 
 extern char empty_zero_page[PAGE_SIZE];
 
@@ -54,61 +210,137 @@
  * This is set up by the setup-routine at boot-time
  */
 #define PARAM	empty_zero_page
-#define EXT_MEM (boot_info.memupper)
-#define DRIVE_INFO (boot_info.drive_info)
-#define SCREEN_INFO (screen_info)
-#define MOUNT_ROOT_RDONLY (boot_info.mount_root_rdonly)
-#define RAMDISK_SIZE (boot_info.ramdisk_size)
 #if 0
 #define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
 #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
 #endif
-#define COMMAND_LINE (boot_info.command_line)
 
 static char command_line[CL_SIZE] = { 0, };
 
+#if 0
+/*
+ * Code for easy access to new style bootinfo
+ *
+ * Parameter:  tag      -- taglist entry
+ *
+ * returns  :  (tag *) -- pointer to taglist entry, NULL for not found
+ */
+tag *
+bi_TagFind(enum bi_tag tag)
+{
+	/* TBD */
+	return 0;
+}
+
+/*
+ * Only for taglist creators (bootloaders)
+ *
+ * Parameter:  tag       -- (enum bi_tag) taglist entry
+ *
+ * returns  :  1         -- success
+ *             0         -- failure
+ */
+int
+bi_TagAdd(enum bi_tag tag, unsigned long size, void *tagdata)
+{
+	/* TBD */
+	return 0;
+}
+#endif /* 0 */
+
 void setup_arch(char **cmdline_p,
 	unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	unsigned long memory_start, memory_end;
-	char c = ' ', *to = command_line, *from = COMMAND_LINE;
-	int len = 0;
+
+	switch(boot_info.machtype)
+	{
+#ifdef CONFIG_ACER_PICA_61
+	case MACH_ACER_PICA_61:
+		feature = &acer_pica_61_feature;
+		break;
+#endif
+#ifdef CONFIG_DECSTATION
+	case MACH_DECSTATION:
+		feature = &decstation_feature;
+		break;
+#endif
+#ifdef CONFIG_DESKSTATION_RPC
+	case MACH_DESKSTATION_RPC:
+		feature = &deskstation_rpc44_feature;
+		break;
+#endif
+#ifdef CONFIG_DESKSTATION_TYNE
+	case MACH_DESKSTATION_TYNE:
+		feature = &deskstation_tyne_feature;
+		break;
+#endif
+#ifdef CONFIG_MIPS_MAGNUM_4000
+	case MACH_MIPS_MAGNUM_4000:
+		feature = &mips_magnum_4000_feature;
+		break;
+#endif
+	default:
+		panic("Unsupported architecture");
+	}
 
 #if 0
  	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
+#else
+#ifdef CONFIG_BLK_DEV_FD
+	ROOT_DEV = to_kdev_t(0x021c);	/* fd0H1440 */
+#else
+	ROOT_DEV = to_kdev_t(0x0101);	/* ram */ 
 #endif
- 	drive_info = DRIVE_INFO;
- 	screen_info = SCREEN_INFO;
+/*	ROOT_DEV = to_kdev_t(0x00ff); */	/* NFS */
+#endif
+ 	memcpy(&drive_info, &boot_info.drive_info, sizeof(drive_info));
 #if 0
 	aux_device_present = AUX_DEVICE_INFO;
 #endif
-	memory_end = EXT_MEM;
+	memory_end = boot_info.memupper;
 	memory_end &= PAGE_MASK;
-	ramdisk_size = RAMDISK_SIZE;
-	if (MOUNT_ROOT_RDONLY)
+	ramdisk_size = boot_info.ramdisk_size;
+	if (boot_info.mount_root_rdonly)
 		root_mountflags |= MS_RDONLY;
-	memory_start = (unsigned long) &end - KERNELBASE;
 
-	for (;;) {
-		if (c == ' ' && *(unsigned long *)from == *(unsigned long *)"mem=") {
-			memory_end = simple_strtoul(from+4, &from, 0);
-			if ( *from == 'K' || *from == 'k' ) {
-				memory_end = memory_end << 10;
-				from++;
-			} else if ( *from == 'M' || *from == 'm' ) {
-				memory_end = memory_end << 20;
-				from++;
-			}
-		}
-		c = *(from++);
-		if (!c)
-			break;
-		if (CL_SIZE <= ++len)
-			break;
-		*(to++) = c;
-	}
-	*to = '\0';
+	memory_start = (unsigned long) &_end;
+	memory_start += (ramdisk_size << 10);
+
 	*cmdline_p = command_line;
 	*memory_start_p = memory_start;
 	*memory_end_p = memory_end;
+
+#if 0
+	/*
+	 * Check that struct pt_regs is defined properly
+	 * (Should be optimized away, but gcc 2.6.3 is too bad..)
+	 */
+	if (FR_SIZE != sizeof(struct pt_regs) ||
+	    FR_SIZE & 7)
+	{
+		panic("Check_definition_of_struct_pt_regs\n");
+	}
+#endif
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * BUFFER is PAGE_SIZE bytes long.
+ */
+int get_cpuinfo(char *buffer)
+{
+	const char *cpu_name[] = CPU_NAMES;
+	const char *mach_name[] = MACH_NAMES;
+
+	return sprintf(buffer,
+		       "cpu\t\t\t: MIPS\n"
+		       "cpu model\t\t: %s\n"
+		       "system type\t\t: %s\n"
+		       "BogoMIPS\t\t: %lu.%02lu\n",
+
+		       cpu_name[boot_info.cputype < CPU_LAST ? boot_info.cputype : CPU_UNKNOWN],
+		       mach_name[boot_info.machtype < CPU_LAST ? boot_info.machtype : CPU_UNKNOWN],
+		       loops_per_sec / 500000, (loops_per_sec / 5000) % 100);
 }
+#endif /* CONFIG_PROC_FS */
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c
--- v1.3.47/linux/arch/mips/kernel/signal.c	Mon Jan 23 23:04:08 1995
+++ linux/arch/mips/kernel/signal.c	Wed Dec 13 12:39:44 1995
@@ -3,7 +3,6 @@
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
-
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
@@ -13,6 +12,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 
+#include <asm/bitops.h>
 #include <asm/segment.h>
 #include <asm/cachectl.h>
 
@@ -21,6 +21,7 @@
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 
 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
 
 /*
  * atomically swap in the new signal mask, and wait for a signal.
@@ -44,127 +45,187 @@
 /*
  * This sets regs->reg29 even though we don't actually use sigstacks yet..
  */
-asmlinkage int sys_sigreturn(unsigned long __unused)
+asmlinkage int sys_sigreturn(struct pt_regs *regs)
 {
-	struct sigcontext_struct context;
-	struct pt_regs * regs;
+	struct sigcontext_struct *context;
 
-	regs = (struct pt_regs *) &__unused;
-	if (verify_area(VERIFY_READ, (void *) regs->reg29, sizeof(context)))
+	/*
+	 * We don't support fixing ADEL/ADES exceptions for signal stack frames.
+	 * No big loss - who doesn't care about the alignment of this stack
+	 * really deserves to loose.
+	 */
+	context = (struct sigcontext_struct *) regs->reg29;
+	if (verify_area(VERIFY_READ, context, sizeof(struct sigcontext_struct)) ||
+	    (regs->reg29 & 3))
 		goto badframe;
-	memcpy_fromfs(&context,(void *) regs->reg29, sizeof(context));
-	current->blocked = context.oldmask & _BLOCKABLE;
-	regs->reg1  = context.sc_at;
-	regs->reg2  = context.sc_v0;
-	regs->reg3  = context.sc_v1;
-	regs->reg4  = context.sc_a0;
-	regs->reg5  = context.sc_a1;
-	regs->reg6  = context.sc_a2;
-	regs->reg7  = context.sc_a3;
-	regs->reg8  = context.sc_t0;
-	regs->reg9  = context.sc_t1;
-	regs->reg10 = context.sc_t2;
-	regs->reg11 = context.sc_t3;
-	regs->reg12 = context.sc_t4;
-	regs->reg13 = context.sc_t5;
-	regs->reg14 = context.sc_t6;
-	regs->reg15 = context.sc_t7;
-	regs->reg16 = context.sc_s0;
-	regs->reg17 = context.sc_s1;
-	regs->reg18 = context.sc_s2;
-	regs->reg19 = context.sc_s3;
-	regs->reg20 = context.sc_s4;
-	regs->reg21 = context.sc_s5;
-	regs->reg22 = context.sc_s6;
-	regs->reg23 = context.sc_s7;
-	regs->reg24 = context.sc_t8;
-	regs->reg25 = context.sc_t9;
+
+	current->blocked = context->sc_oldmask & _BLOCKABLE;
+	regs->reg1  = context->sc_at;
+	regs->reg2  = context->sc_v0;
+	regs->reg3  = context->sc_v1;
+	regs->reg4  = context->sc_a0;
+	regs->reg5  = context->sc_a1;
+	regs->reg6  = context->sc_a2;
+	regs->reg7  = context->sc_a3;
+	regs->reg8  = context->sc_t0;
+	regs->reg9  = context->sc_t1;
+	regs->reg10 = context->sc_t2;
+	regs->reg11 = context->sc_t3;
+	regs->reg12 = context->sc_t4;
+	regs->reg13 = context->sc_t5;
+	regs->reg14 = context->sc_t6;
+	regs->reg15 = context->sc_t7;
+	regs->reg16 = context->sc_s0;
+	regs->reg17 = context->sc_s1;
+	regs->reg18 = context->sc_s2;
+	regs->reg19 = context->sc_s3;
+	regs->reg20 = context->sc_s4;
+	regs->reg21 = context->sc_s5;
+	regs->reg22 = context->sc_s6;
+	regs->reg23 = context->sc_s7;
+	regs->reg24 = context->sc_t8;
+	regs->reg25 = context->sc_t9;
 	/*
 	 * Skip k0/k1
 	 */
-	regs->reg28 = context.sc_gp;
-	regs->reg29 = context.sc_sp;
-	regs->reg30 = context.sc_fp;
-	regs->reg31 = context.sc_ra;
-	regs->cp0_epc = context.sc_epc;
-	regs->cp0_cause = context.sc_cause;
+	regs->reg28 = context->sc_gp;
+	regs->reg29 = context->sc_sp;
+	regs->reg30 = context->sc_fp;
+	regs->reg31 = context->sc_ra;
+	regs->cp0_epc = context->sc_epc;
+	regs->cp0_cause = context->sc_cause;
 
 	/*
 	 * disable syscall checks
 	 */
 	regs->orig_reg2 = -1;
-	return regs->orig_reg2;
+	return context->sc_v0;
+
 badframe:
 	do_exit(SIGSEGV);
 }
 
 /*
  * Set up a signal frame...
+ *
+ * This routine is somewhat complicated by the fact that if the kernel may be
+ * entered by an exception other than a system call; e.g. a bus error or other
+ * "bad" exception.  If this is the case, then *all* the context on the kernel
+ * stack frame must be saved.
+ *
+ * For a large number of exceptions, the stack frame format is the same
+ * as that which will be created when the process traps back to the kernel
+ * when finished executing the signal handler.	In this case, nothing
+ * must be done. This information is saved on the user stack and restored
+ * when the signal handler is returned.
+ *
+ * The signal handler will be called with ra pointing to code1 (see below) and
+ * one parameters in a0 (signum).
+ *
+ *     usp ->  [unused]                         ; first free word on stack
+ *             arg save space                   ; 16 bytes argument save space
+ *	       code1   (addiu sp,#1-offset)	; syscall number
+ *	       code2   (li v0,__NR_sigreturn)	; syscall number
+ *	       code3   (syscall)		; do sigreturn(2)
+ *     #1|     at, v0, v1, a0, a1, a2, a3       ; All integer registers
+ *       |     t0, t1, t2, t3, t4, t5, t6, t7   ; except zero, k0 and k1
+ *       |     s0, s1, s2, s3, s4, s5, s6, s7
+ *       |     t8, t9, gp, sp, fp, ra;
+ *       |     epc                              ; old program counter
+ *       |     cause                            ; CP0 cause register
+ *       |     oldmask
  */
-static void setup_frame(struct sigaction * sa, unsigned long ** fp,
+
+struct sc {
+	unsigned long	ass[4];
+	unsigned int	code[4];
+	struct sigcontext_struct scc;
+};
+#define scc_offset ((size_t)&((struct sc *)0)->scc)
+
+static void setup_frame(struct sigaction * sa, struct sc **fp,
                         unsigned long pc, struct pt_regs *regs,
                         int signr, unsigned long oldmask)
 {
-	unsigned long * frame;
+	struct sc *frame;
 
 	frame = *fp;
-	frame -= 32;
-	if (verify_area(VERIFY_WRITE,frame,21*4))
-		do_exit(SIGSEGV);
+	frame--;
+
 	/*
-	 * set up the "normal" stack seen by the signal handler
+	 * We don't support fixing ADEL/ADES exceptions for signal stack frames.
+	 * No big loss - who doesn't care about the alignment of this stack
+	 * really deserves to loose.
 	 */
-	put_fs_long(regs->reg1 , frame   );
-	put_fs_long(regs->reg2 , frame+ 1);
-	put_fs_long(regs->reg3 , frame+ 2);
-	put_fs_long(regs->reg4 , frame+ 3);
-	put_fs_long(regs->reg5 , frame+ 4);
-	put_fs_long(regs->reg6 , frame+ 5);
-	put_fs_long(regs->reg7 , frame+ 6);
-	put_fs_long(regs->reg8 , frame+ 7);
-	put_fs_long(regs->reg9 , frame+ 8);
-	put_fs_long(regs->reg10, frame+ 9);
-	put_fs_long(regs->reg11, frame+10);
-	put_fs_long(regs->reg12, frame+11);
-	put_fs_long(regs->reg13, frame+12);
-	put_fs_long(regs->reg14, frame+13);
-	put_fs_long(regs->reg15, frame+14);
-	put_fs_long(regs->reg16, frame+15);
-	put_fs_long(regs->reg17, frame+16);
-	put_fs_long(regs->reg18, frame+17);
-	put_fs_long(regs->reg19, frame+18);
-	put_fs_long(regs->reg20, frame+19);
-	put_fs_long(regs->reg21, frame+20);
-	put_fs_long(regs->reg22, frame+21);
-	put_fs_long(regs->reg23, frame+22);
-	put_fs_long(regs->reg24, frame+23);
-	put_fs_long(regs->reg25, frame+24);
-	/*
-	 * Don't copy k0/k1
-	 */
-	put_fs_long(regs->reg28, frame+25);
-	put_fs_long(regs->reg29, frame+26);
-	put_fs_long(regs->reg30, frame+27);
-	put_fs_long(regs->reg31, frame+28);
-	put_fs_long(pc         , frame+29);
-	put_fs_long(oldmask    , frame+30);
+	if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)) ||
+	    ((unsigned long)frame & 3))
+		do_exit(SIGSEGV);
+
 	/*
-	 * set up the return code...
+	 * Set up the return code ...
 	 *
 	 *         .set    noreorder
-	 *         .set    noat
+	 *         addiu   sp,24
+	 *         li      v0,__NR_sigreturn
 	 *         syscall
-	 *         li      $1,__NR_sigreturn
-	 *         .set    at
 	 *         .set    reorder
 	 */
-	put_fs_long(0x24010077, frame+31);		/* li	$1,119 */
-	put_fs_long(0x000000c0, frame+32);		/* syscall     */
-	*fp = frame;
+	frame->code[0] = 0x27bd0000 + scc_offset;
+	frame->code[1] = 0x24020000 + __NR_sigreturn;
+	frame->code[2] = 0x0000000c;
+
 	/*
-	 * Flush caches so the instructions will be correctly executed.
+	 * Flush caches so that the instructions will be correctly executed.
+	 */
+	sys_cacheflush (frame->code, sizeof (frame->code), ICACHE);
+
+	/*
+	 * Set up the "normal" sigcontext_struct
+	 */
+	frame->scc.sc_at = regs->reg1;		/* Assembler temporary */
+	frame->scc.sc_v0 = regs->reg2;		/* Result registers */
+	frame->scc.sc_v1 = regs->reg3;
+	frame->scc.sc_a0 = regs->reg4;		/* Argument registers */
+	frame->scc.sc_a1 = regs->reg5;
+	frame->scc.sc_a2 = regs->reg6;
+	frame->scc.sc_a3 = regs->reg7;
+
+	frame->scc.sc_t0 = regs->reg8;		/* Caller saved */
+	frame->scc.sc_t1 = regs->reg9;
+	frame->scc.sc_t2 = regs->reg10;
+	frame->scc.sc_t3 = regs->reg11;
+	frame->scc.sc_t4 = regs->reg12;
+	frame->scc.sc_t5 = regs->reg13;
+	frame->scc.sc_t6 = regs->reg14;
+	frame->scc.sc_t7 = regs->reg15;
+
+	frame->scc.sc_s0 = regs->reg16;		/* Callee saved */
+	frame->scc.sc_s1 = regs->reg17;
+	frame->scc.sc_s2 = regs->reg18;
+	frame->scc.sc_s3 = regs->reg19;
+	frame->scc.sc_s4 = regs->reg20;
+	frame->scc.sc_s5 = regs->reg21;
+	frame->scc.sc_s6 = regs->reg22;
+	frame->scc.sc_s7 = regs->reg23;
+
+	frame->scc.sc_t8 = regs->reg24;		/* Caller saved */
+	frame->scc.sc_t9 = regs->reg25;
+
+	/*
+	 * Don't copy k0/k1
 	 */
-	sys_cacheflush(frame, 32*4, BCACHE);
+	frame->scc.sc_gp = regs->reg28;		/* global pointer / s8 */
+	frame->scc.sc_sp = regs->reg29;		/* old stack pointer */
+	frame->scc.sc_fp = regs->reg30;		/* old frame pointer */
+	frame->scc.sc_ra = regs->reg31;		/* old return address */
+
+	frame->scc.sc_epc = regs->cp0_epc;	/* Program counter */
+	frame->scc.sc_cause = regs->cp0_cause;	/* c0_epc register */
+
+	frame->scc.sc_oldmask = oldmask;
+	*fp = frame;
+
+	regs->reg4 = signr;             /* argument for handler */
 }
 
 /*
@@ -180,30 +241,15 @@
 {
 	unsigned long mask = ~current->blocked;
 	unsigned long handler_signal = 0;
-	unsigned long *frame = NULL;
+	struct sc *frame = NULL;
 	unsigned long pc = 0;
 	unsigned long signr;
 	struct sigaction * sa;
 
 	while ((signr = current->signal & mask)) {
-		__asm__(".set\tnoreorder\n\t"
-			".set\tnoat\n\t"
-			"li\t%0,31\n"
-			"1:\tsllv\t$1,%1,%0\n\t"
-			"bgezl\t$1,1b\n\t"
-			"subu\t$8,1\n\t"
-			"subu\t%0,31\n\t"
-			"subu\t%0,$0,%0\n\t"
-			"li\t$1,1\n\t"
-			"sllv\t$1,$1,%0\n\t"
-			"nor\t$1,$0\n\t"
-			"xor\t%1,$1\n\t"
-			".set\tat\n\t"
-			".set\treorder"
-			:"=r" (signr),"=r" (current->signal)
-			:"0"  (signr),"1"  (current->signal)
-			:"$1");
-		sa = current->sigaction + signr;
+		signr = ffz(~signr);
+		clear_bit(signr, &current->signal);
+		sa = current->sig->action + signr;
 		signr++;
 		if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
 			current->exit_code = signr;
@@ -219,7 +265,7 @@
 				current->signal |= _S(signr);
 				continue;
 			}
-			sa = current->sigaction + signr - 1;
+			sa = current->sig->action + signr - 1;
 		}
 		if (sa->sa_handler == SIG_IGN) {
 			if (signr != SIGCHLD)
@@ -241,14 +287,14 @@
 					continue;
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags & 
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & 
 						SA_NOCLDSTOP))
 					notify_parent(current);
 				schedule();
 				continue;
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
-			case SIGIOT: case SIGFPE: case SIGSEGV:
+			case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
 				if (current->binfmt && current->binfmt->core_dump) {
 					if (current->binfmt->core_dump(signr, regs))
 						signr |= 0x80;
@@ -271,42 +317,40 @@
 		handler_signal |= 1 << (signr-1);
 		mask &= ~sa->sa_mask;
 	}
+	/*
+	 * Who's code doesn't conform to the restartable syscall convention
+	 * dies here!!!  The li instruction, a single machine instruction,
+	 * must directly be followed by the syscall instruction.
+	 */
 	if (regs->orig_reg2 >= 0 &&
 	    (regs->reg2 == -ERESTARTNOHAND ||
 	     regs->reg2 == -ERESTARTSYS ||
-	     regs->reg2 == -ERESTARTNOINTR)) {
+	     regs->reg2 == -ERESTARTNOINTR))
+	{
 		regs->reg2 = regs->orig_reg2;
-		regs->cp0_epc -= 4;
+		regs->cp0_epc -= 8;
 	}
 	if (!handler_signal)		/* no handler will be called - return 0 */
 		return 0;
 	pc = regs->cp0_epc;
-	frame = (unsigned long *) regs->reg29;
+	frame = (struct sc *) regs->reg29;
 	signr = 1;
-	sa = current->sigaction;
+	sa = current->sig->action;
 	for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
 		if (mask > handler_signal)
 			break;
 		if (!(mask & handler_signal))
 			continue;
-		setup_frame(sa,&frame,pc,regs,signr,oldmask);
+		setup_frame(sa, &frame, pc, regs, signr, oldmask);
 		pc = (unsigned long) sa->sa_handler;
 		if (sa->sa_flags & SA_ONESHOT)
 			sa->sa_handler = NULL;
-		/*
-		 * force a kernel-mode page-in of the signal
-		 * handler to reduce races
-		 */
-		__asm__(".set\tnoat\n\t"
-			"lwu\t$1,(%0)\n\t"
-			".set\tat\n\t"
-			:
-			:"r" ((char *) pc)
-			:"$1");
 		current->blocked |= sa->sa_mask;
 		oldmask |= sa->sa_mask;
 	}
-	regs->reg29 = (unsigned long) frame;
+	regs->reg29 = (unsigned long) frame;		/* Stack pointer */
+	regs->reg31 = (unsigned long) frame->code;	/* Return address */
 	regs->cp0_epc = pc;		/* "return" to the first handler */
+
 	return 1;
 }
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c
--- v1.3.47/linux/arch/mips/kernel/syscall.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/syscall.c	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,225 @@
+/*
+ * MIPS specific syscall handling functions and syscalls
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <linux/unistd.h>
+#include <asm/ptrace.h>
+#include <asm/segment.h>
+#include <asm/signal.h>
+
+extern asmlinkage void syscall_trace(void);
+typedef asmlinkage int (*syscall_t)(void *a0,...);
+extern asmlinkage int do_syscalls(struct pt_regs *regs, syscall_t fun,
+                                  int narg);
+extern syscall_t sys_call_table[];
+extern unsigned char sys_narg_table[];
+
+asmlinkage int sys_pipe(struct pt_regs *regs)
+{
+	int fd[2];
+	int error;
+
+	error = do_pipe(fd);
+	if (error)
+		return error;
+	regs->reg2 = fd[0];
+	regs->reg3 = fd[1];
+	return 0;
+}
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
+                                  int flags, int fd, off_t offset)
+{
+	struct file * file = NULL;
+
+	if (flags & MAP_RENAME) {
+		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+			return -EBADF;
+	}
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+	return do_mmap(file, addr, len, prot, flags, offset);
+}
+
+asmlinkage int sys_idle(void)
+{
+	if (current->pid != 0)
+		return -EPERM;
+
+	/* endless idle loop with no priority at all */
+	current->counter = -100;
+	for (;;) {
+		/*
+		 * R4[26]00 have wait, R4[04]00 don't.
+		 */
+		if (wait_available && !need_resched)
+			__asm__(".set\tmips3\n\t"
+				"wait\n\t"
+				".set\tmips0\n\t");
+		schedule();
+	}
+}
+
+asmlinkage int sys_fork(struct pt_regs *regs)
+{
+	return do_fork(SIGCHLD, regs->reg29, regs);
+}
+
+asmlinkage int sys_clone(struct pt_regs *regs)
+{
+	unsigned long clone_flags;
+	unsigned long newsp;
+
+	clone_flags = regs->reg4;
+	newsp = regs->reg5;
+	if (!newsp)
+		newsp = regs->reg29;
+	return do_fork(clone_flags, newsp, regs);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(struct pt_regs *regs)
+{
+	int error;
+	char * filename;
+
+	error = getname((char *) regs->reg4, &filename);
+	if (error)
+		return error;
+	error = do_execve(filename, (char **) regs->reg5,
+	                  (char **) regs->reg6, regs);
+	putname(filename);
+	return error;
+}
+
+/*
+ * Do the indirect syscall syscall.
+ */
+asmlinkage int sys_syscall(unsigned long a0, unsigned long a1, unsigned long a2,
+                           unsigned long a3, unsigned long a4, unsigned long a5,
+                           unsigned long a6)
+{
+	syscall_t syscall;
+
+	if (a0 > __NR_Linux + __NR_Linux_syscalls)
+		return -ENOSYS;
+
+	syscall = sys_call_table[a0];
+	/*
+	 * Prevent stack overflow by recursive
+	 * syscall(__NR_syscall, __NR_syscall,...);
+	 */
+	if (syscall == (syscall_t) sys_syscall)
+		return -EINVAL;
+
+	if (syscall == NULL)
+		return -ENOSYS;
+
+	return syscall((void *)a0, a1, a2, a3, a4, a5, a6);
+}
+
+void do_sys(struct pt_regs *regs)
+{
+	unsigned long syscallnr, usp;
+	syscall_t syscall;
+	int errno, narg;
+
+	/*
+	 * Compute the return address;
+	 */
+	if (regs->cp0_cause & CAUSEF_BD)
+	{
+		/*
+		 * This syscall is in a branch delay slot.  Since we don't do
+		 * branch delay slot handling we would get a process trying
+		 * to do syscalls ever and ever again.  So better zap it.
+		 */
+		printk("%s: syscall in branch delay slot.\n", current->comm);
+		current->sig->action[SIGILL-1].sa_handler = NULL;
+		current->blocked &= ~(1<<(SIGILL-1));
+		send_sig(SIGILL, current, 1);
+		return;
+	}
+	regs->cp0_epc += 4;
+
+	syscallnr = regs->reg2;
+	if (syscallnr > (__NR_Linux + __NR_Linux_syscalls))
+		goto illegal_syscall;
+
+	syscall = sys_call_table[syscallnr];
+	if (syscall == NULL)
+		goto illegal_syscall;
+
+	narg = sys_narg_table[syscallnr];
+	if (narg > 4)
+	{
+		/*
+		 * Verify that we can savely get the additional parameters
+		 * from the user stack.  Of course I could read the params
+		 * from unaligned addresses ...  Consider this a programming
+		 * course caliber .45.
+		 */
+		usp = regs->reg29;
+		if (usp & 3)
+		{
+			printk("unaligned usp\n");
+			send_sig(SIGSEGV, current, 1);
+			regs->reg2 = EFAULT;
+			regs->reg7 = 1;
+			return;
+		}
+		errno = verify_area(VERIFY_READ, (void *) (usp + 16),
+		                    (narg - 4) * sizeof(unsigned long));
+		if (errno < 0)
+			goto bad_syscall;
+	}
+
+	if ((current->flags & PF_TRACESYS) == 0)
+	{
+		errno = do_syscalls(regs, syscall, narg);
+		if (errno < 0 || current->errno)
+			goto bad_syscall;
+
+		regs->reg2 = errno;
+		regs->reg7 = 0;
+	}
+	else
+	{
+		syscall_trace();
+
+		errno = do_syscalls(regs, syscall, narg);
+		if (errno < 0 || current->errno)
+		{
+			regs->reg2 = -errno;
+			regs->reg7 = 1;
+		}
+		else
+		{
+			regs->reg2 = errno;
+			regs->reg7 = 0;
+		}
+
+		syscall_trace();
+	}
+	return;
+
+bad_syscall:
+	regs->reg2 = -errno;
+	regs->reg7 = 1;
+	return;
+illegal_syscall:
+	regs->reg2 = ENOSYS;
+	regs->reg7 = 1;
+	return;
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h
--- v1.3.47/linux/arch/mips/kernel/syscalls.h	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/syscalls.h	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,176 @@
+/*
+ * List of Linux/MIPS syscalls.
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+
+/*
+ * This file is being included twice - once to build a list of all
+ * syscalls and once to build a table of how many arguments each syscall
+ * accepts.  Syscalls that receive a pointer to the saved registers are
+ * marked as having zero arguments.
+ *
+ * The binary compatibility calls are still missing in this list.
+ */
+SYS(sys_syscall, 7)				/* 4000 */
+SYS(sys_exit, 1)
+SYS(sys_fork, 0)
+SYS(sys_read, 3)
+SYS(sys_write, 3)
+SYS(sys_open, 3)				/* 4005 */
+SYS(sys_close, 3)
+SYS(sys_waitpid, 3)
+SYS(sys_creat, 2)
+SYS(sys_link, 2)
+SYS(sys_unlink, 1)				/* 4010 */
+SYS(sys_execve, 0)
+SYS(sys_chdir, 1)
+SYS(sys_time, 1)
+SYS(sys_mknod, 3)
+SYS(sys_chmod, 2)				/* 4015 */
+SYS(sys_chown, 3)
+SYS(sys_break, 0)
+SYS(sys_stat, 2)
+SYS(sys_lseek, 3)
+SYS(sys_getpid, 0)				/* 4020 */
+SYS(sys_mount, 5)
+SYS(sys_umount, 1)
+SYS(sys_setuid, 1)
+SYS(sys_getuid, 0)
+SYS(sys_stime, 1)				/* 4025 */
+SYS(sys_ptrace, 4)
+SYS(sys_alarm, 1)
+SYS(sys_fstat, 2)
+SYS(sys_pause, 0)
+SYS(sys_utime, 2)				/* 4030 */
+SYS(sys_stty, 0)
+SYS(sys_gtty, 0)
+SYS(sys_access, 2)
+SYS(sys_nice, 1)
+SYS(sys_ftime, 0)				/* 4035 */
+SYS(sys_sync, 0)
+SYS(sys_kill, 2)
+SYS(sys_rename, 2)
+SYS(sys_mkdir, 2)
+SYS(sys_rmdir, 1)				/* 4040 */
+SYS(sys_dup, 1)
+SYS(sys_pipe, 0)
+SYS(sys_times, 1)
+SYS(sys_prof, 0)
+SYS(sys_brk, 1)					/* 4045 */
+SYS(sys_setgid, 1)
+SYS(sys_getgid, 0)
+SYS(sys_signal, 2)
+SYS(sys_geteuid, 0)
+SYS(sys_getegid, 0)				/* 4050 */
+SYS(sys_acct, 0)
+SYS(sys_phys, 0)
+SYS(sys_lock, 0)
+SYS(sys_ioctl, 3)
+SYS(sys_fcntl, 3)				/* 4055 */
+SYS(sys_mpx, 2)
+SYS(sys_setpgid, 2)
+SYS(sys_ulimit, 0)
+SYS(sys_olduname, 1)
+SYS(sys_umask, 1)				/* 4060 */
+SYS(sys_chroot, 1)
+SYS(sys_ustat, 2)
+SYS(sys_dup2, 2)
+SYS(sys_getppid, 0)
+SYS(sys_getpgrp, 0)				/* 4065 */
+SYS(sys_setsid, 0)
+SYS(sys_sigaction, 3)
+SYS(sys_sgetmask, 0)
+SYS(sys_ssetmask, 1)
+SYS(sys_setreuid, 2)				/* 4070 */
+SYS(sys_setregid, 2)
+SYS(sys_sigsuspend, 3)
+SYS(sys_sigpending, 1)
+SYS(sys_sethostname, 2)
+SYS(sys_setrlimit, 2)				/* 4075 */
+SYS(sys_getrlimit, 2)
+SYS(sys_getrusage, 2)
+SYS(sys_gettimeofday, 2)
+SYS(sys_settimeofday, 2)
+SYS(sys_getgroups, 2)				/* 4080 */
+SYS(sys_setgroups, 2)
+SYS(sys_ni_syscall, 0) /* old_select */
+SYS(sys_symlink, 2)
+SYS(sys_lstat, 2)
+SYS(sys_readlink, 3)				/* 4085 */
+SYS(sys_uselib, 1)
+SYS(sys_swapon, 2)
+SYS(sys_reboot, 3)
+SYS(old_readdir, 3)
+SYS(sys_mmap, 6)				/* 4090 */
+SYS(sys_munmap, 2)
+SYS(sys_truncate, 2)
+SYS(sys_ftruncate, 2)
+SYS(sys_fchmod, 2)
+SYS(sys_fchown, 3)				/* 4095 */
+SYS(sys_getpriority, 2)
+SYS(sys_setpriority, 3)
+SYS(sys_profil, 0)
+SYS(sys_statfs, 2)
+SYS(sys_fstatfs, 2)				/* 4100 */
+SYS(sys_ioperm, 3)
+SYS(sys_socketcall, 2)
+SYS(sys_syslog, 3)
+SYS(sys_setitimer, 3)
+SYS(sys_getitimer, 2)				/* 4105 */
+SYS(sys_newstat, 2)
+SYS(sys_newlstat, 2)
+SYS(sys_newfstat, 2)
+SYS(sys_uname, 1)
+SYS(sys_iopl, 0)	/* Well, actually 17 args ... */				/* 4110 */
+SYS(sys_vhangup, 0)
+SYS(sys_idle, 0)
+SYS(sys_vm86, 1)
+SYS(sys_wait4, 4)
+SYS(sys_swapoff, 1)				/* 4115 */
+SYS(sys_sysinfo, 1)
+SYS(sys_ipc, 6)
+SYS(sys_fsync, 1)
+SYS(sys_sigreturn, 0)
+SYS(sys_clone, 0)				/* 4120 */
+SYS(sys_setdomainname, 2)
+SYS(sys_newuname, 1)
+SYS(sys_ni_syscall, 0) /* sys_modify_ldt */
+SYS(sys_adjtimex, 1)
+SYS(sys_mprotect, 3)				/* 4125 */
+SYS(sys_sigprocmask, 3)
+SYS(sys_create_module, 2)
+SYS(sys_init_module, 5)
+SYS(sys_delete_module, 1)
+SYS(sys_get_kernel_syms, 1)			/* 4130 */
+SYS(sys_quotactl, 0)
+SYS(sys_getpgid, 1)
+SYS(sys_fchdir, 1)
+SYS(sys_bdflush, 2)
+SYS(sys_sysfs, 3)				/* 4135 */
+SYS(sys_personality, 1)
+SYS(sys_ni_syscall, 0) /* for afs_syscall */
+SYS(sys_setfsuid, 1)
+SYS(sys_setfsgid, 1)
+SYS(sys_llseek, 5)				/* 4140 */
+SYS(sys_getdents, 3)
+SYS(sys_select, 5)
+SYS(sys_flock, 2)
+SYS(sys_msync, 3)
+SYS(sys_readv, 3)				/* 4145 */
+SYS(sys_writev, 3)
+SYS(sys_cacheflush, 3)
+SYS(sys_cachectl, 3)
+SYS(sys_sysmips, 4)
+SYS(sys_setup, 0)				/* 4150 */
+SYS(sys_getsid, 1)
+SYS(sys_ni_syscall, 0)
+SYS(sys_ni_syscall, 0)
+SYS(sys_mlock, 2)
+SYS(sys_munlock, 2)				/* 4155 */
+SYS(sys_mlockall, 1)
+SYS(sys_munlockall, 0)
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c
--- v1.3.47/linux/arch/mips/kernel/sysmips.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/sysmips.c	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,105 @@
+/*
+ * MIPS specific syscalls
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/utsname.h>
+
+#include <asm/cachectl.h>
+#include <asm/segment.h>
+#include <asm/sysmips.h>
+
+static inline size_t
+strnlen_user(const char *s, size_t count)
+{
+	return strnlen(s, count);
+}
+
+/*
+ * How long a hostname can we get from user space?
+ *  -EFAULT if invalid area or too long
+ *  0 if ok
+ *  >0 EFAULT after xx bytes
+ */
+static inline int
+get_max_hostname(unsigned long address)
+{
+	struct vm_area_struct * vma;
+
+	vma = find_vma(current, address);
+	if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
+		return -EFAULT;
+	address = vma->vm_end - address;
+	if (address > PAGE_SIZE)
+		return 0;
+	if (vma->vm_next && vma->vm_next->vm_start == vma->vm_end &&
+	   (vma->vm_next->vm_flags & VM_READ))
+		return 0;
+	return address;
+}
+
+asmlinkage int
+sys_sysmips(int cmd, int arg1, int arg2, int arg3)
+{
+	int	*p;
+	char	*name;
+	int	flags, len, retval = -EINVAL;
+
+	switch(cmd)
+	{
+	case SETNAME:
+		if (!suser())
+			return -EPERM;
+		name = (char *) arg1;
+		len = get_max_hostname((unsigned long)name);
+		if (retval < 0)
+			return len;
+		len = strnlen_user(name, retval);
+		if (len == 0 || len > __NEW_UTS_LEN)
+			return -EINVAL;
+		memcpy_fromfs(system_utsname.nodename, name, len);
+		system_utsname.nodename[len] = '\0';
+		return 0;
+	case MIPS_ATOMIC_SET:
+		p = (int *) arg1;
+		retval = verify_area(VERIFY_WRITE, p, sizeof(*p));
+		if(retval)
+			return -EINVAL;
+		save_flags(flags);
+		cli();
+		retval = *p;
+		*p = arg2;
+		restore_flags(flags);
+		return retval;
+	case MIPS_FIXADE:
+		if (arg1)
+			current->tss.mflags |= MF_FIXADE;
+		else
+			current->tss.mflags |= MF_FIXADE;
+		retval = 0;
+		break;
+	case FLUSH_CACHE:
+		sys_cacheflush(0, ~0, BCACHE);
+		break;
+	}
+
+	return retval;
+}
+
+/*
+ * No implemented yet ...
+ */
+asmlinkage int
+sys_cachectl(char *addr, int nbytes, int op)
+{
+	return -ENOSYS;
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c
--- v1.3.47/linux/arch/mips/kernel/time.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/time.c	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,286 @@
+/*
+ *  linux/arch/mips/kernel/time.c
+ *
+ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *
+ * This file contains the time handling details for PC-style clocks as
+ * found in some MIPS systems.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+#define TIMER_IRQ 0
+
+/* This function must be called with interrupts disabled 
+ * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
+ * 
+ * However, the pc-audio speaker driver changes the divisor so that
+ * it gets interrupted rather more often - it loads 64 into the
+ * counter rather than 11932! This has an adverse impact on
+ * do_gettimeoffset() -- it stops working! What is also not
+ * good is that the interval that our timer function gets called
+ * is no longer 10.0002 ms, but 9.9767 ms. To get around this
+ * would require using a different timing source. Maybe someone
+ * could use the RTC - I know that this can interrupt at frequencies
+ * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
+ * it so that at startup, the timer code in sched.c would select
+ * using either the RTC or the 8253 timer. The decision would be
+ * based on whether there was any other device around that needed
+ * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
+ * and then do some jiggery to have a version of do_timer that 
+ * advanced the clock by 1/1024 s. Every time that reached over 1/100
+ * of a second, then do all the old code. If the time was kept correct
+ * then do_gettimeoffset could just return 0 - there is no low order
+ * divider that can be accessed.
+ *
+ * Ideally, you would be able to use the RTC for the speaker driver,
+ * but it appears that the speaker driver really needs interrupt more
+ * often than every 120 us or so.
+ *
+ * Anyway, this needs more thought....		pjsg (1993-08-28)
+ * 
+ * If you are really that interested, you should be reading
+ * comp.protocols.time.ntp!
+ */
+
+#define TICK_SIZE tick
+
+static unsigned long do_slow_gettimeoffset(void)
+{
+	int count;
+	unsigned long offset = 0;
+
+	/* timer count may underflow right here */
+	outb_p(0x00, 0x43);	/* latch the count ASAP */
+	count = inb_p(0x40);	/* read the latched count */
+	count |= inb(0x40) << 8;
+	/* we know probability of underflow is always MUCH less than 1% */
+	if (count > (LATCH - LATCH/100)) {
+		/* check for pending timer interrupt */
+		outb_p(0x0a, 0x20);
+		if (inb(0x20) & 1)
+			offset = TICK_SIZE;
+	}
+	count = ((LATCH-1) - count) * TICK_SIZE;
+	count = (count + LATCH/2) / LATCH;
+	return offset + count;
+}
+
+static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	*tv = xtime;
+	tv->tv_usec += do_gettimeoffset();
+	if (tv->tv_usec >= 1000000) {
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}
+	restore_flags(flags);
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	cli();
+	/* This is revolting. We need to set the xtime.tv_usec
+	 * correctly. However, the value in this location is
+	 * is value at the last tick.
+	 * Discover what correction gettimeofday
+	 * would have done, and then undo it!
+	 */
+	tv->tv_usec -= do_gettimeoffset();
+
+	if (tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+
+	xtime = *tv;
+	time_state = TIME_BAD;
+	time_maxerror = 0x70000000;
+	time_esterror = 0x70000000;
+	sti();
+}
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else
+		retval = -1;
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and crystal) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
+/* last time the cmos clock got updated */
+static long last_rtc_update = 0;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static void timer_interrupt(int irq, struct pt_regs * regs)
+{
+	do_timer(regs);
+
+	/*
+	 * If we have an externally synchronized Linux clock, then update
+	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
+	 */
+	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec > 500000 - (tick >> 1) &&
+	    xtime.tv_usec < 500000 + (tick >> 1))
+	  if (set_rtc_mmss(xtime.tv_sec) == 0)
+	    last_rtc_update = xtime.tv_sec;
+	  else
+	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+	/* As we return to user mode fire off the other CPU schedulers.. this is 
+	   basically because we don't yet share IRQ's around. This message is
+	   rigged to be safe on the 386 - basically its a hack, so don't look
+	   closely for now.. */
+	smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); 
+}
+
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+static inline unsigned long mktime(unsigned int year, unsigned int mon,
+	unsigned int day, unsigned int hour,
+	unsigned int min, unsigned int sec)
+{
+	if (0 >= (int) (mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
+		mon += 12;	/* Puts Feb last since it has leap day */
+		year -= 1;
+	}
+	return (((
+	    (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
+	      year*365 - 719499
+	    )*24 + hour /* now have hours */
+	   )*60 + min /* now have minutes */
+	  )*60 + sec; /* finally seconds */
+}
+
+void time_init(void)
+{
+	void (*irq_handler)(int, struct pt_regs *);
+	unsigned int year, mon, day, hour, min, sec;
+	int i;
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+	  {
+	    BCD_TO_BIN(sec);
+	    BCD_TO_BIN(min);
+	    BCD_TO_BIN(hour);
+	    BCD_TO_BIN(day);
+	    BCD_TO_BIN(mon);
+	    BCD_TO_BIN(year);
+	  }
+	if ((year += 1900) < 1970)
+		year += 100;
+	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+	xtime.tv_usec = 0;
+
+	/* FIXME: If we have the CPU hardware time counters, use them */
+	irq_handler = timer_interrupt;	
+
+	if (request_irq(TIMER_IRQ, irq_handler, 0, "timer") != 0)
+		panic("Could not allocate timer IRQ!");
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/tlb.S linux/arch/mips/kernel/tlb.S
--- v1.3.47/linux/arch/mips/kernel/tlb.S	Fri Jan 13 23:49:20 1995
+++ linux/arch/mips/kernel/tlb.S	Thu Jan  1 02:00:00 1970
@@ -1,35 +0,0 @@
-/*
- * arch/mips/kernel/head.S
- *
- * Copyright (C) 1994 Waldorf Electronics
- * Written by Ralf Baechle and Andreas Busse
- *
- * Head.S contains the MIPS exception handler and startup code.
- * Flush the TLB
- *
- * FIXME: knows only how to handle R4x00
- * Read appendix f of the R4000 manual before you change something!
- */
-
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/bootinfo.h>
-
-		.globl	_tlbflush
-_tlbflush:	li	t0,PM_4K
-		mtc0	t0,CP0_PAGEMASK
-		lw	t0,_boot_info+OFFSET_BOOTINFO_TLB_ENTRIES(t0)
-	li	t0,48
-		dmtc0	zero,CP0_ENTRYLO0
-		dmtc0	zero,CP0_ENTRYLO1
-		mfc0	t2,CP0_WIRED
-1:		subu	t0,t0,1
-		mtc0	t0,CP0_INDEX
-		lui	t1,0x0008
-		or	t1,t0,t1
-		dsll	t1,t1,13
-		dmtc0	t1,CP0_ENTRYHI
-		bne	t2,t0,1b
-		tlbwi					# delay slot
-		jr	ra
-		nop
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
--- v1.3.47/linux/arch/mips/kernel/traps.c	Tue Jun 27 14:11:30 1995
+++ linux/arch/mips/kernel/traps.c	Wed Dec 13 12:39:44 1995
@@ -1,7 +1,9 @@
 /*
  *  arch/mips/kernel/traps.c
  *
- *  Copyright (C) 1991, 1992  Linus Torvalds
+ * 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.
  */
 
 /*
@@ -9,17 +11,23 @@
  * 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).
+ *
+ * FIXME: This is the place for a fpu emulator.
  */
 #include <linux/head.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/string.h>
+#include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
-#include <linux/config.h>
 #include <linux/timer.h>
+#include <linux/mm.h>
 
+#include <asm/vector.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -32,18 +40,15 @@
 	console_loglevel = 15;
 }
 
-#define get_seg_byte(seg,addr) ({ \
-register unsigned char __res; \
-__res = get_user_byte(addr); \
-__res;})
-
-#define get_seg_long(seg,addr) ({ \
-register unsigned long __res; \
-__res = get_user_word(addr); \
-__res;})
-
-extern asmlinkage void deskstation_tyne_handle_int(void);
+/*
+ * Machine specific interrupt handlers
+ */
 extern asmlinkage void acer_pica_61_handle_int(void);
+extern asmlinkage void decstation_handle_int(void);
+extern asmlinkage void deskstation_rpc44_handle_int(void);
+extern asmlinkage void deskstation_tyne_handle_int(void);
+extern asmlinkage void mips_magnum_4000_handle_int(void);
+
 extern asmlinkage void handle_mod(void);
 extern asmlinkage void handle_tlbl(void);
 extern asmlinkage void handle_tlbs(void);
@@ -63,90 +68,60 @@
 extern asmlinkage void handle_watch(void);
 extern asmlinkage void handle_reserved(void);
 
-char *cpu_names[] = CPU_NAMES;
+static char *cpu_names[] = CPU_NAMES;
+
+unsigned long page_colour_mask;
 
 int kstack_depth_to_print = 24;
 
 /*
- * These constants are for searching for possible module text
- * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
- * a guess of how much space is likely to be vmalloced.
+ * These constant is for searching for possible module text segments.
+ * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
  */
-#define VMALLOC_OFFSET (8*1024*1024)
 #define MODULE_RANGE (8*1024*1024)
 
 void die_if_kernel(char * str, struct pt_regs * regs, long err)
 {
-	int i;
-	unsigned long *sp, *pc;
-	unsigned long *stack, addr, module_start, module_end;
-	extern char start_kernel, etext;
+	int	i;
+	int	*stack;
+	u32	*sp, *pc, addr, module_start, module_end;
+	extern	char start_kernel, _etext;
 
 	if ((regs->cp0_status & (ST0_ERL|ST0_EXL)) == 0)
 		return;
 
-	sp = (unsigned long *)regs->reg29;
-	pc = (unsigned long *)regs->cp0_epc;
+	sp = (u32 *)regs->reg29;
+	pc = (u32 *)regs->cp0_epc;
 
 	console_verbose();
 	printk("%s: %08lx\n", str, err );
 
-	/*
-	 * Saved main processor registers
-	 */
-	printk("at   : %08lx\n", regs->reg1);
-	printk("v0   : %08lx %08lx\n", regs->reg2, regs->reg3);
-	printk("a0   : %08lx %08lx %08lx %08lx\n",
-	       regs->reg4, regs->reg5, regs->reg6, regs->reg7);
-	printk("t0   : %08lx %08lx %08lx %08lx %08lx\n",
-	       regs->reg8, regs->reg9, regs->reg10, regs->reg11, regs->reg12);
-	printk("t5   : %08lx %08lx %08lx %08lx %08lx\n",
-	       regs->reg13, regs->reg14, regs->reg15, regs->reg24, regs->reg25);
-	printk("s0   : %08lx %08lx %08lx %08lx\n",
-	       regs->reg16, regs->reg17, regs->reg18, regs->reg19);
-	printk("s4   : %08lx %08lx %08lx %08lx\n",
-	       regs->reg20, regs->reg21, regs->reg22, regs->reg23);
-	printk("gp   : %08lx\n", regs->reg28);
-	printk("sp   : %08lx\n", regs->reg29);
-	printk("fp/s8: %08lx\n", regs->reg30);
-	printk("ra   : %08lx\n", regs->reg31);
-
-	/*
-	 * Saved cp0 registers
-	 */
-	printk("epc  : %08lx\nStatus: %08lx\nCause : %08lx\n",
-	       regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
-
-	/*
-	 * Some goodies...
-	 */
-	printk("Int  : %ld\n", regs->interrupt);
+	show_regs(regs);
 
 	/*
 	 * Dump the stack
 	 */
-	if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page)
+	if (STACK_MAGIC != *(u32 *)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);
+	printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ",
+		current->comm, current->pid, current->kernel_stack_page);
 	for(i=0;i<5;i++)
-		printk("%08lx ", *sp++);
-	stack = (unsigned long *) sp;
+		printk("%08x ", *sp++);
+	stack = (int *) sp;
 	for(i=0; i < kstack_depth_to_print; i++) {
-		if (((long) stack & 4095) == 0)
+		if (((u32) stack & (PAGE_SIZE -1)) == 0)
 			break;
 		if (i && ((i % 8) == 0))
 			printk("\n       ");
-		printk("%08lx ", get_seg_long(ss,stack++));
+		printk("%08lx ", get_user(stack++));
 	}
 	printk("\nCall Trace: ");
-	stack = (unsigned long *) sp;
+	stack = (int *)sp;
 	i = 1;
-	module_start = ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
+	module_start = VMALLOC_START;
 	module_end = module_start + MODULE_RANGE;
-	while (((long) stack & 4095) != 0) {
-		addr = get_seg_long(ss, stack++);
+	while (((u32)stack & (PAGE_SIZE -1)) != 0) {
+		addr = get_user(stack++);
 		/*
 		 * If the address is either in the text segment of the
 		 * kernel, or in the region which contains vmalloc'ed
@@ -155,103 +130,159 @@
 		 * down the cause of the crash will be able to figure
 		 * out the call path that was taken.
 		 */
-		if (((addr >= (unsigned long) &start_kernel) &&
-		     (addr <= (unsigned long) &etext)) ||
+		if (((addr >= (u32) &start_kernel) &&
+		     (addr <= (u32) &_etext)) ||
 		    ((addr >= module_start) && (addr <= module_end))) {
 			if (i && ((i % 8) == 0))
 				printk("\n       ");
-			printk("%08lx ", addr);
+			printk("%08x ", addr);
 			i++;
 		}
 	}
 
 	printk("\nCode : ");
-	for(i=0;i<5;i++)
-		printk("%08lx ", *pc++);
-	printk("\n");
+	if ((!verify_area(VERIFY_READ, pc, 5 * sizeof(*pc)) ||
+	     KSEGX(pc) == KSEG0 ||
+	     KSEGX(pc) == KSEG1) &&
+	    (((unsigned long) pc & 3) == 0))
+	{
+		for(i=0;i<5;i++)
+			printk("%08x ", *pc++);
+		printk("\n");
+	}
+	else
+		printk("(Bad address in epc)\n");
+while(1);
 	do_exit(SIGSEGV);
 }
 
+static void
+fix_ade(struct pt_regs *regs, int write)
+{
+	printk("Received address error (ade%c)\n", write ? 's' : 'l');
+	panic("Fixing address errors not implemented yet");
+}
+
 void do_adel(struct pt_regs *regs)
 {
+	if(current->tss.mflags & MF_FIXADE)
+	{
+		fix_ade(regs, 0);
+		return;
+	}
+	show_regs(regs);
+while(1);
+	dump_tlb_nonwired();
 	send_sig(SIGSEGV, current, 1);
 }
 
 void do_ades(struct pt_regs *regs)
 {
+	unsigned long	pc = regs->cp0_epc;
+	int	i;
+
+	if(current->tss.mflags & MF_FIXADE)
+	{
+		fix_ade(regs, 1);
+		return;
+	}
+while(1);
+	for(i=0; i<NR_TASKS;i++)
+		if(task[i] && task[i]->pid >= 2)
+		{
+			printk("Process %d\n", task[i]->pid);
+			dump_list_process(task[i], pc);
+		}
+	show_regs(regs);
+	dump_tlb_nonwired();
 	send_sig(SIGSEGV, current, 1);
 }
 
+/*
+ * The ibe/dbe exceptions are signaled by onboard hardware and should get
+ * a board specific handlers to get maximum available information. Bus
+ * errors are always symptom of hardware malfunction or a kernel error.
+ *
+ * FIXME: Linux/68k sends a SIGSEGV for a buserror which seems to be wrong.
+ * This is certainly wrong. Actually, all hardware errors (ades,adel,ibe,dbe)
+ * are bus errors and therefor should send a SIGBUS! (Andy)
+ */
 void do_ibe(struct pt_regs *regs)
 {
-	send_sig(SIGSEGV, current, 1);
+show_regs(regs);
+while(1);
+	send_sig(SIGBUS, current, 1);
 }
 
 void do_dbe(struct pt_regs *regs)
 {
-	send_sig(SIGSEGV, current, 1);
+show_regs(regs);
+while(1);
+	send_sig(SIGBUS, current, 1);
 }
 
 void do_ov(struct pt_regs *regs)
 {
+show_regs(regs);
+while(1);
 	send_sig(SIGFPE, current, 1);
 }
 
 void do_fpe(struct pt_regs *regs)
 {
-	/*
-	 * FIXME: This is the place for a fpu emulator. Not written
-	 * yet and the demand seems to be quite low.
-	 */
-	printk("Caught FPE exception at %lx.\n", regs->cp0_epc);
+show_regs(regs);
+while(1);
 	send_sig(SIGFPE, current, 1);
 }
 
 void do_bp(struct pt_regs *regs)
 {
+show_regs(regs);
+while(1);
 	send_sig(SIGILL, current, 1);
 }
 
 void do_tr(struct pt_regs *regs)
 {
+show_regs(regs);
+while(1);
 	send_sig(SIGILL, current, 1);
 }
 
 void do_ri(struct pt_regs *regs)
 {
+	int	i;
+
+	for(i=0; i<NR_TASKS;i++)
+		if(task[i] && task[i]->pid >= 2)
+		{
+			printk("Process %d\n", task[i]->pid);
+			dump_list_process(task[i], 0x7ffff000);
+		}
+	show_regs(regs);
+while(1);
 	send_sig(SIGILL, current, 1);
 }
 
 void do_cpu(struct pt_regs *regs)
 {
-	unsigned long pc;
-	unsigned int insn;
+	unsigned int cpid;
 
-	/*
-	 * Check whether this was a cp1 instruction
-	 */
-	pc = regs->cp0_epc;
-	if (regs->cp0_cause & (1<<31))
-		pc += 4;
-	insn = *(unsigned int *)pc;
-	insn &= 0xfc000000;
-	switch(insn) {
-		case 0x44000000:
-		case 0xc4000000:
-		case 0xe4000000:
-			printk("CP1 instruction - enabling cp1.\n");
-			regs->cp0_status |= ST0_CU1;
-			/*
-			 * No need to handle branch delay slots
-			 */
-			break;
-		default:
-			/*
-			 * This wasn't a cp1 instruction and therefore illegal.
-			 * Default is to kill the process.
-			 */
-			send_sig(SIGILL, current, 1);
-		}
+	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
+	switch(cpid)
+	{
+	case 1:
+		regs->cp0_status |= ST0_CU1;
+		break;
+	case 0:
+		/*
+		 * CPU for cp0 can only happen in user mode
+		 */
+	case 2:
+	case 3:
+		send_sig(SIGILL, current, 1);
+		break;
+	}
 }
 
 void do_vcei(struct pt_regs *regs)
@@ -274,10 +305,6 @@
 
 void do_watch(struct pt_regs *regs)
 {
-	/*
-	 * Only possible on R4[04]00. No way to handle this because
-	 * I don't have such a cpu.
-	 */
 	panic("Caught WATCH exception - can't handle yet\n");
 }
 
@@ -285,7 +312,7 @@
 {
 	/*
 	 * Game over - no way to handle this if it ever occurs.
-	 * Most probably caused by a new unknown cpu type or a
+	 * Most probably caused by a new unknown cpu type or
 	 * after another deadly hard/software error.
 	 */
 	panic("Caught reserved exception - can't handle.\n");
@@ -293,12 +320,11 @@
 
 void trap_init(void)
 {
-	int	i;
+	unsigned long	i;
+	void watch_set(unsigned long, unsigned long);
 
-	/*
-	 * FIXME: Mips Magnum R4000 has an EISA bus!
-	 */
-	EISA_bus = 0;
+	if(boot_info.machtype == MACH_MIPS_MAGNUM_4000)
+		EISA_bus = 1;
 
 	/*
 	 * Setup default vectors
@@ -310,30 +336,49 @@
 	 * Handling the following exceptions depends mostly of the cpu type
 	 */
 	switch(boot_info.cputype) {
+	/*
+	 * The R10000 is in most aspects similar to the R4400.  It however
+	 * should get some special optimizations.
+	 */
+	case CPU_R10000:
+		write_32bit_cp0_register(CP0_FRAMEMASK, 0);
+		set_cp0_status(ST0_XX, ST0_XX);
+		page_colour_mask = 0x3000;
+		panic("CPU too expensive - making holiday in the ANDES!");
+		break;
 	case CPU_R4000MC:
 	case CPU_R4400MC:
 	case CPU_R4000SC:
 	case CPU_R4400SC:
 		/*
-		 * Handlers not implemented yet
+		 * Handlers not implemented yet.  If should ever be used -
+		 * otherwise it's a bug in the Linux/MIPS kernel, anyway.
 		 */
 		set_except_vector(14, handle_vcei);
 		set_except_vector(31, handle_vced);
 	case CPU_R4000PC:
 	case CPU_R4400PC:
+	case CPU_R4200:
+     /* case CPU_R4300: */
 		/*
-		 * Handler not implemented yet
+		 * Use watch exception to trap on access to address zero
 		 */
 		set_except_vector(23, handle_watch);
-	case CPU_R4200:
+		watch_set(KSEG0, 3);
 	case CPU_R4600:
 		set_except_vector(1, handle_mod);
 		set_except_vector(2, handle_tlbl);
 		set_except_vector(3, handle_tlbs);
 		set_except_vector(4, handle_adel);
 		set_except_vector(5, handle_ades);
+		/*
+		 * The following two are signaled by onboard hardware and
+		 * should get board specific handlers to get maximum
+		 * available information.
+		 */
 		set_except_vector(6, handle_ibe);
 		set_except_vector(7, handle_dbe);
+
 		set_except_vector(8, handle_sys);
 		set_except_vector(9, handle_bp);
 		set_except_vector(10, handle_ri);
@@ -341,6 +386,15 @@
 		set_except_vector(12, handle_ov);
 		set_except_vector(13, handle_tr);
 		set_except_vector(15, handle_fpe);
+
+		/*
+		 * Compute mask for page_colour().  This is based on the
+		 * size of the data cache.  Does the size of the icache
+		 * need to be accounted for?
+		 */
+		i = read_32bit_cp0_register(CP0_CONFIG);
+		i = (i >> 26) & 7;
+		page_colour_mask = 1 << (12 + i);
 		break;
 	case CPU_R2000:
 	case CPU_R3000:
@@ -353,27 +407,18 @@
 	case CPU_R6000:
 	case CPU_R6000A:
 	case CPU_R8000:
-	case CPU_R10000:
 		printk("Detected unsupported CPU type %s.\n",
-		       cpu_names[boot_info.cputype]);
+			cpu_names[boot_info.cputype]);
 		panic("Can't handle CPU\n");
 		break;
+
 	case CPU_UNKNOWN:
 	default:
-		panic("Unknown type of CPU");
-		}
+		panic("Unknown CPU type");
+	}
 
 	/*
-	 * The interrupt handler depends of both type of the board and cpu
+	 * The interrupt handler mostly depends of the board type.
 	 */
-	switch(boot_info.machtype) {
-	case MACH_DESKSTATION_TYNE:
-		set_except_vector(0, deskstation_tyne_handle_int);
-		break;
-	case MACH_ACER_PICA_61:
-		set_except_vector(0, acer_pica_61_handle_int);
-		break;
-	default:
-		panic("Unknown machine type");
-		}
+	set_except_vector(0, feature->handle_int);
 }
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/tyne-c.c linux/arch/mips/kernel/tyne-c.c
--- v1.3.47/linux/arch/mips/kernel/tyne-c.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/tyne-c.c	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,122 @@
+/*
+ * Deskstation Tyne specific C parts
+ *
+ * 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, 1995 by Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+
+/*
+ * How to access the FDC's registers.
+ */
+unsigned char deskstation_tyne_fd_inb(unsigned int port)
+{
+	return inb_p(port);
+}
+
+void deskstation_tyne_fd_outb(unsigned char value, unsigned int port)
+{
+	outb_p(value, port);
+}
+
+/*
+ * How to access the floppy DMA functions.
+ */
+void deskstation_tyne_fd_enable_dma(void)
+{
+	enable_dma(FLOPPY_DMA);
+}
+
+void deskstation_tyne_fd_disable_dma(void)
+{
+	disable_dma(FLOPPY_DMA);
+}
+
+int deskstation_tyne_fd_request_dma(void)
+{
+	return request_dma(FLOPPY_DMA, "floppy");
+}
+
+void deskstation_tyne_fd_free_dma(void)
+{
+	free_dma(FLOPPY_DMA);
+}
+
+void deskstation_tyne_fd_clear_dma_ff(void)
+{
+	clear_dma_ff(FLOPPY_DMA);
+}
+
+int deskstation_tyne_fd_set_dma_mode(char mode)
+{
+	return set_dma_mode(FLOPPY_DMA, mode);
+}
+
+void deskstation_tyne_fd_set_dma_addr(unsigned int a)
+{
+	set_dma_addr(FLOPPY_DMA, addr);
+}
+
+void deskstation_tyne_fd_set_dma_count(unsigned int count)
+{
+	set_dma_count(FLOPPY_DMA, count);
+}
+
+int deskstation_tyne_fd_get_dma_residue(void)
+{
+	return get_dma_residue(FLOPPY_DMA);
+}
+
+void deskstation_tyne_fd_enable_irq(void)
+{
+	enable_irq(FLOPPY_IRQ);
+}
+
+void deskstation_tyne_fd_disable_irq(void)
+{
+	disable_irq(FLOPPY_IRQ);
+}
+
+void deskstation_tyne_fd_cacheflush(unsigned char *addr, unsigned int)
+{
+	sys_cacheflush((void *)addr, size, DCACHE);
+}
+
+
+/*
+ * Tiny Tyne DMA buffer allocator
+ *
+ * Untested for a long time and changed again and again ...
+ * Sorry, but no hardware to test ...
+ */
+static unsigned long allocated;
+
+/*
+ * Not very sophisticated, but should suffice for now...
+ */
+unsigned long deskstation_tyne_dma_alloc(size_t size)
+{
+	unsigned long ret = allocated;
+	allocated += size;
+	if (allocated > boot_info.dma_cache_size)
+		ret = -1;
+	return ret;
+}
+
+void deskstation_tyne_dma_init(void)
+{
+	if (boot_info.machtype != MACH_DESKSTATION_TYNE)
+		return;
+	allocated = 0;
+	printk ("Deskstation Tyne DMA (%luk) buffer initialized.\n",
+	        boot_info.dma_cache_size >> 10);
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/tyne.S linux/arch/mips/kernel/tyne.S
--- v1.3.47/linux/arch/mips/kernel/tyne.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/kernel/tyne.S	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,128 @@
+/*
+ * arch/mips/kernel/tyne.S
+ *
+ * Deskstation Tyne specific Assembler code
+ *
+ * Copyright (C) 1994, 1995 Waldorf Electronics
+ * written by Ralf Baechle and Andreas Busse
+ */
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+
+/*
+ * Deskstation Tyne interrupt handler
+ */
+		.text
+		.set	noreorder
+		.set	noat
+		.align	5
+		NESTED(deskstation_tyne_handle_int, FR_SIZE, sp)
+		SAVE_ALL
+		CLI
+		.set	at
+		lui	s0,%hi(PORT_BASE)
+		li	t1,0x0f
+		sb	t1,%lo(PORT_BASE+0x20)(s0)	# poll command
+		lb	t1,%lo(PORT_BASE+0x20)(s0)	# read result
+		li	s1,1
+		bgtz	t1,Lpoll_second
+		andi	t1,t1,7
+		/*
+		 * Acknowledge first pic
+		 */
+		lb	t2,%lo(PORT_BASE+0x21)(s0)
+		lui	s4,%hi(cache_21)
+		lb	t0,%lo(cache_21)(s4)
+		sllv	s1,s1,t1
+		or	t0,t0,s1
+		sb	t0,%lo(cache_21)(s4)
+		sb	t0,%lo(PORT_BASE+0x21)(s0)
+		lui	s3,%hi(intr_count)
+		lw	t0,%lo(intr_count)(s3)
+		li	t2,0x20
+		sb	t2,%lo(PORT_BASE+0x20)(s0)
+		/*
+		 * Now call the real handler
+		 */
+		la	t3,IRQ_vectors
+		sll	t2,t1,2
+		addu	t3,t3,t2
+		lw	t3,(t3)
+		addiu	t0,t0,1
+		jalr	t3
+		sw	t0,%lo(intr_count)(s3)			# delay slot
+		lw	t0,%lo(intr_count)(s3)
+		/*
+		 * Unblock first pic
+		 */
+		lbu	t1,%lo(PORT_BASE+0x21)(s0)
+		lb	t1,%lo(cache_21)(s4)
+		subu	t0,t0,1
+		sw	t0,%lo(intr_count)(s3)
+		nor	s1,zero,s1
+		and	t1,t1,s1
+		sb	t1,%lo(cache_21)(s4)
+		jr	v0
+		sb	t1,%lo(PORT_BASE+0x21)(s0)	# delay slot
+
+		.align	5
+Lpoll_second:	li	t1,0x0f
+		sb	t1,%lo(PORT_BASE+0xa0)(s0)	# poll command
+		lb	t1,%lo(PORT_BASE+0xa0)(s0)	# read result
+		lui	s4,%hi(cache_A1)
+		bgtz	t1,spurious_interrupt
+		andi	t1,t1,7
+		/*
+		 * Acknowledge second pic
+		 */
+		lbu	t2,%lo(PORT_BASE+0xa1)(s0)
+		lb	t3,%lo(cache_A1)(s4)
+		sllv	s1,s1,t1
+		or	t3,t3,s1
+		sb	t3,%lo(cache_A1)(s4)
+		sb	t3,%lo(PORT_BASE+0xa1)(s0)
+		li	t3,0x20
+		sb	t3,%lo(PORT_BASE+0xa0)(s0)
+		lui	s3,%hi(intr_count)
+		lw	t0,%lo(intr_count)(s3)
+		sb	t3,%lo(PORT_BASE+0x20)(s0)
+		/*
+		 * Now call the real handler
+		 */
+		la	t0,IRQ_vectors
+		sll	t2,t1,2
+		addu	t0,t0,t2
+		lw	t0,32(t0)
+		addiu	t0,t0,1
+		jalr	t0
+		sw	t0,%lo(intr_count)(s3)			# delay slot
+		lw	t0,%lo(intr_count)(s3)
+		/*
+		 * Unblock second pic
+		 */
+		lb	t1,%lo(PORT_BASE+0xa1)(s0)
+		lb	t1,%lo(cache_A1)(s4)
+		subu	t0,t0,1
+		lw	t0,%lo(intr_count)(s3)
+		nor	s1,zero,s1
+		and	t1,t1,s1
+		sb	t1,%lo(cache_A1)(s4)
+		jr	v0
+		sb	t1,%lo(PORT_BASE+0xa1)(s0)	# delay slot
+		END(deskstation_tyne_handle_int)
+
+		.align	5
+LEAF(spurious_interrupt)
+		/*
+		 * Nothing happened... (whistle)
+		 */
+		lui	t1,%hi(spurious_count)
+		lw	t0,%lo(spurious_count)(t1)
+		la	v0,return
+		addiu	t0,1
+		jr	ra
+		sw	t0,%lo(spurious_count)(t1)
+		END(spurious_interrupt)
+
diff -u --recursive --new-file v1.3.47/linux/arch/mips/kernel/tynedma.c linux/arch/mips/kernel/tynedma.c
--- v1.3.47/linux/arch/mips/kernel/tynedma.c	Wed Jan 25 08:54:22 1995
+++ linux/arch/mips/kernel/tynedma.c	Thu Jan  1 02:00:00 1970
@@ -1,35 +0,0 @@
-/*
- * Tiny Tyne DMA buffer allocator
- *
- * Copyright (C) 1995 Ralf Baechle
- */
-#include <linux/autoconf.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-
-#ifdef CONFIG_DESKSTATION_TYNE
-
-static unsigned long allocated;
-
-/*
- * Not very sophisticated, but should suffice for now...
- */
-unsigned long deskstation_tyne_dma_alloc(size_t size)
-{
-	unsigned long ret = allocated;
-	allocated += size;
-	if (allocated > boot_info.dma_cache_size)
-		ret = -1;
-	return ret;
-}
-
-void deskstation_tyne_dma_init(void)
-{
-	if (boot_info.machtype != MACH_DESKSTATION_TYNE)
-		return;
-	allocated = 0;
-	printk ("Deskstation Tyne DMA (%luk) buffer initialized.\n",
-	        boot_info.dma_cache_size >> 10);
-}
-
-#endif /* CONFIG_DESKSTATION_TYNE */
diff -u --recursive --new-file v1.3.47/linux/arch/mips/ld.script linux/arch/mips/ld.script
--- v1.3.47/linux/arch/mips/ld.script	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/ld.script	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,106 @@
+OUTPUT_FORMAT("elf32-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(kernel_entry)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x80000000;
+  .rel.text      : { *(.rel.text)	}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)	}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)	}
+  .rela.got      : { *(.rela.got)	}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.init      : { *(.rel.init)	}
+  .rela.init     : { *(.rela.init)	}
+  .rel.fini      : { *(.rel.fini)	}
+  .rela.fini     : { *(.rela.fini)	}
+  .rel.bss       : { *(.rel.bss)	}
+  .rela.bss      : { *(.rela.bss)	}
+  .rel.plt       : { *(.rel.plt)	}
+  .rela.plt      : { *(.rela.plt)	}
+  .init          : { *(.init)		} =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  _etext = .;
+  PROVIDE (etext = .);
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  _edata  =  .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  _fbss = .;
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  _end = . ;
+  PROVIDE (end = .);
+   *(.sbss)
+   *(.scommon)
+  }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile
--- v1.3.47/linux/arch/mips/lib/Makefile	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/lib/Makefile	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,16 @@
+#
+# Makefile for MIPS-specific library files..
+#
+# Many of these routines are just left over debugging trash of ancient
+# times when I just make my Tyne beep and so ...
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+L_TARGET = lib.a
+L_OBJS	= beep.o checksum.o csum.o dump_tlb.o tinycon.o watch.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.47/linux/arch/mips/lib/checksum.c linux/arch/mips/lib/checksum.c
--- v1.3.47/linux/arch/mips/lib/checksum.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/mips/lib/checksum.c	Wed Dec 13 12:39:44 1995
@@ -0,0 +1,148 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		MIPS specific IP/TCP/UDP checksumming routines
+ *
+ * Authors:	Ralf Baechle, <ralf@waldorf-gmbh.de>
+ *		Lots of code moved from tcp.c and ip.c; see those files
+ *		for more names.
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+#include <net/checksum.h>
+#include <asm/string.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
+{
+	unsigned long	scratch1;
+	unsigned long	scratch2;
+
+	/*
+	 * The GCC generated code for handling carry bits makes
+	 * it strongly desireable to do this in assembler!
+	 */
+    __asm__("
+	.set	noreorder
+	.set	noat
+	andi	$1,%5,2		# Check alignment
+	beqz	$1,2f		# Branch if ok
+	subu	$1,%4,2		# delay slot, Alignment uses up two bytes
+	bgez	$1,1f		# Jump if we had at least two bytes
+	move	%4,$1		# delay slot
+	j	4f
+	addiu	%4,2		# delay slot; len was < 2.  Deal with it
+
+1:	lw	%2,(%5)
+	addiu	%4,2
+	addu	%0,%2
+	sltu	$1,%0,%2
+	addu	%0,$1
+
+2:	move	%1,%4
+	srl	%1,%1,5
+	beqz	%1,2f
+	sll	%1,%1,5		# delay slot
+
+	addu	%1,%5
+1:	lw	%2,0(%5)
+	addu	%5,32
+	addu	%0,%2
+	sltu	$1,%0,%2
+
+	lw	%2,-28(%5)
+	addu	%0,$1
+	addu	%0,%2
+	sltu	$1,%0,%2
+
+	lw	%2,-24(%5)
+	addu	%0,$1
+	addu	%0,%2
+	sltu	$1,%0,%2
+
+	lw	%2,-20(%5)
+	addu	%0,$1
+	addu	%0,%2
+	sltu	$1,%0,%2
+
+	lw	%2,-16(%5)
+	addu	%0,$1
+	addu	%0,%2
+	sltu	$1,%0,%2
+
+	lw	%2,-12(%5)
+	addu	%0,$1
+	addu	%0,%2
+	sltu	$1,%0,%2
+
+	lw	%2,-8(%5)
+	addu	%0,$1
+	addu	%0,%2
+	sltu	$1,%0,%2
+
+	lw	%2,-4(%5)
+	addu	%0,$1
+	addu	%0,%2
+	sltu	$1,%0,%2
+
+	bne	%5,%1,1b
+	addu	%0,$1		# delay slot
+
+2:	andi	%1,%4,0x1c
+	srl	%1,%1,2
+	beqz	%1,4f
+	addu	%1,%5		# delay slot
+3:	lw	%2,0(%5)
+	addu	%5,4
+	addu	%0,%2
+	sltu	$1,%0,%2
+	bne	%5,%1,3b
+	addu	%0,$1		# delay slot
+
+4:	andi	$1,%3,2
+	beqz	$1,5f
+	move	%2,$0		# delay slot
+	lhu	%2,(%5)
+	addiu	%5,2
+
+5:	andi	$1,%3,1
+	beqz	$1,6f
+	sll	%1,16		# delay slot
+	lbu	%1,(%5)
+	nop			# NOP ALERT (spit, gasp)
+6:	or	%2,%1
+	addu	%0,%2
+	sltu	$1,%0,%2
+	addu	%0,$1
+7:	.set	at
+	.set	reorder"
+	: "=r"(sum), "=r" (scratch1), "=r" (scratch2)
+	: "0"(sum), "r"(len), "r"(buff)
+	: "$1");
+
+	return sum;
+}
+
+/*
+ * copy from fs while checksumming, otherwise like csum_partial
+ */
+unsigned int csum_partial_copy(const char *src, char *dst, 
+				  int len, int sum)
+{
+	/*
+	 * It's 2:30 am and I don't feel like doing it real ...
+	 * This is lots slower than the real thing (tm)
+	 */
+	sum = csum_partial(src, len, sum);
+	memcpy(dst, src, len);
+
+	return sum;
+}
diff -u --recursive --new-file v1.3.47/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile
--- v1.3.47/linux/arch/mips/mm/Makefile	Tue Aug 15 20:39:00 1995
+++ linux/arch/mips/mm/Makefile	Wed Dec 13 12:39:44 1995
@@ -1,5 +1,5 @@
 #
-# Makefile for the linux mips-specific parts of the memory manager.
+# Makefile for the Linux/MIPS-specific parts of the memory manager.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
 # removes any old dependencies. DON'T put your own dependencies here
diff -u --recursive --new-file v1.3.47/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c
--- v1.3.47/linux/arch/mips/mm/fault.c	Wed Jan 25 08:54:22 1995
+++ linux/arch/mips/mm/fault.c	Wed Dec 13 12:39:44 1995
@@ -1,11 +1,8 @@
 /*
  *  arch/mips/mm/fault.c
  *
- *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
- *  Ported to MIPS by Ralf Baechle
+ *  Copyright (C) 1995 by Ralf Baechle
  */
-
-#include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/head.h>
@@ -19,7 +16,7 @@
 
 #include <asm/system.h>
 #include <asm/segment.h>
-#include <asm/mipsconfig.h>
+#include <asm/pgtable.h>
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
 
@@ -27,61 +24,43 @@
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
  * routines.
- *
- * The error_code parameter just the same as in the i386 version:
- *
- *	bit 0 == 0 means no page found, 1 means protection fault
- *	bit 1 == 0 means read, 1 means write
- *	bit 2 == 0 means kernel, 1 means user-mode
  */
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+asmlinkage void
+do_page_fault(struct pt_regs *regs, unsigned long writeaccess, unsigned long address)
 {
 	struct vm_area_struct * vma;
-	unsigned long address;
-	unsigned long page;
-
-	/* get the address */
-	__asm__("dmfc0\t%0,$8"
-	        : "=r" (address));
 
-	for (vma = current->mm->mmap ; ; vma = vma->vm_next) {
-		if (!vma)
-			goto bad_area;
-		if (vma->vm_end > address)
-			break;
-	}
+#if 0
+	printk("do_page_fault() #1: %s %08lx (epc == %08lx, ra == %08lx)\n",
+	       writeaccess ? "writeaccess to" : "readaccess from",
+	       address, regs->cp0_epc, regs->reg31);
+#endif
+	vma = find_vma(current, address);
+	if (!vma)
+		goto bad_area;
 	if (vma->vm_start <= address)
 		goto good_area;
 	if (!(vma->vm_flags & VM_GROWSDOWN))
 		goto bad_area;
-	if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
+	if (expand_stack(vma, address))
 		goto bad_area;
-	vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
-	vma->vm_start = (address & PAGE_MASK);
 /*
  * Ok, we have a good vm_area for this memory access, so
  * we can handle it..
  */
 good_area:
-	/*
-	 * was it a write?
-	 */
-	if (error_code & 2) {
+	if (writeaccess) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
 	} else {
-		/* read with protection fault? */
-		if (error_code & 1)
-			goto bad_area;
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
 	}
-	if (error_code & 1) {
-		do_wp_page(vma, address, error_code & 2);
-		return;
-	}
-	do_no_page(vma, address, error_code & 2);
-	return;
+	handle_mm_fault(vma, address, writeaccess);
+	/* FIXME: This flushes the cache far to often */
+	sys_cacheflush(address, PAGE_SIZE, BCACHE);
+
+        return;
 
 /*
  * Something tried to access memory that isn't in our memory map..
@@ -90,10 +69,7 @@
 bad_area:
 	if (user_mode(regs)) {
 		current->tss.cp0_badvaddr = address;
-		current->tss.error_code = error_code;
-#if 0
-		current->tss.trap_no = 14;
-#endif
+		current->tss.error_code = writeaccess;
 		send_sig(SIGSEGV, current, 1);
 		return;
 	}
@@ -101,22 +77,8 @@
 	 * Oops. The kernel tried to access some bad page. We'll have to
 	 * terminate things with extreme prejudice.
 	 */
-	if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) {
-		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-		pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
-	} else
-		printk(KERN_ALERT "Unable to handle kernel paging request");
-	printk(" at virtual address %08lx\n",address);
-	page = current->tss.pg_dir;
-	printk(KERN_ALERT "current->tss.pg_dir = %08lx\n", page);
-	page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
-	printk(KERN_ALERT "*pde = %08lx\n", page);
-	if (page & 1) {
-		page &= PAGE_MASK;
-		address &= 0x003ff000;
-		page = ((unsigned long *) page)[address >> PAGE_SHIFT];
-		printk(KERN_ALERT "*pte = %08lx\n", page);
-	}
-	die_if_kernel("Oops", regs, error_code);
+	printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
+	       "address %08lx\n", address);
+	die_if_kernel("Oops", regs, writeaccess);
 	do_exit(SIGKILL);
 }
diff -u --recursive --new-file v1.3.47/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c
--- v1.3.47/linux/arch/mips/mm/init.c	Sun Sep  3 12:26:49 1995
+++ linux/arch/mips/mm/init.c	Wed Dec 13 12:39:45 1995
@@ -4,7 +4,6 @@
  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  *  Ported to MIPS by Ralf Baechle
  */
-
 #include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -17,11 +16,12 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 
+#include <asm/cachectl.h>
+#include <asm/jazzdma.h>
+#include <asm/vector.h>
 #include <asm/system.h>
 #include <asm/segment.h>
-#include <asm/mipsconfig.h>
-
-extern unsigned long pg0[1024];		/* page table for 0-4MB for everybody */
+#include <asm/pgtable.h>
 
 extern void deskstation_tyne_dma_init(void);
 extern void scsi_mem_init(unsigned long);
@@ -29,6 +29,8 @@
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
+extern char empty_zero_page[PAGE_SIZE];
+
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
@@ -45,86 +47,177 @@
 pte_t * __bad_pagetable(void)
 {
 	extern char empty_bad_page_table[PAGE_SIZE];
-	unsigned long dummy;
+	unsigned long page;
+	unsigned long dummy1, dummy2;
 
+	page = ((unsigned long)empty_bad_page_table) + (PT_OFFSET - PAGE_OFFSET);
+#if __mips__ >= 3
+        /*
+         * Use 64bit code even for Linux/MIPS 32bit on R4000
+         */
 	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
+		".set\tnoreorder\n"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"dsll32\t$1,%2,0\n\t"
+		"dsrl32\t%2,$1,0\n\t"
+		"or\t%2,$1\n"
+		"1:\tsd\t%2,(%0)\n\t"
+		"subu\t%1,1\n\t"
+		"bnez\t%1,1b\n\t"
+		"addiu\t%0,8\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n"
+		".set\treorder"
+		:"=r" (dummy1),
+		 "=r" (dummy2)
+		:"r" (pte_val(BAD_PAGE)),
+		 "0" (page),
+		 "1" (PAGE_SIZE/8));
+#else
+	__asm__ __volatile__(
+		".set\tnoreorder\n"
 		"1:\tsw\t%2,(%0)\n\t"
-		"subu\t%1,%1,1\n\t"
-		"bne\t$0,%1,1b\n\t"
-		"addiu\t%0,%0,1\n\t"
+		"subu\t%1,1\n\t"
+		"bnez\t%1,1b\n\t"
+		"addiu\t%0,4\n\t"
 		".set\treorder"
-		:"=r" (dummy),
-		 "=r" (dummy)
+		:"=r" (dummy1),
+		 "=r" (dummy2)
 		:"r" (pte_val(BAD_PAGE)),
-		 "0" ((long) empty_bad_page_table),
-		 "1" (PTRS_PER_PAGE));
+		 "0" (page),
+		 "1" (PAGE_SIZE/4));
+#endif
 
-	return (pte_t *) empty_bad_page_table;
+	return (pte_t *)page;
 }
 
-pte_t __bad_page(void)
+static inline void
+__zeropage(unsigned long page)
 {
-	extern char empty_bad_page[PAGE_SIZE];
-	unsigned long dummy;
+	unsigned long dummy1, dummy2;
 
+#ifdef __R4000__
+        /*
+         * Use 64bit code even for Linux/MIPS 32bit on R4000
+         */
+	__asm__ __volatile__(
+		".set\tnoreorder\n"
+		".set\tnoat\n\t"
+		".set\tmips3\n"
+		"1:\tsd\t$0,(%0)\n\t"
+		"subu\t%1,1\n\t"
+		"bnez\t%1,1b\n\t"
+		"addiu\t%0,8\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n"
+		".set\treorder"
+		:"=r" (dummy1),
+		 "=r" (dummy2)
+		:"0" (page),
+		 "1" (PAGE_SIZE/8));
+#else
 	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
+		".set\tnoreorder\n"
 		"1:\tsw\t$0,(%0)\n\t"
-		"subu\t%1,%1,1\n\t"
-		"bne\t$0,%1,1b\n\t"
-		"addiu\t%0,%0,1\n\t"
+		"subu\t%1,1\n\t"
+		"bnez\t%1,1b\n\t"
+		"addiu\t%0,4\n\t"
 		".set\treorder"
-		:"=r" (dummy),
-		 "=r" (dummy)
-		:"0" ((long) empty_bad_page),
-		 "1" (PTRS_PER_PAGE));
+		:"=r" (dummy1),
+		 "=r" (dummy2)
+		:"0" (page),
+		 "1" (PAGE_SIZE/4));
+#endif
+}
 
-	return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
+static inline void
+zeropage(unsigned long page)
+{
+	sys_cacheflush((void *)page, PAGE_SIZE, BCACHE);
+	sync_mem();
+	__zeropage(page + (PT_OFFSET - PAGE_OFFSET));
+}
+
+pte_t __bad_page(void)
+{
+	extern char empty_bad_page[PAGE_SIZE];
+	unsigned long page = (unsigned long)empty_bad_page;
+
+	zeropage(page);
+	return pte_mkdirty(mk_pte(page, PAGE_SHARED));
 }
 
 unsigned long __zero_page(void)
 {
-	extern char empty_zero_page[PAGE_SIZE];
-	unsigned long dummy;
+	unsigned long page = (unsigned long) empty_zero_page;
 
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		"1:\tsw\t$0,(%0)\n\t"
-		"subu\t%1,%1,1\n\t"
-		"bne\t$0,%1,1b\n\t"
-		"addiu\t%0,%0,1\n\t"
-		".set\treorder"
-		:"=r" (dummy),
-		 "=r" (dummy)
-		:"0" ((long) empty_zero_page),
-		 "1" (PTRS_PER_PAGE));
+	zeropage(page);
+	return page;
+}
 
-	return (unsigned long) empty_zero_page;
+/*
+ * This is horribly inefficient ...
+ */
+void __copy_page(unsigned long from, unsigned long to)
+{
+	/*
+	 * Now copy page from uncached KSEG1 to KSEG0.  The copy destination
+	 * is in KSEG0 so that we keep stupid L2 caches happy.
+	 */
+	if(from == (unsigned long) empty_zero_page)
+	{
+		/*
+		 * The page copied most is the COW empty_zero_page.  Since we
+		 * know it's contents we can avoid the writeback reading of
+		 * the page.  Speeds up the standard case alot.
+		 */
+		__zeropage(to);
+	}
+	else
+	{
+		/*
+		 * Force writeback of old page to memory.  We don't know the
+		 * virtual address, so we have to flush the entire cache ...
+		 */
+		sys_cacheflush(0, ~0, DCACHE);
+		sync_mem();
+		memcpy((void *) to,
+		       (void *) (from + (PT_OFFSET - PAGE_OFFSET)), PAGE_SIZE);
+	}
+	/*
+	 * Now writeback the page again if colour has changed.
+	 * Actually this does a Hit_Writeback, but due to an artifact in
+	 * the R4xx0 implementation this should be slightly faster.
+	 * Then sweep chipset controlled secondary caches and the ICACHE.
+	 */
+	if (page_colour(from) != page_colour(to))
+		sys_cacheflush(0, ~0, DCACHE);
+	sys_cacheflush(0, ~0, ICACHE);
 }
 
 void show_mem(void)
 {
-	int i,free = 0,total = 0,reserved = 0;
+	int i, free = 0, total = 0, reserved = 0;
 	int shared = 0;
 
 	printk("Mem-info:\n");
 	show_free_areas();
-	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-	i = high_memory >> PAGE_SHIFT;
+	printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+	i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
 	while (i-- > 0) {
 		total++;
-		if (mem_map[i] & MAP_PAGE_RESERVED)
+		if (mem_map[i].reserved)
 			reserved++;
-		else if (!mem_map[i])
+		else if (!mem_map[i].count)
 			free++;
 		else
-			shared += mem_map[i]-1;
+			shared += mem_map[i].count-1;
 	}
-	printk("%d pages of RAM\n",total);
-	printk("%d free pages\n",free);
-	printk("%d reserved pages\n",reserved);
-	printk("%d pages shared\n",shared);
+	printk("%d pages of RAM\n", total);
+	printk("%d free pages\n", free);
+	printk("%d reserved pages\n", reserved);
+	printk("%d pages shared\n", shared);
 	show_buffers();
 #ifdef CONFIG_NET
 	show_net_buffers();
@@ -133,56 +226,22 @@
 
 extern unsigned long free_area_init(unsigned long, unsigned long);
 
-/*
- * paging_init() sets up the page tables - note that the first 4MB are
- * already mapped by head.S.
- *
- * This routines also unmaps the page at virtual kernel address 0, so
- * that we can trap those pesky NULL-reference errors in the kernel.
- */
 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
 {
-	pgd_t * pg_dir;
-	pte_t * pg_table;
-	unsigned long tmp;
-	unsigned long address;
-
-	start_mem = PAGE_ALIGN(start_mem);
-	address = 0;
-	pg_dir = swapper_pg_dir;
-	while (address < end_mem) {
-		if (pgd_none(pg_dir[0])) {
-			pgd_set(pg_dir, (pte_t *) start_mem);
-			start_mem += PAGE_SIZE;
-		}
-		/*
-		 * also map it in at 0x00000000 for init
-		 */
-		pg_table = (pte_t *) pgd_page(pg_dir[0]);
-		pgd_set(pg_dir, pg_table);
-		pg_dir++;
-		for (tmp = 0 ; tmp < PTRS_PER_PAGE ; tmp++,pg_table++) {
-			if (address < end_mem)
-				set_pte(pg_table, mk_pte(address, PAGE_SHARED));
-			else
-				pte_clear(pg_table);
-			address += PAGE_SIZE;
-		}
-	}
-#if KERNELBASE == KSEG0
-	cacheflush();
-#endif
-	invalidate();
+	pgd_init((unsigned long)swapper_pg_dir - (PT_OFFSET - PAGE_OFFSET));
 	return free_area_init(start_mem, end_mem);
 }
 
 void mem_init(unsigned long start_mem, unsigned long end_mem)
 {
 	int codepages = 0;
-	int reservedpages = 0;
 	int datapages = 0;
 	unsigned long tmp;
-	extern int etext;
+	extern int _etext;
+
+#ifdef CONFIG_MIPS_JAZZ
+	start_mem = vdma_init(start_mem, end_mem);
+#endif
 
 	end_mem &= PAGE_MASK;
 	high_memory = end_mem;
@@ -190,10 +249,12 @@
 	/* mark usable pages in the mem_map[] */
 	start_mem = PAGE_ALIGN(start_mem);
 
-	while (start_mem < high_memory) {
-		mem_map[MAP_NR(start_mem)] = 0;
-		start_mem += PAGE_SIZE;
+	tmp = start_mem;
+	while (tmp < high_memory) {
+		mem_map[MAP_NR(tmp)].reserved = 0;
+		tmp += PAGE_SIZE;
 	}
+
 #ifdef CONFIG_DESKSTATION_TYNE
 	deskstation_tyne_dma_init();
 #endif
@@ -203,33 +264,24 @@
 #ifdef CONFIG_SOUND
 	sound_mem_init();
 #endif
-	for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) {
-		if (mem_map[MAP_NR(tmp)]) {
-			/*
-			 * We don't have any reserved pages on the
-			 * MIPS systems supported until now
-			 */
-			if (0)
-				reservedpages++;
-			else if (tmp < ((unsigned long) &etext - KERNELBASE))
+	for (tmp = PAGE_OFFSET ; tmp < high_memory ; tmp += PAGE_SIZE) {
+		if (mem_map[MAP_NR(tmp)].reserved) {
+			if (tmp < (unsigned long) &_etext)
 				codepages++;
-			else
+			else if (tmp < start_mem)
 				datapages++;
 			continue;
 		}
-		mem_map[MAP_NR(tmp)] = 1;
+		mem_map[MAP_NR(tmp)].count = 1;
 		free_page(tmp);
 	}
 	tmp = nr_free_pages << PAGE_SHIFT;
-	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
+	printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n",
 		tmp >> 10,
-		high_memory >> 10,
+		(high_memory - PAGE_OFFSET) >> 10,
 		codepages << (PAGE_SHIFT-10),
-		reservedpages << (PAGE_SHIFT-10),
 		datapages << (PAGE_SHIFT-10));
-	pg0[0] = pte_val(mk_pte(0, PAGE_READONLY));
 
-	invalidate();
 	return;
 }
 
@@ -243,12 +295,12 @@
 	val->freeram = nr_free_pages << PAGE_SHIFT;
 	val->bufferram = buffermem;
 	while (i-- > 0)  {
-		if (mem_map[i] & MAP_PAGE_RESERVED)
+		if (mem_map[i].reserved)
 			continue;
 		val->totalram++;
-		if (!mem_map[i])
+		if (!mem_map[i].count)
 			continue;
-		val->sharedram += mem_map[i]-1;
+		val->sharedram += mem_map[i].count-1;
 	}
 	val->totalram <<= PAGE_SHIFT;
 	val->sharedram <<= PAGE_SHIFT;
diff -u --recursive --new-file v1.3.47/linux/drivers/Makefile linux/drivers/Makefile
--- v1.3.47/linux/drivers/Makefile	Mon Oct 23 18:02:01 1995
+++ linux/drivers/Makefile	Thu Dec 14 16:02:24 1995
@@ -9,7 +9,7 @@
 
 SUB_DIRS     := block char net #streams
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sound
+ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sound cdrom
 
 ifdef CONFIG_PCI
 SUB_DIRS += pci
diff -u --recursive --new-file v1.3.47/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v1.3.47/linux/drivers/block/Makefile	Mon Dec 11 15:42:00 1995
+++ linux/drivers/block/Makefile	Thu Dec 14 08:16:53 1995
@@ -16,7 +16,7 @@
 
 
 L_TARGET := block.a
-L_OBJS   := ll_rw_blk.o ramdisk.o genhd.o 
+L_OBJS   := ll_rw_blk.o rd.o genhd.o 
 M_OBJS   :=
 MOD_LIST_NAME := BLOCK_MODULES
 
diff -u --recursive --new-file v1.3.47/linux/drivers/block/README.ide linux/drivers/block/README.ide
--- v1.3.47/linux/drivers/block/README.ide	Mon Dec 11 15:42:00 1995
+++ linux/drivers/block/README.ide	Sun Dec 17 11:17:19 1995
@@ -12,6 +12,8 @@
 
 Major features of ide.c & ide-cd.c:
 
+NEW!	- support for IDE ATAPI *tape* drives, courtesy of Gadi Oxman
+		(run MAKEDEV.ide to create the tape device entries in /dev/)
 NEW!	- support for up to *four* IDE interfaces on one or more IRQs
 NEW!	- support for any mix of up to *eight* disk and/or cdrom drives
 	- support for reading IDE ATAPI cdrom drives (NEC,MITSUMI,VERTOS,SONY)
diff -u --recursive --new-file v1.3.47/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c
--- v1.3.47/linux/drivers/block/cmd640.c	Mon Dec 11 15:42:00 1995
+++ linux/drivers/block/cmd640.c	Sun Dec 17 11:17:19 1995
@@ -237,7 +237,7 @@
 {
 	int  i;
 	int  second_port;
-	int  read_ahead;
+	int  cmd_read_ahead;
 	byte b;
 
 	for (i = 0; i < MAX_HWIFS; i++)
@@ -287,13 +287,13 @@
 	 */
 	bus_speed = (bus_type == vlb) ? 50 : 40; 
 
-#if 0	/* don't know if this is reliable yet */
+#if 1	/* don't know if this is reliable yet */
 	/*
 	 * Enable readahead for versions above 'A'
 	 */
-	read_ahead = (cmd640_chip_version > 1);
+	cmd_read_ahead = (cmd640_chip_version > 1);
 #else
-	read_ahead = 0;
+	cmd_read_ahead = 0;
 #endif
 	/*
 	 * Setup Control Register
@@ -303,7 +303,7 @@
 		b |= CNTRL_ENA_2ND;
 	else
 		b &= ~CNTRL_ENA_2ND;
-	if (read_ahead)
+	if (cmd_read_ahead)
 		b &= ~(CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
 	else
 		b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
@@ -314,7 +314,7 @@
 	 */
 	if (second_port) {
 		/* We reset timings, and setup read-ahead */
-		b = read_ahead ? 0 : (DIS_RA2 | DIS_RA3);
+		b = cmd_read_ahead ? 0 : (DIS_RA2 | DIS_RA3);
 		put_cmd640_reg(cmd640_key, ARTTIM23, b);
 		put_cmd640_reg(cmd640_key, DRWTIM23, 0);
 	}
@@ -343,7 +343,7 @@
 	put_cmd640_reg(cmd640_key, CMDTIM, 0);
 
 	printk("\n ... serialized, %s read-ahead, secondary interface %s\n",
-	       read_ahead ? "enabled" : "disabled",
+	       cmd_read_ahead ? "enabled" : "disabled",
 	       second_port ? "enabled" : "disabled");
 
 	return 1;
diff -u --recursive --new-file v1.3.47/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v1.3.47/linux/drivers/block/genhd.c	Mon Nov 27 12:48:28 1995
+++ linux/drivers/block/genhd.c	Thu Dec 14 08:16:53 1995
@@ -30,7 +30,6 @@
 static int current_minor = 0;
 extern int *blk_size[];
 extern void rd_load(void);
-extern int ramdisk_size;
 
 extern int chr_dev_init(void);
 extern int blk_dev_init(void);
@@ -559,6 +558,5 @@
 		nr += p->nr_real;
 	}
 
-	if (ramdisk_size)
-		rd_load();
+	rd_load();
 }
diff -u --recursive --new-file v1.3.47/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- v1.3.47/linux/drivers/block/ide-tape.c	Mon Dec 11 15:42:01 1995
+++ linux/drivers/block/ide-tape.c	Sun Dec 17 11:17:19 1995
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/block/ide-tape.c	Version 1.0 - ALPHA	Dec  3, 1995
+ * linux/drivers/block/ide-tape.c	Version 1.1 - ALPHA	Dec  14, 1995
  *
  * Copyright (C) 1995 Gadi Oxman <tgud@tochnapc2.technion.ac.il>
  *
@@ -17,14 +17,15 @@
  * This driver is a part of the Linux ide driver and works in co-operation
  * with linux/drivers/block/ide.c.
  *
- * This driver provides both a block device and a character device interface to
- * the tape. The driver, in co-operation with ide.c, basically traverses the
- * request-list for the block device interface. The character device interface,
- * on the other hand, creates new requests, adds them to the request-list
- * of the block device, and waits for their completion.
+ * The driver, in co-operation with ide.c, basically traverses the 
+ * request-list for the block device interface. The character device
+ * interface, on the other hand, creates new requests, adds them
+ * to the request-list of the block device, and waits for their completion.
+ *
+ * Pipelined operation mode is now supported on writes.
  *
  * The block device major and minor numbers are determined from the
- * tape relative position in the ide interfaces, as explained in ide.c.
+ * tape's relative position in the ide interfaces, as explained in ide.c.
  *
  * The character device interface consists of two devices:
  *
@@ -34,19 +35,15 @@
  * Run /usr/src/linux/drivers/block/MAKEDEV.ide to create the above entries.
  * We currently support only one ide tape drive.
  *
- * Although we do support requests which originate from the buffer cache to
- * some extent, it is recommended to use the character device interface when
- * performing a long read or write operation (relative to the amount of free
- * memory in your system). Otherwise, free memory will be used to cache tape
- * blocks, those cached blocks won't be used, Linux's responsiveness will
- * suffer as we start to swap.
- *
  * The general magnetic tape commands compatible interface, as defined by
  * include/linux/mtio.h, is accessible through the character device.
- * Our own ide-tape ioctl's can can be issued to either the block device or
- * the character device.
  *
- * Opening the block device interface will be refused by default.
+ * General ide driver configuration options, such as the interrupt-unmask
+ * flag, can be configured by issuing an ioctl to the block device interface,
+ * as any other ide device.
+ *
+ * Our own ide-tape ioctl's can can be issued to either the block device or
+ * the character device interface.
  *
  * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
  *
@@ -86,14 +83,14 @@
  *                        performing one tape r/w request, a lot of requests
  *                        from the other device can be queued and ide.c will
  *			  service all of them after this single tape request.
- * Ver 1.0   ???         Integrated into Linux 1.3.??? development tree.
+ * Ver 1.0   Dec 11 95   Integrated into Linux 1.3.46 development tree.
  *                       On each read / write request, we now ask the drive
  *                        if we can transfer a constant number of bytes
  *                        (a parameter of the drive) only to its buffers,
  *                        without causing actual media access. If we can't,
  *                        we just wait until we can by polling the DSC bit.
  *                        This ensures that while we are not transferring
- *                        more bytes than the constant reffered to above, the
+ *                        more bytes than the constant referred to above, the
  *                        interrupt latency will not become too high and
  *                        we won't cause an interrupt timeout, as happened
  *                        occasionally in the previous version.
@@ -118,6 +115,26 @@
  *                       Our data transfer buffer is allocated on startup,
  *                        rather than before each data transfer. This should
  *                        ensure that we will indeed have a data buffer.
+ * Ver 1.1   Dec 14 95   Fixed random problems which occured when the tape
+ *                        shared an interface with another device.
+ *                        (poll_for_dsc was a complete mess).
+ *                       Removed some old (non-active) code which had
+ *                        to do with supporting buffer cache originated
+ *                        requests.
+ *                       The block device interface can now be opened, so
+ *                        that general ide driver features like the unmask
+ *                        interrupts flag can be selected with an ioctl.
+ *                        This is the only use of the block device interface.
+ *                       New fast pipelined operation mode (currently only on
+ *                        writes). When using the pipelined mode, the
+ *                        throughput can potentially reach the maximum
+ *                        tape supported throughput, regardless of the
+ *                        user backup program. On my tape drive, it sometimes
+ *                        boosted performance by a factor of 2. Pipelined
+ *                        mode is enabled by default, but since it has a few
+ *                        downfalls as well, you may want to disable it.
+ *                        A short explanation of the pipelined operation mode
+ *                        is available below.
  *
  * We are currently in an *alpha* stage. The driver is not complete and not
  * much tested. I would strongly suggest to:
@@ -135,6 +152,72 @@
  *
  */
 
+/*
+ * A short explanation of the pipelined operation mode.
+ *
+ * Pipelined mode is currently only implemented on writes. Reads are still
+ * performed in the slow non-pipelined mode.
+ *
+ * The pipeline mode, when enough pipeline stages are available, manages to
+ * keep the tape constantly streaming with the maximum device supported
+ * throughput, regardless of the user backup program, since even when Linux
+ * is busy doing other tasks, we still have job to be done.
+ *
+ * On my tape drive, using pipelined mode and giving the tape its own
+ * interface and irq, I get a constant over 400 KBps throughput, which seems
+ * to be the maximum throughput supported by my tape. When sharing the
+ * interface between the tape and another ata-2 disk drive, I receive around
+ * 350 KBps.
+ *
+ * Using the non-pipelined mode, I get anything between 150 to 380 KBps,
+ * with the average being around 150 or 250 KBps, depending mainly on
+ * the double buffering capabilities of the user backup program, but also
+ * on some additional factors, such as the user block size and the ongoing
+ * disk activity.
+ *
+ * However, there are some downfalls:
+ *
+ *	1.	We use memory (for data buffers) in proportional to the number
+ *		of pipeline stages (each stage is about 26 KB with my tape).
+ *	2.	We cheat and postpone error codes to the user task. Again,
+ *		the postponing period is proportional to the number of stages.
+ *
+ * Concerning (1):
+ *
+ *	1.	We allocate stages dynamically only when we need them. When
+ *		we don't need them, we don't consume additional memory. In
+ *		case we can't allocate stages, we just manage without them
+ *		(at the expense of decreased throughput) so when Linux is
+ *		tight in memory, we will not pose additional difficulties.
+ *
+ *	2.	The maximum number of stages (which is, in fact, the maximum
+ *		amount of memory) which we allocate is limited by the compile
+ *		time parameter IDETAPE_MAX_PIPELINE_STAGES.
+ *
+ *	3.	The maximum number of stages is a controlled parameter - We
+ *		don't start from the user defined maximum number of stages
+ *		but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we
+ *		will not even allocate this amount of stages if the user
+ *		program can't handle the speed). We then implement a feedback
+ *		loop which checks if the pipeline is empty, and if it is, we
+ *		increase the maximum number of stages as necessary until we
+ *		reach the optimum value which just manages to keep the tape
+ *		busy with with minimum allocated memory or until we reach
+ *		IDETAPE_MAX_PIPELINE_STAGES.
+ *
+ * Concerning (2):
+ *
+ *	In pipelined mode, ide-tape can not return accurate error codes to
+ *      the user program since we usually just add the request to the
+ *      pipeline without waiting for it to be serviced. In case an error
+ *      occurs, I will report it on the next user request.
+ *
+ *	For accurate error codes, you should disable pipelined mode.
+ *
+ * You can enable/disable/tune the pipelined operation mode by adjusting
+ * the compile time parameters in ide-tape.h.
+ */
+ 
 #include <linux/hdreg.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -161,7 +244,7 @@
 /*
  *	Main Linux ide driver include file
  *
- *	Automatically includes our first include file - ide-tape1.h.
+ *	Automatically includes our include file - ide-tape.h.
  */
  
 #include "ide.h"		
@@ -214,6 +297,8 @@
  *
  */
 
+#define	IDETAPE_FIRST_REQUEST			90
+
 /*
  * 	IDETAPE_PACKET_COMMAND_REQUEST_TYPE1 is used to queue a packet command
  *	in the request queue. We will wait for DSC before issuing the command
@@ -242,6 +327,15 @@
 #define	IDETAPE_READ_REQUEST			92
 #define	IDETAPE_WRITE_REQUEST			93
 
+#define IDETAPE_LAST_REQUEST			93
+
+/*
+ *	A macro which can be used to check if a we support a given
+ *	request command.
+ */
+
+#define IDETAPE_REQUEST_CMD(cmd) 	((cmd >= IDETAPE_FIRST_REQUEST) && (cmd <= IDETAPE_LAST_REQUEST))
+
 /*
  *	We are now able to postpone an idetape request in the stage
  *	where it is polling for DSC and service requests from the other
@@ -629,7 +723,7 @@
  
 void idetape_postpone_request (ide_drive_t *drive);
 void idetape_poll_for_dsc (unsigned long data);
-void idetape_put_back_postponed_request (ide_drive_t *drive);
+void idetape_poll_for_dsc_direct (unsigned long data);
 void idetape_media_access_finished (ide_drive_t *drive);
 
 /*
@@ -695,10 +789,29 @@
  */
  
 int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count);
+
+/*
+ *	idetape_add_chrdev_write_request adds a character device write
+ *	request to the pipeline.
+ */
+ 
+int idetape_add_chrdev_write_request (ide_drive_t *drive,int cmd,int blocks,char *buffer);
+
+/*
+ *	idetape_queue_rw_tail will add a command to the tail of the device
+ *	request queue and wait for it to finish. This is used when we
+ *	can not allocate pipeline stages (or in non-pipelined mode).
+ */
+ 
 int idetape_queue_rw_tail (ide_drive_t *drive,int cmd,int blocks,char *buffer);
+
+/*
+ *	Adds a packet command request to the tail of the device request
+ *	queue and waits for it to be serviced.
+ */
+ 
 int idetape_queue_pc_tail (ide_drive_t *drive,idetape_packet_command_t *pc);
 
-void idetape_fake_read (ide_drive_t *drive);
 int idetape_position_tape (ide_drive_t *drive,unsigned long block);
 int idetape_rewind_tape (ide_drive_t *drive);
 
@@ -712,11 +825,24 @@
  *	General utility functions
  */
  
-void idetape_fixstring (byte *s, const int bytecount, const int byteswap);
 unsigned long idetape_swap_long (unsigned long temp);
 unsigned short idetape_swap_short (unsigned short temp);
 
 /*
+ *	Pipeline related functions
+ */
+
+idetape_pipeline_stage_t *idetape_kmalloc_stage (ide_drive_t *drive);
+void idetape_kfree_stage (idetape_pipeline_stage_t *stage);
+void idetape_copy_buffer_from_stage (idetape_pipeline_stage_t *stage,char *buffer);
+void idetape_copy_buffer_to_stage (idetape_pipeline_stage_t *stage,char *buffer);
+void idetape_increase_max_pipeline_stages (ide_drive_t *drive);
+void idetape_add_stage_tail (ide_drive_t *drive,idetape_pipeline_stage_t *stage);
+void idetape_active_next_stage (ide_drive_t *drive);
+void idetape_empty_pipeline (ide_drive_t *drive);
+void idetape_insert_pipeline_into_queue (ide_drive_t *drive);
+
+/*
  *	For general magnetic tape device compatibility.
  */
  
@@ -972,37 +1098,62 @@
 void idetape_setup (ide_drive_t *drive)
 
 {
-	int buffer_size;
 	idetape_tape_t *tape=&(drive->tape);
-
+	unsigned int allocation_length;
+	
 #if IDETAPE_DEBUG
 	printk ("ide-tape: Reached idetape_setup\n");
 #endif /* IDETAPE_DEBUG */	
 	
 	drive->ready_stat = 0;			/* With an ATAPI device, we can issue packet commands */
 						/* regardless of the state of DRDY */
+	HWIF(drive)->tape_drive=drive;
+
 	tape->block_address=0;			
 	tape->block_address_valid=0;
-	tape->locate_to=0;
-	tape->locate_retries=0;
 	tape->pc_stack_index=0;
 	tape->failed_pc=NULL;
 	tape->postponed_rq=NULL;
-	tape->last_written_valid=0;
 	tape->busy=0;
-	
+	tape->active_data_request=NULL;
+	tape->current_number_of_stages=0;
+	tape->first_stage=tape->last_stage=NULL;
+	tape->pipeline_was_full_once=0;
+	tape->error_in_pipeline_stage=0;
+	tape->pipeline_locked=0;
+
+	tape->request_status=0;
+	tape->request_dsc_callback=0;
+	
+#if IDETAPE_PIPELINE
+	tape->max_number_of_stages=IDETAPE_MIN_PIPELINE_STAGES;
+	printk ("ide-tape: Operating in pipelined (fast and tricky) write mode.\n");
+#else
+	tape->max_number_of_stages=0;
+	printk ("ide-tape: Operating in non-pipelined (slow and safe) write mode.\n");
+#endif /* IDETAPE_PIPELINE */
+	printk ("ide-tape: Operating in non-pipelined (slow and safe) read mode.\n");
+
 	idetape_get_mode_sense_results (drive);
 
-	buffer_size=tape->capabilities.ctl*tape->tape_block_size;
-	tape->data_buffer=kmalloc (buffer_size,GFP_KERNEL);
-	if (tape->data_buffer == NULL) {
-		printk ("ide-tape: FATAL - Can not allocate %d bytes for data transfer buffer\n",buffer_size);
+	tape->data_buffer_size=tape->capabilities.ctl*tape->tape_block_size;
+
+	allocation_length=tape->data_buffer_size;
+	if (tape->data_buffer_size % IDETAPE_ALLOCATION_BLOCK)
+		allocation_length+=IDETAPE_ALLOCATION_BLOCK;
+	
+	tape->data_buffer=kmalloc (allocation_length,GFP_KERNEL);
+	tape->temp_data_buffer=kmalloc (allocation_length,GFP_KERNEL);
+	if (tape->data_buffer == NULL || tape->temp_data_buffer == NULL) {
+		printk ("ide-tape: FATAL - Can not allocate 2 buffers of %d bytes each\n",allocation_length);
 		printk ("ide-tape: Aborting character device installation\n");
 		idetape_drive_already_found=0;
 		unregister_chrdev (idetape_chrdev.major,idetape_chrdev.name);
 		return;
 	}
-	printk ("ide-tape: Speed - %d KBps. Recommended transfer unit - %d bytes.\n",tape->capabilities.speed,buffer_size);
+
+	printk ("ide-tape: Tape speed - %d KBps. Recommended transfer unit - %d bytes.\n",tape->capabilities.speed,tape->data_buffer_size);
+
 	return;
 }
 
@@ -1129,7 +1280,7 @@
 
 	tape=&(drive->tape);
 	        
-#ifdef IDETAPE_DEBUG
+#if IDETAPE_DEBUG
 	if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
 		printk ("ide-tape: ide-tape.c bug - Two request sense in serial were issued\n");
 		/* ??? Need to rethink about that */		
@@ -1262,7 +1413,7 @@
 		if (pc->callback==NULL)			
 			printk ("ide-tape: ide-tape bug - Callback function not set !\n");
 		else
-#endif IDETAPE_DEBUG
+#endif /* IDETAPE_DEBUG */
 			(*pc->callback)(drive);			/* Command finished - Call the callback function */
 		return;
 	}
@@ -1334,16 +1485,19 @@
 	idetape_tape_t *tape;
 	unsigned long flags;
 	struct request *rq;
-		
+	idetape_status_reg_t status;
+	
 	tape=&(drive->tape);
+	status.all=IN_BYTE (IDETAPE_STATUS_REG);
 
+	sti ();
+	
 #if IDETAPE_DEBUG
 	printk ("Reached idetape_postpone_request\n");
 	if (tape->postponed_rq != NULL)
 		printk ("ide-tape.c bug - postponed_rq not NULL in idetape_postpone_request\n");
 #endif /* IDETAPE_DEBUG */
 
-	tape->dsc_count=0;
 	tape->dsc_timer.expires=jiffies + tape->dsc_polling_frequency;	/* Set timer to poll for */
 	tape->dsc_timeout=jiffies+IDETAPE_DSC_TIMEOUT;			/* actual completion */
 	tape->dsc_timer.data=(unsigned long) drive;
@@ -1353,61 +1507,55 @@
 	/*
 	 * Remove current request from the request queue:
 	 */
-	save_flags(flags);						/* Let ide.c handle another request */
-	cli();
+
 	tape->postponed_rq = rq = HWGROUP(drive)->rq;
 	rq->rq_status = IDETAPE_RQ_POSTPONED;	
+	save_flags(flags);cli ();					/* Let ide.c handle another request */
 	blk_dev[MAJOR(rq->rq_dev)].current_request = rq->next;
 	HWGROUP(drive)->rq = NULL;
 	restore_flags(flags);
-
-	tape->dsc_polling_start=jiffies;	
+	
+	tape->request_status=0;
+	tape->request_dsc_callback=0;
+	tape->last_status=status.all;
+	
+	tape->dsc_polling_start=jiffies;
 	add_timer(&(tape->dsc_timer));		/* Activate the polling timer */
 }
 
-
 /*
- *	idetape_poll_for_dsc gets invoked by a timer (which was set
- *	by idetape_postpone_request) to poll for the DSC bit
- *	in the status register. When the DSC bit is set, or a timeout is
- *	reached, we put back the postponed request in front of the request
- *	queue.
+ *	idetape_poll_for_dsc_direct is called from idetape_poll_for_dsc
+ *	to handle the case in which we can safely communicate with the tape
+ *	(since no other request for this hwgroup is active).
  */
  
-void idetape_poll_for_dsc (unsigned long data)
+void idetape_poll_for_dsc_direct (unsigned long data)
 
 {
-	ide_drive_t *drive;
-	idetape_tape_t *tape;
-	
+	ide_drive_t *drive=(ide_drive_t *) data;
+	ide_hwgroup_t *hwgroup=HWGROUP (drive);
+	idetape_tape_t *tape=&(drive->tape);
 	idetape_status_reg_t status;
-	idetape_packet_command_t *pc;
+	unsigned long flags;
 
-	drive=(ide_drive_t *) data;
-	tape=&(drive->tape);
-	pc=tape->pc;
-	
 #if IDETAPE_DEBUG
-	printk ("%s: idetape_poll_for_dsc called\n",drive->name);
+	printk ("%s: idetape_poll_for_dsc_direct called\n",drive->name);
 #endif /* IDETAPE_DEBUG */	
 
+	save_flags (flags);cli ();
+	OUT_BYTE(drive->select.all,IDE_SELECT_REG);
 	status.all=IN_BYTE (IDETAPE_STATUS_REG);
+	if (hwgroup->drive != NULL)
+		OUT_BYTE (hwgroup->drive->select.all,IDE_SELECT_REG);
+	restore_flags (flags);
 
-	if (status.b.dsc)
-		tape->dsc_count++;
-	else {
-		if (tape->dsc_count)
-			printk ("ide-tape: DSC fluctuation detected - Restarting DSC count\n");
-		tape->dsc_count=0;
-	}
-
-	if (tape->dsc_count == IDETAPE_DSC_COUNT) {		/* DSC received */
+	if (status.b.dsc) {					/* DSC received */
 		tape->dsc_received=1;
 		del_timer (&(tape->dsc_timer));			/* Stop polling and put back the postponed */
 		idetape_put_back_postponed_request (drive);	/* request in the request queue */
 		return;
 	}
-		
+
 	if (jiffies > tape->dsc_timeout) 	{ /* Timeout */
 		tape->dsc_received=0;
 		del_timer (&(tape->dsc_timer));
@@ -1415,23 +1563,129 @@
 		idetape_put_back_postponed_request (drive);
 		return;
 	}
-	
+
 	/* Poll again */
+	
+	if (jiffies - tape->dsc_polling_start > IDETAPE_FAST_SLOW_THRESHOLD)
+		tape->dsc_timer.expires = jiffies + IDETAPE_DSC_SLOW_MEDIA_ACCESS_FREQUENCY;
+	else
+		tape->dsc_timer.expires = jiffies + tape->dsc_polling_frequency;
+	add_timer(&(tape->dsc_timer));
+	return;
+}
+
+/*
+ *	idetape_poll_for_dsc gets invoked by a timer (which was set
+ *	by idetape_postpone_request) to poll for the DSC bit
+ *	in the status register.
+ *
+ *	We take care not to perform any tape access and not to touch the
+ *	device request queue if the driver is accessing the other device.
+ *	We will instead ask ide.c to perform those functions on the next
+ *	call to do_request, at the point in which the other device is idle.
+ *
+ *	However, in case the other device is already idle, we will read
+ *	the status register from our timer handler.
+ *
+ *	I am also a bit paranoid with the use of cli (), all through the
+ *	code. I still need to think harder about each one whether we can
+ *	avoid it and still be free of race conditions ...
+ */
+ 
+void idetape_poll_for_dsc (unsigned long data)
+
+{
+	ide_drive_t *drive=(ide_drive_t *) data;
+	unsigned int major = HWIF(drive)->major;
+	idetape_tape_t *tape=&(drive->tape);
+	struct blk_dev_struct *bdev = &blk_dev[major];
+	unsigned long flags;
+	
+	idetape_status_reg_t status;
+
+	save_flags (flags);cli ();
+			
+#if IDETAPE_DEBUG
+	printk ("%s: idetape_poll_for_dsc called\n",drive->name);
+#endif /* IDETAPE_DEBUG */	
+
+	/*
+	 *	Check if the other device is idle. If there are no requests,
+	 *	we can safely access the tape.
+	 */
 
+	if (bdev->current_request == NULL) {
+		restore_flags (flags);
+		idetape_poll_for_dsc_direct (data);
+		return;
+	}
+	
+	if (bdev->current_request->next == NULL) {
+		/*
+		 *	There will not be another request after the currently
+		 *	ongoing request, so ide.c won't be able to sample
+		 *	the status register on our behalf in do_request. Just
+		 *	give up and poll again (in a faster frequency), until
+		 *	we are lucky.
+		 */
+		restore_flags (flags);
+		tape->dsc_timer.expires = jiffies + tape->dsc_polling_frequency/2;
+		add_timer(&(tape->dsc_timer));
+		return;
+	}
+	
+	/*
+	 *	We now know that:
+	 *
+	 *		1.	The ide driver is potentially accessing
+	 *			the other device -- We can not touch it.
+	 *		2.	do_request will be called after the current
+	 *			request is finished.
+	 *
+	 *	We will therefor ask ide.c to perform the tasks on our behalf.
+	 */
+	 
+	status.all=tape->last_status;
+	
+	if (status.b.dsc) {					/* DSC received */
+		tape->dsc_received=1;
+		del_timer (&(tape->dsc_timer));			/* Stop polling and request ide.c to call */
+		tape->request_dsc_callback=1;			/* our idetape_put_back_postponed_request later */
+		restore_flags (flags);		
+		return;
+	}
+
+	if (jiffies > tape->dsc_timeout) 	{ 		/* Timeout */
+		tape->dsc_received=1;
+		del_timer (&(tape->dsc_timer));
+		/* ??? */
+		tape->request_dsc_callback=1;
+		restore_flags (flags);
+		return;
+	}
+
+	/*
+	 *	Request ide.c to sample for us the tape's status register on
+	 *	the next time in which it can be safely done.
+	 */
+
+	tape->request_status=1;
+	restore_flags (flags);
+		 
+	/* Poll again */
+	
 	if (jiffies - tape->dsc_polling_start > IDETAPE_FAST_SLOW_THRESHOLD)
 		tape->dsc_timer.expires = jiffies + IDETAPE_DSC_SLOW_MEDIA_ACCESS_FREQUENCY;
 	else
 		tape->dsc_timer.expires = jiffies + tape->dsc_polling_frequency;
-/*	init_timer (&(tape->dsc_timer)); */
 	add_timer(&(tape->dsc_timer));
 	return;
 }
 
 /*
- *	idetape_put_back_postponed_request gets called by
- *	idetape_poll_for_dsc when we decided to stop polling - Either
- *	becase we received DSC or because we decided to give up and
- *	stop waiting.
+ *	idetape_put_back_postponed_request gets called by do_request
+ *	in ide.c when we decided to stop polling for DSC and continue
+ *	servicing our postponed request.
  */
 
 void idetape_put_back_postponed_request (ide_drive_t *drive)
@@ -1571,7 +1825,7 @@
 #if IDETAPE_DEBUG	
 	printk ("ide-tape: Reached idetape_read_callback\n");
 #endif /* IDETAPE_DEBUG */
-	tape->block_address+=tape->pc->actually_transferred/512;
+	tape->block_address+=tape->pc->actually_transferred/tape->tape_block_size;
 	if (!tape->pc->error) {
 #if IDETAPE_DEBUG
 		printk ("Request completed\n");
@@ -1588,33 +1842,6 @@
 	return;
 }
 
-void idetape_fake_read (ide_drive_t *drive)
-
-{
-	idetape_tape_t *tape;
-	struct request *rq;
-	unsigned long i;
-
-	tape=&(drive->tape);	
-	rq=HWGROUP(drive)->rq;
-#if IDETAPE_DEBUG	
-	printk ("ide-tape: Reached idetape_fake_read\n");
-#endif /* IDETAPE_DEBUG */
-
-#if IDETAPE_DEBUG
-	printk ("Request completed\n");
-#endif /* IDETAPE_DEBUG */
-	
-	for (i=0;i<rq->current_nr_sectors*512;i++)
-		rq->buffer [i]=0;
-
-	tape->block_address+=rq->current_nr_sectors;
-	rq->sector+=rq->current_nr_sectors;
-	rq->nr_sectors-=rq->current_nr_sectors;
-	rq->current_nr_sectors=0;
-	idetape_end_request (1,HWGROUP (drive));
-}
-
 void idetape_write_callback (ide_drive_t *drive)
 
 {
@@ -1626,7 +1853,7 @@
 #if IDETAPE_DEBUG	
 	printk ("ide-tape: Reached idetape_write_callback\n");
 #endif /* IDETAPE_DEBUG */
-	tape->block_address+=tape->pc->actually_transferred/512;
+	tape->block_address+=tape->pc->actually_transferred/tape->tape_block_size;
 	if (!tape->pc->error) {
 #if IDETAPE_DEBUG
 		printk ("Request completed\n");
@@ -1743,9 +1970,9 @@
 	idetape_inquiry_result_t *result;
 
 	result=(idetape_inquiry_result_t *) buffer;
-	idetape_fixstring (result->vendor_id,8,0);
-	idetape_fixstring (result->product_id,16,0);
-	idetape_fixstring (result->revision_level,4,0);
+	ide_fixstring (result->vendor_id,8,0);
+	ide_fixstring (result->product_id,16,0);
+	ide_fixstring (result->revision_level,4,0);
 
 	if (result->response_format != 2) {
 		printk ("The INQUIRY Data Format is unknown to us !\n");
@@ -2258,26 +2485,54 @@
 {
 	ide_drive_t *drive = hwgroup->drive;
 	struct request *rq = hwgroup->rq;
-
-	if (rq->cmd == READ || rq->cmd == WRITE) {	/* Buffer cache originated request */
-		ide_end_request (uptodate,hwgroup);	/* Let the common code handle it */
-		return;
-	}
+	idetape_tape_t *tape = &(drive->tape);
+	
 							/* Our own originated request */
 	rq->errors=!uptodate;				/* rq->errors will tell us if the request was successfull */
-	ide_end_drive_cmd (drive, 0, 0);
+	
+	if (tape->active_data_request == rq) {		/* The request was a data transfer request */
+#if IDETAPE_DEBUG
+		if (!tape->max_number_of_stages)
+			printk ("ide-tape: non pipelined mode bug\n");
+		printk ("Finished our active data request\n");
+		printk ("Requests in pipeline: %d\n",tape->current_number_of_stages);
+#endif /* IDETAPE_DEBUG */
+		if (rq->errors)
+			tape->error_in_pipeline_stage=1;
 
-	/* The "up(rq->sem);" does the necessary "wake_up()" for us,
-	 * providing we started sleeping with a "down()" call.
-	 * This may not be the case if the driver converts a READ or WRITE
-	 * request into a special internal rq->cmd type.   -ml
-	 */
-	 
-	 /*
-	  * As Mark explained, we do not need a "wake_up()" call here,
-	  * since we are always sleeping with a "down()" call.
-	  */
+		/*
+		 *	Pass to the next stage, but avoid a possible
+		 *	race condition which could occur since
+		 *	active_data_request is set to NULL until
+		 *	idetape_active_next_stage returns, and in that
+		 *	time, the higher level of the driver can get
+		 *	an inaccurate sampling of this variable.
+		 */
+		 
+		tape->pipeline_locked=1;
+		tape->active_data_request = NULL;
+		if (tape->first_stage == NULL) {
+			tape->pipeline_locked=0;
+			idetape_increase_max_pipeline_stages (drive);
+			return;
+		}
+		idetape_active_next_stage (drive);
+		tape->pipeline_locked=0;
+#if IDETAPE_DEBUG
+		printk ("Using ide_end\n");
+#endif /* IDETAPE_DEBUG */
 
+		/*
+		 *	Insert the next request into the request queue.
+		 *
+		 *	We currently give higher priority to the other devie
+		 *	by using ide_end. ide_next can be used to give us
+		 *	a higher priority.
+		 */
+		 
+		ide_do_drive_cmd (drive,tape->active_data_request,ide_end);
+	}
+	ide_end_drive_cmd (drive, 0, 0);
 }
 
 /*
@@ -2287,19 +2542,33 @@
 void idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block)
 
 {
-	idetape_tape_t *tape;
+	idetape_tape_t *tape=&(drive->tape);
 	idetape_packet_command_t *pc;
-	struct request *new_rq;
 	idetape_status_reg_t status;
 
-	tape=&(drive->tape);
-		
 #if IDETAPE_DEBUG
 	printk ("Current request:\n");
 	printk ("rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
 	printk ("sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
 #endif /* IDETAPE_DEBUG */
 
+	if (!IDETAPE_REQUEST_CMD (rq->cmd)) {
+
+		/*
+		 *	We do not support buffer cache originated requests.
+		 */
+
+		printk ("ide-tape: Unsupported command in request queue\n");
+		printk ("ide-tape: The block device interface should not be used for data transfers.\n");
+		printk ("ide-tape: Use the character device interfaces\n");
+		printk ("ide-tape: /dev/ht0 and /dev/nht0 instead.\n");
+		printk ("ide-tape: (Run linux/drivers/block/MAKEDEV.ide to create them)\n");
+		printk ("ide-tape: Aborting request.\n");
+
+		ide_end_request (0,HWGROUP (drive));			/* Let the common code handle it */
+		return;
+	}
+
 	/* Retry a failed packet command */
 
 	if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
@@ -2310,13 +2579,13 @@
 	/* Check if we have a postponed request */
 	
 	if (tape->postponed_rq != NULL) {
-/* #if IDETAPE_DEBUG */
+ #if IDETAPE_DEBUG
 		if (tape->postponed_rq->rq_status != RQ_ACTIVE || rq != tape->postponed_rq) {
 			printk ("ide-tape: ide-tape.c bug - Two DSC requests were queued\n");
 			idetape_end_request (0,HWGROUP (drive));
 			return;
 		}
-/* #endif */ /* IDETAPE_DEBUG */
+#endif /* IDETAPE_DEBUG */
 		if (rq->cmd == IDETAPE_PACKET_COMMAND_REQUEST_TYPE1) {
 	
 			/* Media access command */
@@ -2335,69 +2604,10 @@
 		 tape->postponed_rq = NULL;
 	}	
 	
-
-	if (rq->cmd == READ || rq->cmd == IDETAPE_READ_REQUEST || rq->cmd == WRITE || rq->cmd == IDETAPE_WRITE_REQUEST) {
-
-		if (!tape->block_address_valid || tape->block_address!=rq->sector) {		/* Re-position the tape */
-		
-			if (tape->locate_to == rq->sector && tape->locate_retries > IDETAPE_LOCATE_RETRIES) {
-				printk ("ide-tape: Can not reach block %lu - Aborting request\n",rq->sector);
-				tape->locate_retries=0;
-				idetape_end_request (0,HWGROUP (drive));
-				return;
-			}
-						
-			if (tape->locate_to == rq->sector)
-				tape->locate_retries++;
-			else {
-				tape->locate_to=rq->sector;
-				tape->locate_retries=1;
-			}
-#if IDETAPE_DEBUG
-			printk ("ide-tape: We are not at the requested block\n");
-			printk ("ide-tape: Re-positioning tape\n");
-			printk ("ide-tape: Adding READ POSITION command to the head of the queue\n");
-#endif /* IDETAPE_DEBUG */
-			pc=idetape_next_pc_storage (drive);
-			new_rq=idetape_next_rq_storage (drive);
-			idetape_create_read_position_cmd (pc); 
-			pc->buffer=pc->temp_buffer;
-			pc->buffer_size=IDETAPE_TEMP_BUFFER_SIZE;
-			pc->current_position=pc->temp_buffer;
-			idetape_queue_pc_head (drive,pc,new_rq);
-#if IDETAPE_DEBUG			
-			printk ("ide-tape: Adding LOCATE %lu command to the head of the queue\n",rq->sector);
-#endif /* IDETAPE_DEBUG */
-			pc=idetape_next_pc_storage (drive);
-			new_rq=idetape_next_rq_storage (drive);
-			idetape_create_locate_cmd (pc,rq->sector,0);
-			idetape_queue_pc_head (drive,pc,new_rq);
-
-			if (!tape->block_address_valid) {		/* The tape doesn't know the position - help it */
-									/* by rewinding the tape */
-#if IDETAPE_DEBUG			
-				printk ("ide-tape: Adding LOCATE 0 command to the head of the queue\n");
-#endif /* IDETAPE_DEBUG */
-				pc=idetape_next_pc_storage (drive);
-				new_rq=idetape_next_rq_storage (drive);
-				idetape_create_locate_cmd (pc,0,0);
-				idetape_queue_pc_head (drive,pc,new_rq);
-			}
-			
-			return;
-		}
-		else
-			tape->locate_retries=0;
-	}
-	
 	switch (rq->cmd) {
-		case READ:
 		case IDETAPE_READ_REQUEST:
 #if IDETAPE_DEBUG
-			if (rq->cmd == READ)
-				printk ("ide-tape: Handling buffer cache READ request\n");
-			else
-				printk ("ide-tape: Handling our own (not buffer cache originated) READ request\n");
+			printk ("ide-tape: Handling our own (not buffer cache originated) READ request\n");
 #endif /* IDETAPE_DEBUG */			
 			status.all=IN_BYTE (IDETAPE_STATUS_REG);
 			if (!status.b.dsc) {				/* Tape buffer not ready to accept r/w command */
@@ -2409,27 +2619,21 @@
 				return;
 			}			
 
-			tape->last_written_valid=0;
-			
 			pc=idetape_next_pc_storage (drive);
 
 			idetape_create_read_cmd (pc,rq->current_nr_sectors);
 			
 			pc->buffer=rq->buffer;
-			pc->buffer_size=rq->current_nr_sectors*512;
+			pc->buffer_size=rq->current_nr_sectors*tape->tape_block_size;
 			pc->current_position=rq->buffer;
-			pc->request_transfer=rq->current_nr_sectors*512;
+			pc->request_transfer=rq->current_nr_sectors*tape->tape_block_size;
 
 			idetape_issue_packet_command (drive,pc,&idetape_pc_intr);
 			return;
 		
-		case WRITE:
 		case IDETAPE_WRITE_REQUEST:
 #if IDETAPE_DEBUG
-			if (rq->cmd == WRITE)
-				printk ("ide-tape: Handling buffer cache WRITE request\n");
-			else
-				printk ("ide-tape: Handling our own (not buffer cache originated) WRITE request\n");
+			printk ("ide-tape: Handling our own (not buffer cache originated) WRITE request\n");
 #endif /* IDETAPE_DEBUG */			
 
 			status.all=IN_BYTE (IDETAPE_STATUS_REG);
@@ -2442,17 +2646,14 @@
 				return;
 			}			
 
-			tape->last_written_valid=1;
-			tape->last_written_block=rq->sector;
-			
 			pc=idetape_next_pc_storage (drive);
 
 			idetape_create_write_cmd (pc,rq->current_nr_sectors);
 			
 			pc->buffer=rq->buffer;
-			pc->buffer_size=rq->current_nr_sectors*512;
+			pc->buffer_size=rq->current_nr_sectors*tape->tape_block_size;
 			pc->current_position=rq->buffer;
-			pc->request_transfer=rq->current_nr_sectors*512;
+			pc->request_transfer=rq->current_nr_sectors*tape->tape_block_size;
 
 			idetape_issue_packet_command (drive,pc,&idetape_pc_intr);
 			return;
@@ -2468,7 +2669,7 @@
 			if (!status.b.dsc) {				/* Tape buffers are still not ready */
 #if IDETAPE_DEBUG
 				printk ("ide-tape: DSC != 1 - Postponing packet command request\n");
-#endif IDETAPE_DEBUG
+#endif /* IDETAPE_DEBUG */
 				rq->cmd=IDETAPE_PACKET_COMMAND_REQUEST_TYPE2;	/* Note that we are waiting for DSC *before* we */
 										/* even issued the command */
 				tape->dsc_polling_frequency=IDETAPE_DSC_READ_WRITE_FREQUENCY;
@@ -2479,10 +2680,11 @@
 			pc=(idetape_packet_command_t *) rq->buffer;
 			idetape_issue_packet_command (drive,pc,&idetape_pc_intr);
 			return;
-
+#if IDETAPE_DEBUG
 		default:
-			printk ("ide-tape: Unknown command in request - Aborting request\n");
+			printk ("ide-tape: bug in IDETAPE_REQUEST_CMD macro\n");
 			idetape_end_request (0,HWGROUP (drive));
+#endif /* IDETAPE_DEBUG */
 	}	
 }
 
@@ -2546,6 +2748,19 @@
 	(void) ide_do_drive_cmd (drive, rq, ide_preempt);
 }
 
+void idetape_wait_for_request (struct request *rq)
+
+{
+	unsigned long flags;
+	struct semaphore sem = MUTEX_LOCKED;
+
+	save_flags (flags);cli ();
+	rq->sem=&sem;
+	restore_flags (flags);
+
+	down (&sem);
+}
+
 /*
  *	idetape_queue_rw_tail is typically called from the character device
  *	interface to generate a read/write request for the block device interface
@@ -2573,40 +2788,133 @@
 	rq.sector = tape->block_address;
 	rq.nr_sectors = blocks;
 	rq.current_nr_sectors = blocks;
+	tape->active_data_request=NULL;	/* Non-pipelined mode */
+#if IDETAPE_DEBUG
+		printk ("Using ide_tail\n");
+#endif /* IDETAPE_DEBUG */
 	return ide_do_drive_cmd (drive, &rq, ide_wait);
 }
 
-/*
- *	Copied from ide.c (declared static there)
+ /*
+ *	idetape_add_chrdev_write_request tries to add a character device
+ *	originated write request to our pipeline. In case we don't succeed,
+ *	we revert to non-piplined operation mode for this request.
+ *
+ *	1.	Try to allocate a new pipeline stage.
+ *	2.	If we can't, wait for more and more requests to be serviced
+ *		and try again each time.
+ *	3.	If we still can't allocate a stage, fallback to
+ *		non-pipelined operation mode for this request.
  */
 
-void idetape_fixstring (byte *s, const int bytecount, const int byteswap)
+int idetape_add_chrdev_write_request (ide_drive_t *drive,int cmd,int blocks,char *buffer)
+
 {
-	byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */
+	idetape_tape_t *tape = &(drive->tape);
+	idetape_pipeline_stage_t *new_stage;
+	struct request *rq;
+
+#if IDETAPE_DEBUG
+	printk ("Reached idetape_add_chrdev_write_request\n");
+	printk ("Trying to allocate stage - ");
+#endif /* IDETAPE_DEBUG */
+	
+	if (tape->error_in_pipeline_stage)		/* Return a deferred error */
+		return (-EIO);
+	
+	new_stage=idetape_kmalloc_stage (drive);
+
+	/*
+	 *	If we don't have a new stage, wait for more and more requests
+	 *	to finish, and try to allocate after each one.
+	 *
+	 *	Pay special attention to possible race conditions.
+	 */
 
-	if (byteswap) {
-		/* convert from big-endian to host byte order */
-		for (p = end ; p != s;) {
-			unsigned short *pp = (unsigned short *) (p -= 2);
-			*pp = ntohs(*pp);
+	while (new_stage == NULL) {
+
+		/*
+		 *	Wait for the time in which we can safely inspect
+		 *	tape->first_stage.
+		 */
+		 
+		while (tape->pipeline_locked);
+
+		if (tape->first_stage != NULL) {
+			idetape_wait_for_request (&(tape->first_stage->rq));
+			new_stage=idetape_kmalloc_stage (drive);
 		}
+		else
+			break;					/* Linux is short on memory */
 	}
-
-	/* 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);
+	
+	/*
+	 *	If we don't have a new_stage, fallback to non-pipelined
+	 *	operation mode for this request.
+	 */
+	 	 	
+	if (new_stage == NULL) {
+		if (tape->active_data_request != NULL)
+			idetape_wait_for_request (tape->active_data_request);
+		return (idetape_queue_rw_tail (drive,cmd,blocks,buffer));
 	}
 
-	/* wipe out trailing garbage */
-	while (p != end)
-		*p++ = '\0';
+	rq=&(new_stage->rq);
+
+	ide_init_drive_cmd (rq);
+	rq->buffer = NULL;			/* We will correct this when we will actually service the request */
+	rq->cmd = cmd;
+	rq->sector = tape->block_address;	/* Doesn't actually matter - We always assume sequential access */
+	rq->nr_sectors = blocks;
+	rq->current_nr_sectors = blocks;
+
+	idetape_copy_buffer_to_stage (new_stage,buffer);
+	idetape_add_stage_tail (drive,new_stage);
+
+	return (0);		
 }
 
+void idetape_empty_pipeline (ide_drive_t *drive)
+
+{
+	idetape_tape_t *tape = &(drive->tape);
+
+	tape->pipeline_was_full_once=0;
+
+	while (tape->pipeline_locked);
+	
+	if (tape->active_data_request == NULL)
+		idetape_insert_pipeline_into_queue (drive);		
+
+	if (tape->last_stage != NULL)
+		idetape_wait_for_request (&(tape->last_stage->rq));
+
+	else if (tape->active_data_request != NULL)
+		idetape_wait_for_request (tape->active_data_request);
+
+	tape->error_in_pipeline_stage=0;
+
+	/*
+	 *	On the next backup, perform the feedback loop again.
+	 *	(I don't want to keep sense information between backups,
+	 *	 as some systems are constantly on, and the system load
+	 *	 can be totally different on the next backup).
+	 */
+
+#if IDETAPE_PIPELINE
+	tape->max_number_of_stages=IDETAPE_MIN_PIPELINE_STAGES;
+#else
+	tape->max_number_of_stages=0;
+#endif /* IDETAPE_PIPELINE */
+
+#if IDETAPE_DEBUG
+	if (tape->first_stage != NULL || tape->last_stage != NULL || tape->current_number_of_stages != 0) {
+		printk ("ide-tape: ide-tape pipeline bug\n");		
+	}
+#endif /* IDETAPE_DEBUG */
+}
+
+
 /*
  *	idetape_zero_packet_command just zeros a packet command and
  *	sets the number of retries to 0, as we haven't retried it yet.
@@ -2722,28 +3030,48 @@
 /*
  *	Block device interface functions
  *
- *	The default action is not to allow direct access to the block device
- *	interface (-EBUSY will be returned on open).
+ *	The block device interface should not be used for data transfers.
+ *	However, we still allow opening it so that we can issue general
+ *	ide driver configuration ioctl's, such as the interrupt unmask feature.
  */
 
 int idetape_blkdev_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
 
 {
-#if IDETAPE_ALLOW_OPENING_BLOCK_DEVICE
+	idetape_tape_t *tape=&(drive->tape);
+	unsigned long flags;
+			
+	save_flags (flags);cli();
+
+#if IDETAPE_DEBUG
+	printk ("Reached idetape_blkdev_open\n");
+#endif /* IDETAPE_DEBUG */
+
+	if (tape->busy) {
+		restore_flags (flags);		/* Allowing access only through one */
+		return (-EBUSY);		/* one file descriptor */
+	}
+
+	tape->busy=1;
+	restore_flags (flags);
+
 	return (0);
-#else
-	printk ("ide-tape: The block device interface should not be used.\n");
-	printk ("ide-tape: Use the character device interfaces\n");
-	printk ("ide-tape: /dev/ht0 and /dev/nht0 instead.\n");
-	printk ("ide-tape: (Run linux/drivers/block/MAKEDEV.ide to create them)\n");
-	printk ("ide-tape: Refusing open request.\n");
-	return (-EBUSY);
-#endif /* IDETAPE_ALLOW_OPENING_BLOCK_DEVICE */
 }
 
 void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
 
 {
+	idetape_tape_t *tape=&(drive->tape);
+	unsigned long flags;
+			
+#if IDETAPE_DEBUG
+	printk ("Reached idetape_blkdev_release\n");
+#endif /* IDETAPE_DEBUG */
+
+	save_flags (flags);cli();
+	tape->busy=0;
+	restore_flags (flags);
+
 	return;
 }
 
@@ -2776,7 +3104,7 @@
 /*
  *	Our character device read / write functions.
  *
- *	The tape is optimized to maximize throughpot when it is transfering
+ *	The tape is optimized to maximize throughput when it is transfering
  *	an integral number of the "continous transfer limit", which is
  *	a parameter of the specific tape (26 KB on my particular tape). The
  *	resulting increase in performance should be dramatical. In the
@@ -2872,9 +3200,8 @@
 	if (count==0)
 		return (0);
 
-
-	blocks=count/512;
-	remainder=count%512;
+	blocks=count/tape->tape_block_size;
+	remainder=count%tape->tape_block_size;
 	if (remainder) {
 #if IDETAPE_DEBUG
 	printk ("ide-tape: Padding read to block boundary\n");
@@ -2888,7 +3215,7 @@
 	retval=idetape_queue_rw_tail (drive,IDETAPE_READ_REQUEST,blocks,tape->data_buffer);
 	if (retval) {
 		printk ("ide-tape: Error occured while reading\n");
-		actually_read=512*(tape->block_address-previous_block_address);
+		actually_read=tape->tape_block_size*(tape->block_address-previous_block_address);
 		if (actually_read > count)
 			actually_read=count;
 		if (actually_read != 0)
@@ -2907,7 +3234,7 @@
 {
 	ide_drive_t *drive;
 	idetape_tape_t *tape;
-	int blocks,remainder,retval,ctl_bytes;
+	int blocks,remainder,retval;
 	const char *buf_ptr;
 	unsigned long previous_block_address,actually_written;
 
@@ -2917,6 +3244,7 @@
 
 	drive=idetape_chrdev.drive;
 	tape=&(drive->tape);
+
 	tape->last_dt_was_write=1;
 
 	if (count==0)
@@ -2924,26 +3252,25 @@
 
 	actually_written=0;
 	buf_ptr=buf;
-	ctl_bytes=tape->capabilities.ctl*tape->tape_block_size;
-	blocks=count/ctl_bytes;
-	remainder=count%ctl_bytes;
+	blocks=count/tape->data_buffer_size;
+	remainder=count%tape->data_buffer_size;
 
 	while (blocks) {
-#if IDETAPE_DEBUG
-		printk ("Copying %d bytes from the user space memory\n",ctl_bytes);
-#endif /* IDETAPE_DEBUG */
-		memcpy_fromfs (tape->data_buffer,buf_ptr,ctl_bytes);
-		buf_ptr+=ctl_bytes;
-#if IDETAPE_DEBUG
-		printk ("Adding a WRITE request to the block device request queue\n");
-#endif /* IDETAPE_DEBUG */
+		memcpy_fromfs (tape->temp_data_buffer,buf_ptr,tape->data_buffer_size);
+		buf_ptr+=tape->data_buffer_size;
 		previous_block_address=tape->block_address;
-		retval=idetape_queue_rw_tail (drive,IDETAPE_WRITE_REQUEST,tape->capabilities.ctl,tape->data_buffer);
-		actually_written+=tape->tape_block_size*(tape->block_address-previous_block_address);
+		retval=idetape_add_chrdev_write_request (drive,IDETAPE_WRITE_REQUEST,tape->capabilities.ctl,tape->temp_data_buffer);
+		if (tape->max_number_of_stages)
+			actually_written+=tape->data_buffer_size;	/* Pipelined mode - Cheat :-) */
+		else
+			actually_written+=tape->tape_block_size*(tape->block_address-previous_block_address);
 
 		if (retval) {
 			printk ("ide-tape: Error occured while writing\n");
-			return (actually_written);
+			if (tape->max_number_of_stages)
+				return (0);
+			else
+				return (actually_written);
 		}
 		blocks--;
 	}
@@ -2969,20 +3296,20 @@
 	drive=idetape_chrdev.drive;
 	tape=&(drive->tape);
 
-	blocks=count/512;
-	remainder=count%512;
+	blocks=count/tape->tape_block_size;
+	remainder=count%tape->tape_block_size;
 	if (remainder)
 		blocks++;
 #if IDETAPE_DEBUG
 	printk ("Copying %d bytes from the user space memory\n",count);
 #endif /* IDETAPE_DEBUG */
 
-	memcpy_fromfs (tape->data_buffer,buf,count);
+	memcpy_fromfs (tape->temp_data_buffer,buf,count);
 	if (remainder) {
 #if IDETAPE_DEBUG
 	printk ("ide-tape: Padding written data to block boundary\n");
 #endif /* IDETAPE_DEBUG */
-		ptr=tape->data_buffer+(blocks-1)*512;
+		ptr=tape->temp_data_buffer+(blocks-1)*tape->tape_block_size;
 		memset (ptr,0,remainder);
 	}
 #if IDETAPE_DEBUG
@@ -2990,10 +3317,13 @@
 #endif /* IDETAPE_DEBUG */
 
 	previous_block_address=tape->block_address;
-	retval=idetape_queue_rw_tail (drive,IDETAPE_WRITE_REQUEST,blocks,tape->data_buffer);
+	retval=idetape_add_chrdev_write_request (drive,IDETAPE_WRITE_REQUEST,blocks,tape->temp_data_buffer);
 	if (retval) {
 		printk ("ide-tape: Error occured while writing\n");
-		actually_written=512*(tape->block_address-previous_block_address);
+		if (tape->max_number_of_stages)
+			actually_written=0;
+		else
+			actually_written=tape->tape_block_size*(tape->block_address-previous_block_address);
 		if (actually_written > count)
 			actually_written=count;
 		return (actually_written);
@@ -3164,9 +3494,8 @@
 	idetape_tape_t *tape;
 	unsigned long flags;
 	unsigned int minor;
-		
-	save_flags (flags);
-	cli();
+			
+	save_flags (flags);cli();
 
 #if IDETAPE_DEBUG
 	printk ("Reached idetape_chrdev_open\n");
@@ -3199,7 +3528,7 @@
 	}
 
 	tape->last_dt_was_write=0;
-	
+
 	return (0);
 }
 
@@ -3225,6 +3554,8 @@
 	tape=&(drive->tape);
 	minor=MINOR (inode->i_rdev);
 
+	idetape_empty_pipeline (drive);
+
 	if (tape->last_dt_was_write) {
 		idetape_create_write_filemark_cmd (&pc,1);	/* Write a filemark */
 		if (idetape_queue_pc_tail (drive,&pc)) {
@@ -3247,11 +3578,10 @@
 		}
 	}
 
-	save_flags (flags);
-	cli();
+	save_flags (flags);cli();
 	tape->busy=0;
 	restore_flags (flags);
-		
+
 	return;
 }
 
@@ -3310,4 +3640,315 @@
 	pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE;
 	pc.current_position=pc.temp_buffer;
 	return (idetape_queue_pc_tail (drive,&pc));
+}
+
+/*
+ *	Pipeline related functions
+ */
+
+/*
+ *	idetape_kmalloc_stage uses kmalloc to allocate a pipeline stage,
+ *	along with all the necessary small buffers which together make
+ *	a buffer of size tape->data_buffer_size or a bit more, in case
+ *	it is not a multiply of IDETAPE_ALLOCATION_BLOCK (it isn't ...).
+ *
+ *	Returns a pointer to the new allocated stage, or NULL if we
+ *	can't (or don't want to, in case we already have too many stages)
+ *	allocate a stage.
+ *
+ *	Pipeline stages are optional and are used to increase performance.
+ *	If we can't allocate them, we'll manage without them.
+ */
+ 
+idetape_pipeline_stage_t *idetape_kmalloc_stage (ide_drive_t *drive)
+
+{
+	idetape_tape_t *tape=&(drive->tape);
+	idetape_pipeline_stage_t *new_stage;
+	idetape_buffer_head_t *prev_bh,*bh;
+	int buffers_num,i;
+	
+#if IDETAPE_DEBUG
+	printk ("Reached idetape_kmalloc_stage\n");
+#endif /* IDETAPE_DEBUG */
+
+	if (tape->current_number_of_stages==tape->max_number_of_stages) {
+		tape->pipeline_was_full_once=1;
+		return (NULL);
+	}
+		
+	new_stage=(idetape_pipeline_stage_t *) kmalloc (sizeof (idetape_pipeline_stage_t),GFP_KERNEL);
+	if (new_stage==NULL)
+		return (NULL);
+		
+	new_stage->next=new_stage->prev=NULL;
+
+	buffers_num=tape->data_buffer_size / IDETAPE_ALLOCATION_BLOCK;
+	if (tape->data_buffer_size % IDETAPE_ALLOCATION_BLOCK)
+		buffers_num++;
+
+	prev_bh=new_stage->bh=(idetape_buffer_head_t *) kmalloc (sizeof (idetape_buffer_head_t),GFP_KERNEL);
+	if (new_stage->bh==NULL) {
+		idetape_kfree_stage (new_stage);
+		return (NULL);
+	}
+	new_stage->bh->next=NULL;
+
+	new_stage->bh->data=kmalloc (IDETAPE_ALLOCATION_BLOCK,GFP_KERNEL);
+	if (new_stage->bh->data==NULL) {
+		idetape_kfree_stage (new_stage);
+		return (NULL);
+	}
+	
+	for (i=1;i<buffers_num;i++) {
+		bh=(idetape_buffer_head_t *) kmalloc (sizeof (idetape_buffer_head_t),GFP_KERNEL);
+		if (bh==NULL) {
+			idetape_kfree_stage (new_stage);
+			return (NULL);
+		}
+		bh->next=NULL;
+		prev_bh->next=bh;
+		bh->data=kmalloc (IDETAPE_ALLOCATION_BLOCK,GFP_KERNEL);
+		if (bh->data == NULL) {
+			idetape_kfree_stage (new_stage);
+			return (NULL);
+		}
+		prev_bh=bh;
+	}
+	return (new_stage);
+}
+
+/*
+ *	idetape_kfree_stage calls kfree to completly free a stage, along with
+ *	its related buffers.
+ */
+ 
+void idetape_kfree_stage (idetape_pipeline_stage_t *stage)
+
+{
+	idetape_buffer_head_t *prev_bh,*bh;
+	
+	if (stage == NULL)
+		return;
+
+#if IDETAPE_DEBUG
+	printk ("Reached idetape_kfree_stage\n");
+#endif /* IDETAPE_DEBUG */
+	
+	bh=stage->bh;
+	
+	while (bh != NULL) {
+		prev_bh=bh;
+		if (bh->data != NULL)
+			kfree (bh->data);
+		bh=bh->next;
+		kfree (prev_bh);
+	}
+	
+	kfree (stage);
+	return;
+}
+
+/*
+ *	idetape_copy_buffer_from_stage and idetape_copy_buffer_to_stage
+ *	copy data from/to the small buffers into/from a continous buffer.
+ */
+  
+void idetape_copy_buffer_from_stage (idetape_pipeline_stage_t *stage,char *buffer)
+
+{
+	idetape_buffer_head_t *bh;
+	char *ptr;
+
+#if IDETAPE_DEBUG
+	printk ("Reached idetape_copy_buffer_from_stage\n");
+#endif /* IDETAPE_DEBUG */
+	
+	ptr=buffer;
+	bh=stage->bh;
+	
+	while (bh != NULL) {
+		memcpy (ptr,bh->data,IDETAPE_ALLOCATION_BLOCK);
+		bh=bh->next;
+		ptr=ptr+IDETAPE_ALLOCATION_BLOCK;
+	}
+	return;
+}
+
+/*
+ *	Here we copy a continuous data buffer to the various small buffers
+ *	in the pipeline stage.
+ */
+ 
+void idetape_copy_buffer_to_stage (idetape_pipeline_stage_t *stage,char *buffer)
+
+{
+	idetape_buffer_head_t *bh;
+	char *ptr;
+
+#if IDETAPE_DEBUG
+	printk ("Reached idetape_copy_buffer_to_stage\n");
+#endif /* IDETAPE_DEBUG */
+
+	ptr=buffer;
+	bh=stage->bh;
+	
+	while (bh != NULL) {
+		memcpy (bh->data,ptr,IDETAPE_ALLOCATION_BLOCK);
+		bh=bh->next;
+		ptr=ptr+IDETAPE_ALLOCATION_BLOCK;
+	}
+	return;
+}
+
+/*
+ *	idetape_increase_max_pipeline_stages is a part of the feedback
+ *	loop which tries to find the optimum number of stages. In the
+ *	feedback loop, we are starting from a minimum maximum number of
+ *	stages, and if we sense that the pipeline is empty, we try to
+ *	increase it, until we reach the user compile time memory limit.
+ */
+
+void idetape_increase_max_pipeline_stages (ide_drive_t *drive)
+
+{
+	idetape_tape_t *tape=&(drive->tape);
+	
+#if IDETAPE_DEBUG
+	printk ("Reached idetape_increase_max_pipeline_stages\n");
+#endif /* IDETAPE_DEBUG */
+
+	if (!tape->pipeline_was_full_once)
+		return;
+
+	tape->max_number_of_stages+=IDETAPE_INCREASE_STAGES_RATE*
+					(IDETAPE_MAX_PIPELINE_STAGES-IDETAPE_MIN_PIPELINE_STAGES);
+
+	if (tape->max_number_of_stages >= IDETAPE_MAX_PIPELINE_STAGES)
+		tape->max_number_of_stages = IDETAPE_MAX_PIPELINE_STAGES;
+
+#if IDETAPE_DEBUG
+	printk ("Maximum number of stages: %d\n",tape->max_number_of_stages);
+#endif /* IDETAPE_DEBUG */
+
+	return;
+}
+
+/*
+ *	idetape_add_stage_tail adds a new stage at the end of the pipeline.
+ */
+ 
+void idetape_add_stage_tail (ide_drive_t *drive,idetape_pipeline_stage_t *stage)
+
+{
+	idetape_tape_t *tape=&(drive->tape);
+	unsigned long flags;
+	
+#if IDETAPE_DEBUG
+		printk ("Reached idetape_add_stage_tail\n");
+#endif /* IDETAPE_DEBUG */
+
+	stage->next=NULL;
+	
+#if IDETAPE_DEBUG
+		printk ("Adding to the tail of the pipeline\n");
+#endif /* IDETAPE_DEBUG */
+
+	/*
+	 *	Avoid a race condition - pipeline_locked is set whenever
+	 *	we modify active_data_request from the lower level of
+	 *	the driver. We wait until active_data_request is valid.
+	 */
+	 
+	while (tape->pipeline_locked);
+
+	save_flags (flags);cli ();
+	stage->prev=tape->last_stage;
+	if (tape->first_stage != NULL)
+		tape->last_stage->next=stage;
+	else
+		tape->first_stage=stage;
+	tape->last_stage=stage;
+	tape->current_number_of_stages++;
+
+	/*
+	 *	Check if we are currently servicing requests in the bottom
+	 *	part of the driver.
+	 *
+	 *	If not, wait for the pipeline to be full enough (75%) before
+	 *	starting to service requests, so that we will be able to
+	 *	keep up with the higher speeds of the tape.
+	 */
+
+	if (tape->active_data_request == NULL &&
+		tape->current_number_of_stages >= 0.75*tape->max_number_of_stages) {
+		
+		restore_flags (flags);
+		idetape_insert_pipeline_into_queue (drive);		
+	}
+	else
+		restore_flags (flags);
+}
+
+/*
+ *	idetape_insert_pipeline_into_queue is used to start servicing the
+ *	pipeline stages.
+ */
+ 
+void idetape_insert_pipeline_into_queue (ide_drive_t *drive)
+
+{
+	idetape_tape_t *tape=&(drive->tape);
+
+	if (tape->first_stage == NULL)
+		return;
+
+	if (tape->active_data_request == NULL) {
+		idetape_active_next_stage (drive);
+#if IDETAPE_DEBUG
+		printk ("Using ide_end\n");
+#endif /* IDETAPE_DEBUG */
+		(void) (ide_do_drive_cmd (drive,tape->active_data_request,ide_end));
+		return;
+	}
+}
+
+/*
+ *	idetape_active_next_stage will "move the pipeline" one stage -
+ *	Inserting the first stage into the "active place", and using kfree
+ *	to free the stage.
+ */
+ 
+void idetape_active_next_stage (ide_drive_t *drive)
+
+{
+	idetape_tape_t *tape=&(drive->tape);
+	idetape_pipeline_stage_t *stage;
+	struct request *rq;
+	unsigned long flags;
+
+#if IDETAPE_DEBUG
+	printk ("Reached idetape_active_next_stage\n");
+	if (tape->first_stage == NULL) {
+		printk ("ide-tape: ide-tape.c bug - tape->first_stage is NULL\n");
+		return;
+	}
+#endif /* IDETAPE_DEBUG */
+	
+	stage=tape->first_stage;
+
+	idetape_copy_buffer_from_stage (stage,tape->data_buffer);
+	rq=idetape_next_rq_storage (drive);
+	*rq=stage->rq;
+	rq->buffer=tape->data_buffer;
+
+	save_flags (flags);cli ();
+	tape->first_stage=stage->next;
+	if (tape->first_stage == NULL)
+		tape->last_stage=NULL;
+	tape->current_number_of_stages--;
+	tape->active_data_request=rq;
+	restore_flags (flags);
+	
+	idetape_kfree_stage (stage);
 }
diff -u --recursive --new-file v1.3.47/linux/drivers/block/ide-tape.h linux/drivers/block/ide-tape.h
--- v1.3.47/linux/drivers/block/ide-tape.h	Mon Dec 11 15:42:01 1995
+++ linux/drivers/block/ide-tape.h	Sun Dec 17 11:17:19 1995
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/block/ide-tape.h	Version 1.0 - ALPHA	Dec  3, 1995
+ * linux/drivers/block/ide-tape.h	Version 1.1 - ALPHA	Dec  14, 1995
  *
  * Copyright (C) 1995 Gadi Oxman <tgud@tochnapc2.technion.ac.il>
  */
@@ -19,6 +19,63 @@
 /**************************** Tunable parameters *****************************/
 
 /*
+ *	This is probably the most important configuration option.
+ *
+ *	Pipelined operation mode has the potential to maximize the
+ *	performance of the driver and thus to saturate the throughput
+ *	to the maximum value supported by the tape. Currently, pipelined
+ *	mode is supported only on writes.
+ *
+ *	In pipelined mode we are servicing requests without blocking the
+ *	user backup program. For example, on a write request, we will add it
+ *	to the pipeline and return without waiting for it to complete. The
+ *	user program will then have enough time to prepare the next blocks
+ *	while the tape is still busy working on the previous requests.
+ *
+ *	Pipelined (write) operation mode is enabled by default, but since
+ *	it has a few downfalls as well (Use of additional memory and deferred
+ *      error code to the application), you may wish to disable it.
+ *	Further explanation of pipelined mode is available in ide-tape.c .
+ */
+
+#define	IDETAPE_PIPELINE	1
+
+/*
+ *	Pipelined mode parameters.
+ *
+ *	We try to use the minimum number of stages which is enough to
+ *	keep the tape constantly streaming. To accomplish that, we implement
+ *	a feedback loop around the maximum number of stages:
+ *
+ *	We start from MIN maximum stages (we will not even use MIN stages
+ *      if we don't need them), increment it by RATE*(MAX-MIN)
+ *	whenever we sense that the pipeline is empty, until we reach
+ *	the optimum value or until we reach MAX.
+ */
+ 
+#define	IDETAPE_MIN_PIPELINE_STAGES		100
+#define	IDETAPE_MAX_PIPELINE_STAGES		200
+#define	IDETAPE_INCREASE_STAGES_RATE		0.2
+
+/*
+ *	It seems that dynamically allocating buffers of about 32KB
+ *	each is doomed to fail, unless we are in or very near the
+ *	initialization stage. Take care when changing this value, as it
+ *	is now optimized with the design of kmalloc, so that we will not
+ *	allocate parts of a page. Setting the size to 512 bytes, for example,
+ *	would cause kmalloc to allocate for us 1024 bytes, and to
+ *	unnecessarily waste double amount of memory.
+ */
+
+#if PAGE_SIZE == 4096
+	#define	IDETAPE_ALLOCATION_BLOCK		500
+#elif PAGE_SIZE == 8192
+	#define	IDETAPE_ALLOCATION_BLOCK		496
+#else /* ??? Not defined by linux/mm/kmalloc.c */
+	#define IDETAPE_ALLOCATION_BLOCK		512
+#endif
+
+/*
  *	Setting IDETAPE_DEBUG to 1 will:
  *
  *		1.	Generally log all driver actions.
@@ -45,15 +102,6 @@
 #define	IDETAPE_MAX_PC_RETRIES	2
 
 /*
- *	In case the tape is not at the requested block, we re-position the
- *	tape. Repeat the procedure for IDETAPE_LOCATE_RETRIES times before
- *	we give up and abort the request. Note that this should not usually
- *	happen when using only the character device interface.
- */
-
-#define	IDETAPE_LOCATE_RETRIES	1
-
-/*
  *	With each packet command, we allocate a buffer of
  *	IDETAPE_TEMP_BUFFER_SIZE bytes. This is used for several packet
  *	commands (Not for READ/WRITE commands).
@@ -80,70 +128,56 @@
  *	the handling of a specific request.
  *
  *	Follows a worse case calculation of the required storage, with a
- *	large safety margin. Hopefully. :-)
+ *	large safety margin.
  */
 
-#define	IDETAPE_PC_STACK	10+\
-				IDETAPE_MAX_PC_RETRIES+\
-				3*IDETAPE_LOCATE_RETRIES*IDETAPE_MAX_PC_RETRIES
-/*
- *	Media access packet command (like the LOCATE command) have immediate
- *	status with a delayed (and usually long) execution. The tape doesn't
- *	issue an interrupt when the command is actually complete (so that the
- *	bus is freed to use the other IDE device on the same interface), so we
- *	must for poll for this event.
- *
- *	We set a timer with polling frequency of 1/IDETAPE_DSC_MEDIA_ACCESS_FREQUENCY
- *	in this case. We also poll for DSC *before* read/write commands. At
- *	this time the DSC role is changed and instead of signalling command
- *	completion, it will signal buffer availability. Since read/write
- *	commands are fast in comparision to media access commands, the polling
- *	frequency here should be much higher.
- *
- *	We will insist of reading DSC=1 for IDETAPE_DSC_COUNT times in a row,
- *	to accommodate for random fluctuations in the sampling of DSC.
- *	We will also set IDETAPE_DSC_POLLING_FREQUENCY to a rather low
- *	frequency which besides freeing the CPU and the bus will let
- *	random fluctuations a time to settle down.
+#define	IDETAPE_PC_STACK	20+IDETAPE_MAX_PC_RETRIES
+
+/*
+ *	DSC polling parameters.
  *
+ *	Polling for DSC (a single bit in the status register) is a very
+ *	important function in ide-tape. There are two cases in which we
+ *	poll for DSC:
+ *
+ *	1.	Before a read/write packet command, to ensure that we
+ *		can transfer data from/to the tape's data buffers, without
+ *		causing an actual media access. In case the tape is not
+ *		ready yet, we take out our request from the device
+ *		request queue, so that ide.c will service requests from
+ *		the other device on the same interface meanwhile.
+ *
+ *		The polling frequency is 1/IDETAPE_DSC_READ_WRITE_FREQUENCY,
+ *		and it should be relatively fast. The default is a period
+ *		of 50 msec.
+ *
+ *	2.	After the successful initialization of a "media access
+ *		packet command", which is a command which can take a long
+ *		time to complete (it can be several seconds or even an hour).
+ *
+ *		Again, we postpone our request in the middle to free the bus
+ *		for the other device. The polling frequency here should be
+ *		lower than the read/write frequency since those media access
+ *		commands are slow. We start from a "fast" frequency -
+ *		IDETAPE_DSC_FAST_MEDIA_ACCESS_FREQUENCY (one second), and
+ *		if we don't receive DSC after IDETAPE_FAST_SLOW_THRESHOLD
+ *		(5 minutes), we switch it to a lower frequency -
+ *		IDETAPE_DSC_SLOW_MEDIA_ACCESS_FREQUENCY (1 minute).
+ *		
  *	We also set a timeout for the timer, in case something goes wrong.
  *	The timeout should be longer then the maximum execution time of a
  *	tape operation. I still have to measure exactly how much time does
  *	it take to space over a far filemark, etc. It seemed that 15 minutes
  *	was way too low, so I am meanwhile setting it to a rather large
- *	timeout - 2 Hours.
+ *	timeout - 2 Hours ...
  *
- *	Once we pass a threshold, the polling frequency will change to
- *	a slow frequency: On relatively fast operations, there is a point
- *	in polling fast, but if we sense that the operation is taking too
- *	much time, we will poll at a lower frequency.
  */
 
+#define	IDETAPE_DSC_READ_WRITE_FREQUENCY	5*HZ/100	/* 50 msec */
 #define	IDETAPE_DSC_FAST_MEDIA_ACCESS_FREQUENCY	1*HZ		/* 1 second */
 #define	IDETAPE_FAST_SLOW_THRESHOLD		5*60*HZ		/* 5 minutes */
 #define IDETAPE_DSC_SLOW_MEDIA_ACCESS_FREQUENCY	60*HZ		/* 1 minute */
-#define	IDETAPE_DSC_READ_WRITE_FREQUENCY	HZ/20		/* 50 msec */
 #define	IDETAPE_DSC_TIMEOUT			2*60*60*HZ	/* 2 hours */
-#define IDETAPE_DSC_COUNT			1		/* Assume no DSC fluctuations */
-
-/*
- *	As explained in many places through the code, we provide both a block
- *	device and a character device interface to the tape. The block device
- *	interface is needed for compatibility with ide.c. The character device
- *	interface is the higher level of the driver, and passes requests
- *	to the lower part of the driver which interfaces with ide.c.
- *	Using the block device interface, we can bypass this high level
- *	of the driver, talking directly with the lower level part.
- *
- *	It is intended that the character device interface will be used by
- *	the user. To prevent mistakes in this regard, opening of the block
- *	device interface will be refused if ALLOW_OPENING_BLOCK_DEVICE is 0.
- *
- *	Do not change the following parameter unless you are developing
- *	the driver itself.
- */
- 
-#define IDETAPE_ALLOW_OPENING_BLOCK_DEVICE	0
 
 /*************************** End of tunable parameters ***********************/
 
@@ -226,6 +260,30 @@
 } idetape_capabilities_page_t;
 
 /*
+ *	A pipeline stage contains several small buffers of type
+ *	idetape_buffer_head_t. This is necessary since dynamical allocation
+ *	of large (32 KB or so) continuous memory blocks will usually fail.
+ */
+ 
+typedef struct idetape_buffer_head_s {
+	char *data;					/* Pointer to data (512 bytes by default) */
+	struct idetape_buffer_head_s *next;
+} idetape_buffer_head_t;
+
+/*
+ *	A pipeline stage.
+ *
+ *	In a pipeline stage we have a request, pointer to a list of small
+ *	buffers, and pointers to the near stages.
+ */
+
+typedef struct idetape_pipeline_stage_s {
+	struct request rq;				/* The correspoding request */
+	idetape_buffer_head_t *bh;			/* The data buffers */
+	struct idetape_pipeline_stage_s *next,*prev;	/* Pointers to the next and previous stages */
+} idetape_pipeline_stage_t;
+
+/*
  *	Most of our global data which we need to save even as we leave the
  *	driver due to an interrupt or a timer event is stored in a variable
  *	of type tape_info, defined below.
@@ -268,9 +326,9 @@
 	 *	another ide block device which receives requests and completes
 	 *	them.
 	 *
-	 *	However, our requests usually don't originate in the buffer
-	 *	cache but rather in ide-tape.c itself. Here we provide safe
-	 *	storage for such requests.
+	 *	However, our requests don't originate in the buffer cache but
+	 *	rather in ide-tape.c itself. Here we provide safe storage for
+	 *	such requests.
 	 */
 
 	struct request rq_stack [IDETAPE_PC_STACK];
@@ -279,31 +337,37 @@
 	/*
 	 *	While polling for DSC we use postponed_rq to postpone the
 	 *	current request so that ide.c will be able to service
-	 *	pending requests on the other device.
+	 *	pending requests on the other device. Note that at most
+	 *	we will have only one DSC (usually data transfer) request
+	 *	in the device request queue. Additional request can be
+	 *	queued in our internal pipeline, but they will be visible
+	 *	to ide.c only one at a time.
 	 */
 
 	struct request *postponed_rq;
-	byte dsc_count;		
-	unsigned long dsc_polling_start;
+	
+	/*
+	 *	DSC polling variables.
+	 */
+	 
+	byte dsc_count;				/* We received DSC dsc_count times in a row */
+	unsigned long dsc_polling_start;	/* The time in which we started polling for DSC */
 	struct timer_list dsc_timer;		/* Timer used to poll for dsc */
-	unsigned long dsc_polling_frequency;
+	unsigned long dsc_polling_frequency;	/* The current polling frequency */
 	unsigned long dsc_timeout;		/* Maximum waiting time */
-	byte dsc_received;
+	byte dsc_received;			/* Set when we receive DSC */
 
+	byte request_status;
+	byte request_dsc_callback;
+	byte last_status;			/* Contents of the tape status register */
+						/* before the current request (saved for us */
+						/* by ide.c) */
 	/* Position information */
 	
 	byte partition_num;			/* Currently not used */
 	unsigned long block_address;		/* Current block */
 	byte block_address_valid;		/* 0 When the tape position is unknown */
 						/* (To the tape or to us) */
-	unsigned long locate_to;		/* We want to reach this block, as a part */
-						/* of handling the current request */
-	byte locate_retries;			/* Each time, increase locate_retries */
-
-	unsigned long last_written_block;	/* Once writing started, we don't allow read */
-	byte last_written_valid;		/* access beyond the last written block */
-						/* ??? Should I remove this ? */
-
 	/* Last error information */
 	
 	byte sense_key,asc,ascq;
@@ -311,17 +375,60 @@
 	/* Character device operation */
 
 	unsigned char last_dt_was_write;	/* Last character device data transfer was a write */
-	byte busy;				/* Device already opened */	
+	byte busy;				/* Device already opened */
 
 	/* Device information */
 	
-	unsigned short tape_block_size;
-	idetape_capabilities_page_t capabilities;	/* Capabilities and Mechanical Page */
+	unsigned short tape_block_size;			/* Usually 512 or 1024 bytes */
+	idetape_capabilities_page_t capabilities;	/* Copy of the tape's Capabilities and Mechanical Page */
 
-	/* Data buffer */
+	/*
+	 *	Active data transfer request parameters.
+	 *
+	 *	At most, there is only one ide-tape originated data transfer
+	 *	request in the device request queue. This allows ide.c to
+	 *	easily service requests from the other device when we
+	 *	postpone our active request. In the pipelined operation
+	 *	mode, we use our internal pipeline structure to hold
+	 *	more data requests.
+	 *
+	 *	The data buffer size is chosen based on the tape's
+	 *	recommendation.
+	 */
 	
-	char *data_buffer;
+	struct request *active_data_request;	/* Pointer to the request which is waiting in the device request queue */
+	char *data_buffer;			/* The correspoding data buffer (for read/write requests) */
+	int data_buffer_size;			/* Data buffer size (chosen based on the tape's recommendation */
+	char *temp_data_buffer;			/* Temporary buffer for user <-> kernel space data transfer */
 
+	/*
+	 *	Pipeline parameters.
+	 *
+	 *	To accomplish non-pipelined mode, we simply set the following
+	 *	variables to zero (or NULL, where appropriate).
+	 */
+		
+	int current_number_of_stages;		/* Number of currently used stages */
+	int max_number_of_stages;		/* We will not allocate more than this number of stages */
+	idetape_pipeline_stage_t *first_stage;	/* Will be serviced after the currently active request */
+	idetape_pipeline_stage_t *last_stage;	/* New write requests will be added to the pipeline here */
+	int pipeline_was_full_once;		/* Set at the first time we fill the pipeline since the tape was opened */
+	int error_in_pipeline_stage;		/* Set when an error was detected in one of the pipeline stages */	
+	int pipeline_locked;			/* Against race conditions ... */
+	
 } idetape_tape_t;
+
+#define POLL_HWIF_TAPE_DRIVE							\
+	if (hwif->tape_drive != NULL) {						\
+		if (hwif->tape_drive->tape.request_status) {			\
+			OUT_BYTE(hwif->tape_drive->select.all,IDE_SELECT_REG);	\
+			hwif->tape_drive->tape.last_status=GET_STAT();		\
+			hwif->tape_drive->tape.request_status=0;		\
+		}								\
+		if (hwif->tape_drive->tape.request_dsc_callback) {		\
+			hwif->tape_drive->tape.request_dsc_callback=0;		\
+			idetape_put_back_postponed_request(hwif->tape_drive);	\
+		}								\
+	}
 
 #endif /* IDETAPE_H */
diff -u --recursive --new-file v1.3.47/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v1.3.47/linux/drivers/block/ide.c	Mon Dec 11 15:42:01 1995
+++ linux/drivers/block/ide.c	Sun Dec 17 11:17:19 1995
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c	Version 5.22  Dec 10, 1995
+ *  linux/drivers/block/ide.c	Version 5.23  Dec 15, 1995
  *
  *  Copyright (C) 1994, 1995  Linus Torvalds & authors (see below)
  */
@@ -178,6 +178,7 @@
  *			generalized ide_do_drive_cmd() for tape/cdrom driver use
  *  Version 5.21	fix nasty cdrom/tape bug (ide_preempt was messed up)
  *  Version 5.22	fix ide_xlate_1024() to work with/without drive->id
+ *  Version 5.23	miscellaneous touch-ups
  *
  *  Driver compile-time options are in ide.h
  *
@@ -187,6 +188,7 @@
  *	- add ioctls to get/set interface timings on various interfaces
  *	- add Promise Caching controller support from peterd@pnd-pc.demon.co.uk
  *	- modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
+ *	- add new HT6560B code from malafoss@snakemail.hut.fi
  */
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
@@ -315,7 +317,9 @@
 		hwif->name[1]	= 'd';
 		hwif->name[2]	= 'e';
 		hwif->name[3]	= '0' + h;
-
+#ifdef CONFIG_BLK_DEV_IDETAPE
+		hwif->tape_drive = NULL;
+#endif /* CONFIG_BLK_DEV_IDETAPE */
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
 			ide_drive_t *drive = &hwif->drives[unit];
 
@@ -415,6 +419,7 @@
 	static byte current_select = 0;
 
 	if (hwif->select != current_select) {
+		byte t;
 		unsigned long flags;
 		save_flags (flags);
 		cli();
@@ -422,8 +427,16 @@
 		(void) inb(0x3e6);
 		(void) inb(0x3e6);
 		(void) inb(0x3e6);
-		(void) inb(0x3e6);
-		outb(current_select,0x3e6);
+		/*
+		 * Avoid clobbering existing bits at 0x3e6:
+		 *	bit5 (0x20) - disables fast interface speed
+		 *	bit0 (0x01) - enables secondary interface
+		 *	we don't touch any other bits
+		 */
+		t = inb(0x3e6);
+		t &= (~0x21);
+		t |= (current_select & 0x21);
+		outb(t,0x3e6);
 		restore_flags (flags);
 	}
 }
@@ -877,7 +890,7 @@
 	} else {
 		if (drive->media == ide_disk && (stat & ERR_STAT)) {
 			/* err has different meaning on cdrom and tape */
-			if (err & BBD_ERR)		/* retries won't help this! */
+			if (err & (BBD_ERR | ECC_ERR))	/* retries won't help these */
 				rq->errors = ERROR_MAX;
 			else if (err & TRK0_ERR)	/* help it find track zero */
 				rq->errors |= ERROR_RECAL;
@@ -1271,8 +1284,10 @@
 	if (rq->cmd == IDE_DRIVE_CMD) {
 		byte *args = rq->buffer;
 		if (args) {
+#ifdef DEBUG
 			printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x\n",
 			 drive->name, args[0], args[1], args[2]);
+#endif
 			OUT_BYTE(args[2],io_base+IDE_FEATURE_OFFSET);
 			ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
 			return;
@@ -1341,11 +1356,17 @@
 	if (hwif->select)
 		ide_hwif_select (hwif);
 #endif
+
+#ifdef CONFIG_BLK_DEV_IDETAPE
+	POLL_HWIF_TAPE_DRIVE;	/* macro from ide-tape.h */
+#endif /* CONFIG_BLK_DEV_IDETAPE */
+
 	OUT_BYTE(drive->select.all,IDE_SELECT_REG);
 	if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
 		printk("%s: drive not ready for command\n", drive->name);
 		return;
 	}
+	
 	if (!drive->special.all) {
 #ifdef CONFIG_BLK_DEV_IDEATAPI
 		switch (drive->media) {
@@ -1638,6 +1659,12 @@
  * returns without waiting for the new rq to be completed.  As above,
  * This is VERY DANGEROUS, and is intended for careful use by the
  * ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_end, then the rq is queued at the end of the
+ * request queue, and the function returns immediately without waiting
+ * for the new rq to be completed. This is again intended for careful
+ * use by the ATAPI tape/cdrom driver code. (Currently used by ide-tape.c,
+ * when operating in the pipelined operation mode).
  */
 int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action)
 {
@@ -1664,7 +1691,7 @@
 		if (action != ide_preempt)
 			bdev->request_fn();
 	} else {
-		if (action == ide_wait) {
+		if (action == ide_wait || action == ide_end) {
 			while (cur_rq->next != NULL)	/* find end of list */
 				cur_rq = cur_rq->next;
 		}
@@ -1704,7 +1731,12 @@
 		check_disk_change(inode->i_rdev);
 		ide_init_drive_cmd (&rq);
 		rq.buffer = door_lock;
-		return ide_do_drive_cmd(drive, &rq, ide_wait);
+		/*
+		 * Ignore the return code from door_lock,
+		 * since the open() has already succeeded,
+		 * and the door_lock is irrelevant at this point.
+		 */
+		(void) ide_do_drive_cmd(drive, &rq, ide_wait);
 	}
 	return 0;
 }
@@ -1997,7 +2029,7 @@
 	return 0;
 }
 
-static void fixstring (byte *s, const int bytecount, const int byteswap)
+void ide_fixstring (byte *s, const int bytecount, const int byteswap)
 {
 	byte *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */
 
@@ -2055,9 +2087,9 @@
 		 || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
 			bswap = 0;	/* Vertos drives may still be weird */
 	}
-	fixstring (id->model,     sizeof(id->model),     bswap);
-	fixstring (id->fw_rev,    sizeof(id->fw_rev),    bswap);
-	fixstring (id->serial_no, sizeof(id->serial_no), bswap);
+	ide_fixstring (id->model,     sizeof(id->model),     bswap);
+	ide_fixstring (id->fw_rev,    sizeof(id->fw_rev),    bswap);
+	ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap);
 
 	/*
 	 * Check for an ATAPI device
@@ -2678,15 +2710,19 @@
 				/*
 				 * Using 0x1c and 0x1d apparently selects a
 				 * faster interface speed than 0x3c and 0x3d.
+				 * (bit5 (0x20) selects fast speed when set)
+				 * (bit0 (0x01) selects second interface)
 				 *
-				 * Need to add an ioctl to select between them.
+				 * Need to set these per-drive, rather than
+				 * per-hwif, and also add an ioctl to select
+				 * between them.
 				 */
 				if (check_region(0x3e6,1)) {
 					printk(" -- HT6560 PORT 0x3e6 ALREADY IN USE");
 					goto done;
 				}
 				request_region(0x3e6, 1, hwif->name);
-				ide_hwifs[0].select = 0x3c;
+				ide_hwifs[0].select = 0x1c;
 				ide_hwifs[1].select = 0x3d;
 				goto do_serialize;
 #endif /* SUPPORT_HT6560B */
@@ -2741,13 +2777,13 @@
 		return 0;
 
 	if (drive->id) {
-		drive->bios_cyl  = drive->id->cyls;
-		drive->bios_head = drive->id->heads;
-		drive->bios_sect = drive->id->sectors;
-	}
-	drive->cyl  = drive->bios_cyl;
-	drive->head = drive->bios_head;
-	drive->sect = drive->bios_sect;
+		drive->cyl  = drive->id->cyls;
+		drive->head = drive->id->heads;
+		drive->sect = drive->id->sectors;
+	}
+	drive->bios_cyl  = drive->cyl;
+	drive->bios_head = drive->head;
+	drive->bios_sect = drive->sect;
 	drive->special.b.set_geometry = 1;
 
 	tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
diff -u --recursive --new-file v1.3.47/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v1.3.47/linux/drivers/block/ide.h	Mon Dec 11 15:42:01 1995
+++ linux/drivers/block/ide.h	Sun Dec 17 11:17:19 1995
@@ -355,6 +355,9 @@
 	struct request request_sense_request;	/* from ide-cd.c */
 	struct packet_command request_sense_pc;	/* from ide-cd.c */
 #endif /* CONFIG_BLK_DEV_IDECD */
+#ifdef CONFIG_BLK_DEV_IDETAPE
+	ide_drive_t	*tape_drive;	/* Pointer to the tape on this interface */
+#endif /* CONFIG_BLK_DEV_IDETAPE */
 	} ide_hwif_t;
 
 /*
@@ -413,6 +416,14 @@
 void ide_error (ide_drive_t *drive, const char *msg, byte stat);
 
 /*
+ * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
+ * removing leading/trailing blanks and compressing internal blanks.
+ * It is primarily used to tidy up the model name/number fields as
+ * returned by the WIN_[P]IDENTIFY commands.
+ */
+void ide_fixstring (byte *s, const int bytecount, const int byteswap);
+
+/*
  * This routine busy-waits for the drive status to be not "busy".
  * It then checks the status for all of the "good" bits and none
  * of the "bad" bits, and if all is okay it returns 0.  All other
@@ -443,7 +454,8 @@
 typedef enum
 	{ide_wait,	/* insert rq at end of list, and wait for it */
 	 ide_next,	/* insert rq immediately after current request */
-	 ide_preempt}	/* insert rq in front of current request */
+	 ide_preempt,	/* insert rq in front of current request */
+	 ide_end}	/* insert rq at end of list, but don't wait for it */
  ide_action_t;
 
 /*
@@ -465,6 +477,12 @@
  * returns without waiting for the new rq to be completed.  As above,
  * This is VERY DANGEROUS, and is intended for careful use by the 
  * ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_end, then the rq is queued at the end of the
+ * request queue, and the function returns immediately without waiting
+ * for the new rq to be completed. This is again intended for careful
+ * use by the ATAPI tape/cdrom driver code. (Currently used by ide-tape.c,
+ * when operating in the pipelined operation mode).
  */
 int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
  
@@ -534,6 +552,13 @@
  */
  
 void idetape_register_chrdev (void);
+
+/*
+ *	The following function is called to re-insert a postponed tape
+ *	request into the request queue.
+ */
+ 
+void idetape_put_back_postponed_request (ide_drive_t *drive);
 
 #endif /* CONFIG_BLK_DEV_IDETAPE */
 
diff -u --recursive --new-file v1.3.47/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v1.3.47/linux/drivers/block/ll_rw_blk.c	Mon Dec 11 15:42:01 1995
+++ linux/drivers/block/ll_rw_blk.c	Thu Dec 14 08:16:53 1995
@@ -623,6 +623,7 @@
 		req->next = NULL;
 	}
 	memset(ro_bits,0,sizeof(ro_bits));
+	rd_init();
 #ifdef CONFIG_BLK_DEV_IDE
 	ide_init();		/* this MUST preceed hd_init */
 #endif
diff -u --recursive --new-file v1.3.47/linux/drivers/block/ramdisk.c linux/drivers/block/ramdisk.c
--- v1.3.47/linux/drivers/block/ramdisk.c	Mon Oct 23 18:02:03 1995
+++ linux/drivers/block/ramdisk.c	Thu Jan  1 02:00:00 1970
@@ -1,232 +0,0 @@
-/*
- *  linux/kernel/blk_drv/ramdisk.c
- *
- *  Written by Theodore Ts'o, 12/2/91
- *
- * Modifications by Fred N. van Kempen to allow for bootable root
- * disks (which are used in LINUX/Pro).  Also some cleanups.  03/03/93
- */
-
-
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-
-#define MAJOR_NR  MEM_MAJOR
-#include <linux/blk.h>
-
-#define RAMDISK_MINOR	1
-
-extern void wait_for_keypress(void);
-
-char	*rd_start;
-int	rd_length = 0;
-static int rd_blocksizes[2] = {0, 0};
-
-static void do_rd_request(void)
-{
-	int	len;
-	char	*addr;
-
-repeat:
-	INIT_REQUEST;
-	addr = rd_start + (CURRENT->sector << 9);
-	len = CURRENT->current_nr_sectors << 9;
-
-	if ((MINOR(CURRENT->rq_dev) != RAMDISK_MINOR) ||
-	    (addr+len > rd_start+rd_length)) {
-		end_request(0);
-		goto repeat;
-	}
-	if (CURRENT-> cmd == WRITE) {
-		(void ) memcpy(addr,
-			      CURRENT->buffer,
-			      len);
-	} else if (CURRENT->cmd == READ) {
-		(void) memcpy(CURRENT->buffer, 
-			      addr,
-			      len);
-	} else
-		panic("RAMDISK: unknown RAM disk command !\n");
-	end_request(1);
-	goto repeat;
-}
-
-static struct file_operations rd_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	NULL,			/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* no special release code */
-	block_fsync		/* fsync */
-};
-
-/*
- * Returns amount of memory which needs to be reserved.
- */
-long rd_init(long mem_start, int length)
-{
-	int	i;
-	char	*cp;
-
-	if (register_blkdev(MEM_MAJOR,"rd",&rd_fops)) {
-		printk("RAMDISK: Unable to get major %d.\n", MEM_MAJOR);
-		return 0;
-	}
-	blk_dev[MEM_MAJOR].request_fn = DEVICE_REQUEST;
-	rd_start = (char *) mem_start;
-	rd_length = length;
-	cp = rd_start;
-	for (i=0; i < length; i++)
-		*cp++ = '\0';
-
-	for(i=0;i<2;i++) rd_blocksizes[i] = 1024;
-	blksize_size[MAJOR_NR] = rd_blocksizes;
-
-	return(length);
-}
-
-static void do_load(void)
-{
-	struct buffer_head *bh;
-	struct super_block {
-	  union
-	  {
-	    char minix [sizeof (struct minix_super_block)];
-	    char ext2 [sizeof (struct ext2_super_block)];
-	  } record;
-	} sb;
-	struct minix_super_block *minixsb =
-		(struct minix_super_block *)&sb;
-	struct ext2_super_block *ext2sb =
-		(struct ext2_super_block *)&sb;
-	int		block, tries;
-	int		i = 1;
-	int		nblocks;
-	char		*cp;
-	
-	/*
-	 * Check for a super block on the diskette.
-	 * The old-style boot/root diskettes had their RAM image
-	 * starting at block 512 of the boot diskette.  LINUX/Pro
-	 * uses the entire diskette as a file system, so in that
-	 * case, we have to look at block 0.  Be intelligent about
-	 * this, and check both... - FvK
-	 */
-	for (tries = 0; tries < 1000; tries += 512) {
-		block = tries;
-		bh = breada(ROOT_DEV,block+1,BLOCK_SIZE, 0,  PAGE_SIZE);
-		if (!bh) {
-			printk("RAMDISK: I/O error while looking for super block!\n");
-			return;
-		}
-
-		/* This is silly- why do we require it to be a MINIX FS? */
-		*((struct super_block *) &sb) =
-			*((struct super_block *) bh->b_data);
-		brelse(bh);
-
-
-		/* Try Minix */
-		nblocks = -1;
-		if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
-		    minixsb->s_magic == MINIX_SUPER_MAGIC2) {
-			printk("RAMDISK: Minix filesystem found at block %d\n",
-				block);
-			nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
-		}
-
-		/* Try ext2 */
-		if (nblocks == -1 && ext2sb->s_magic == EXT2_SUPER_MAGIC)
-	        {
-			printk("RAMDISK: Ext2 filesystem found at block %d\n",
-				block);
-			nblocks = ext2sb->s_blocks_count;
-		}
-
-		if (nblocks == -1)
-		{
-			printk("RAMDISK: trying old-style RAM image.\n");
-			continue;
-		}
-
-		if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) {
-			printk("RAMDISK: image too big! (%d/%d blocks)\n",
-					nblocks, rd_length >> BLOCK_SIZE_BITS);
-			return;
-		}
-		printk("RAMDISK: Loading %d blocks into RAM disk", nblocks);
-
-		/* We found an image file system.  Load it into core! */
-		cp = rd_start;
-		while (nblocks) {
-			if (nblocks > 2) 
-			        bh = breada(ROOT_DEV, block, BLOCK_SIZE, 0,  PAGE_SIZE);
-			else
-				bh = bread(ROOT_DEV, block, BLOCK_SIZE);
-			if (!bh) {
-				printk("RAMDISK: I/O error on block %d, aborting!\n", 
-				block);
-				return;
-			}
-			(void) memcpy(cp, bh->b_data, BLOCK_SIZE);
-			brelse(bh);
-			if (!(nblocks-- & 15)) printk(".");
-			cp += BLOCK_SIZE;
-			block++;
-			i++;
-		}
-		printk("\ndone\n");
-
-		/* We loaded the file system image.  Prepare for mounting it. */
-		ROOT_DEV = MKDEV(MEM_MAJOR, RAMDISK_MINOR);
-		return;
-	}
-}
-
-/*
- * If the root device is the RAM disk, try to load it.
- * In order to do this, the root device is originally set to the
- * floppy, and we later change it to be RAM disk.
- */
-void rd_load(void)
-{
-	struct inode inode;
-	struct file filp;
-
-	/* If no RAM disk specified, give up early. */
-	if (!rd_length)
-		return;
-	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)
-		return;
-
-	/* for Slackware install disks */
-	printk(KERN_NOTICE "VFS: Insert root floppy to be loaded into ramdisk and press ENTER\n");
-	wait_for_keypress();
-
-	memset(&filp, 0, sizeof(filp));
-	memset(&inode, 0, sizeof(inode));
-	inode.i_rdev = ROOT_DEV;
-	filp.f_mode = 1; /* read only */
-	filp.f_inode = &inode;
-	if(blkdev_open(&inode, &filp) == 0 ){
-		do_load();
-		if(filp.f_op && filp.f_op->release)
-			filp.f_op->release(&inode,&filp);
-	}
-}
diff -u --recursive --new-file v1.3.47/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v1.3.47/linux/drivers/block/rd.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/block/rd.c	Thu Dec 14 08:29:23 1995
@@ -0,0 +1,527 @@
+/*
+ * ramdisk.c - Multiple ramdisk driver - gzip-loading version - v. 0.8 beta.
+ * 
+ * (C) Chad Page, Theodore Ts'o, et. al, 1995. 
+ *
+ * This ramdisk is designed to have filesystems created on it and mounted
+ * just like a regular floppy disk.  
+ *  
+ * It also does something suggested by Linus: use the buffer cache as the
+ * ramdisk data.  This makes it possible to dynamically allocate the ramdisk
+ * buffer - with some consequences I have to deal with as I write this. 
+ * 
+ * This code is based on the original ramdisk.c, written mostly by
+ * Theodore Ts'o (TYT) in 1991.  The code was largely rewritten by
+ * Chad Page to use the buffer cache to store the ramdisk data in
+ * 1995; Theodore then took over the driver again, and cleaned it up
+ * for inclusion in the mainline kernel.
+ *
+ * The original CRAMDISK code was written by Richard Lyons, and
+ * adapted by Chad Page to use the new ramdisk interface.  Theodore
+ * Ts'o rewrote it so that both the compressed ramdisk loader and the
+ * kernel decompressor uses the same inflate.c codebase.  The ramdisk
+ * loader now also loads into a dynamic (buffer cache based) ramdisk,
+ * not the old static ramdisk.  Support for the old static ramdisk has
+ * been completely removed.
+ */
+
+#include <linux/sched.h>
+#include <linux/minix_fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/malloc.h>
+#include <linux/ioctl.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+
+extern void wait_for_keypress(void);
+
+/*
+ * 35 has been officially registered as the RAMDISK major number, but
+ * so is the original MAJOR number of 1.  We're using 1 in
+ * include/linux/major.h for now
+ */
+#define MAJOR_NR RAMDISK_MAJOR
+#include <linux/blk.h>
+
+#define BUILD_CRAMDISK
+#define NUM_RAMDISKS 8
+
+void rd_load(void);
+static int crd_load(struct file *fp, struct file *outfp);
+
+/* Various static variables go here... mostly used within the ramdisk code only. */
+
+static int rd_length[NUM_RAMDISKS];
+static int rd_blocksizes[NUM_RAMDISKS];
+
+/*
+ * Parameters for the boot-loading of the ramdisk.  These are set by
+ * init/main.c (from arguments to the kernel command line) or from the
+ * architecture-specific setup routine (from the stored bootsector
+ * information). 
+ */
+int rd_doload = 0;		/* 1 = load ramdisk, 0 = don't load */
+int rd_prompt = 1;		/* 1 = prompt for ramdisk, 0 = don't prompt */
+int rd_image_start = 0;		/* starting block # of image */
+
+int rd_loading = 0;
+
+/*
+ *  Basically, my strategy here is to set up a buffer-head which can't be
+ *  deleted, and make that my Ramdisk.  If the request is outside of the
+ *  allocated size, we must get rid of it...
+ *
+ */
+static void rd_request(void)
+{
+	unsigned int minor;
+	int offset, len;
+
+repeat:
+	INIT_REQUEST;
+	
+	minor = MINOR(CURRENT->rq_dev);
+
+	if (minor >= NUM_RAMDISKS) {
+		end_request(0);
+		goto repeat;
+	}
+	
+	offset = CURRENT->sector << 9;
+	len = CURRENT->current_nr_sectors << 9;
+
+	if ((offset + len) > rd_length[minor]) {
+		end_request(0);
+		goto repeat;
+	}
+
+	if (CURRENT->cmd == READ) {	
+		memset(CURRENT->buffer, 0, len); 
+	}
+	set_bit(BH_Protected, &CURRENT->bh->b_state);
+
+	end_request(1);
+	goto repeat;
+} 
+
+static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int err;
+	
+	if (!inode || !inode->i_rdev) 	
+		return -EINVAL;
+
+	switch (cmd) {
+		case BLKFLSBUF:
+			if (!suser()) return -EACCES;
+			invalidate_buffers(inode->i_rdev);
+			break;
+         	case BLKGETSIZE:   /* Return device size */
+			if (!arg)  return -EINVAL;
+			err = verify_area(VERIFY_WRITE, (long *) arg,
+					  sizeof(long));
+			if (err)
+				return err;
+			put_user(rd_length[MINOR(inode->i_rdev)] / 512, 
+				 (long *) arg);
+			return 0;
+			
+		default:
+			break;
+	};
+
+	return 0;
+}
+
+static int rd_open(struct inode * inode, struct file * filp)
+{
+
+	if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
+		return -ENODEV;
+
+	return 0;
+}
+
+static struct file_operations fd_fops = {
+	NULL,		/* lseek - default */
+	block_read,	/* read - block dev write */
+	block_write,	/* write - block dev write */
+	NULL,		/* readdir - not here! */
+	NULL,		/* select */
+	rd_ioctl, 	/* ioctl */
+	NULL,		/* mmap */
+	rd_open,	/* open */
+	NULL,		/* no special release code... */
+	block_fsync		/* fsync */ 
+};
+
+/* This is the registration and initialization section of the ramdisk driver */
+int rd_init(void)
+{
+	int		i;
+
+	if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
+		printk("RAMDISK2 : Could not get major %d", MAJOR_NR);
+		return -EIO;
+	}
+
+	blk_dev[MAJOR_NR].request_fn = &rd_request;
+
+	for (i = 0; i < NUM_RAMDISKS; i++) {
+		rd_length[i] = (16384 * 1024);
+		rd_blocksizes[i] = 1024;
+	}
+
+	blksize_size[MAJOR_NR] = rd_blocksizes;
+
+	return 0;
+}
+
+/*
+ * This routine tries to a ramdisk image to load, and returns the
+ * number of blocks to read for a non-compressed image, 0 if the image
+ * is a compressed image, and -1 if an image with the right magic
+ * numbers could not be found.
+ *
+ * We currently check for the following magic numbers:
+ * 	minix
+ * 	ext2
+ * 	gzip
+ */
+int
+identify_ramdisk_image(int device, struct file *fp, int start_block)
+{
+	const int size = 512;
+	struct minix_super_block *minixsb;
+	struct ext2_super_block *ext2sb;
+	int nblocks = -1;
+	int max_blocks;
+	unsigned char *buf;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (buf == 0)
+		return -1;
+
+	minixsb = (struct minix_super_block *) buf;
+	ext2sb = (struct ext2_super_block *) buf;
+	memset(buf, 0xe5, size);
+
+	/*
+	 * Read block 0 to test for gzipped kernel
+	 */
+	if (fp->f_op->lseek)
+		fp->f_op->lseek(fp->f_inode, fp, start_block * BLOCK_SIZE, 0);
+	fp->f_pos = start_block * BLOCK_SIZE;
+	
+	fp->f_op->read(fp->f_inode, fp, buf, size);
+
+	/*
+	 * If it matches the gzip magic numbers, return -1
+	 */
+	if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) {
+		printk(KERN_NOTICE
+		       "RAMDISK: Compressed image found at block %d\n",
+		       start_block);
+		nblocks = 0;
+		goto done;
+	}
+
+	/*
+	 * Read block 1 to test for minix and ext2 superblock
+	 */
+	if (fp->f_op->lseek)
+		fp->f_op->lseek(fp->f_inode, fp,
+				(start_block+1) * BLOCK_SIZE, 0);
+	fp->f_pos = (start_block+1) * BLOCK_SIZE;
+
+	fp->f_op->read(fp->f_inode, fp, buf, size);
+		
+	/* Try minix */
+	if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
+	    minixsb->s_magic == MINIX_SUPER_MAGIC2) {
+		printk(KERN_NOTICE
+		       "RAMDISK: Minix filesystem found at block %d\n",
+		       start_block);
+		nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
+		goto done;
+	}
+
+	/* Try ext2 */
+	printk("ext2 magic = %d\n", ext2sb->s_magic);
+	if (ext2sb->s_magic == EXT2_SUPER_MAGIC) {
+		printk(KERN_NOTICE
+		       "RAMDISK: Ext2 filesystem found at block %d\n",
+		       start_block);
+		nblocks = ext2sb->s_blocks_count;
+		goto done;
+	}
+	printk(KERN_NOTICE
+	       "RAMDISK: Couldn't find valid ramdisk image starting at %d.\n",
+	       start_block);
+	
+done:
+	if (fp->f_op->lseek)
+		fp->f_op->lseek(fp->f_inode, fp, start_block * BLOCK_SIZE, 0);
+	fp->f_pos = start_block * BLOCK_SIZE;	
+
+	if ((nblocks > 0) && blk_size[MAJOR(device)]) {
+		max_blocks = blk_size[MAJOR(device)][MINOR(device)];
+		max_blocks -= start_block;
+		if (nblocks > max_blocks) {
+			printk(KERN_NOTICE
+			       "RAMDISK: Restricting filesystem size "
+			       "from %d to %d blocks.\n",
+			       nblocks, max_blocks);
+			nblocks = max_blocks;
+		}
+	}
+	kfree(buf);
+	return nblocks;
+}
+
+/*
+ * This routine loads in the ramdisk image.
+ */
+void rd_load()
+{
+	struct inode inode, out_inode;
+	struct file infile, outfile;
+	unsigned short fs;
+	int device, ram_device;
+	int nblocks, i;
+	char *buf;
+
+	if (rd_doload == 0)
+		return;
+	
+	device = ROOT_DEV;
+	ram_device = (MAJOR_NR << 8);
+
+	if (MAJOR(device) != FLOPPY_MAJOR) return;
+
+	if (rd_prompt) {
+		printk(KERN_NOTICE
+		       "VFS: Insert ramdisk floppy and press ENTER\n");
+		wait_for_keypress();
+	}
+
+	memset(&infile, 0, sizeof(infile));
+	memset(&inode, 0, sizeof(inode));
+	inode.i_rdev = device;
+	infile.f_mode = 1; /* read only */
+	infile.f_inode = &inode;
+
+	memset(&outfile, 0, sizeof(outfile));
+	memset(&out_inode, 0, sizeof(out_inode));
+	out_inode.i_rdev = ram_device;
+	outfile.f_mode = 3; /* read/write */
+	outfile.f_inode = &out_inode;
+
+	if (blkdev_open(&inode, &infile) != 0) return;
+	if (blkdev_open(&out_inode, &outfile) != 0) return;
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	rd_loading = 1;
+	
+	nblocks = identify_ramdisk_image(device, &infile, rd_image_start);
+	if (nblocks < 0)
+		goto done;
+
+	if (nblocks == 0) {
+#ifdef BUILD_CRAMDISK
+		if (crd_load(&infile, &outfile) == 0)
+			goto successful_load;
+#else
+		printk(KERN_NOTICE
+		       "RAMDISK: Kernel does not support compressed "
+		       "ramdisk images\n");
+#endif
+		goto done;
+	}
+
+	if (nblocks > (rd_length[0] >> BLOCK_SIZE_BITS)) {
+		printk("RAMDISK: image too big! (%d/%d blocks)\n",
+		       nblocks, rd_length[0] >> BLOCK_SIZE_BITS);
+		goto done;
+	}
+		
+	/*
+	 * OK, time to copy in the data
+	 */
+	buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
+	if (buf == 0) {
+		printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
+		goto done;
+	}
+	for (i=0; i < nblocks; i++) {
+		infile.f_op->read(infile.f_inode, &infile, buf,
+				  BLOCK_SIZE);
+		outfile.f_op->write(outfile.f_inode, &outfile, buf,
+				    BLOCK_SIZE);
+	}
+	kfree(buf);
+
+successful_load:
+	invalidate_buffers(ROOT_DEV);
+	ROOT_DEV = (MAJOR_NR << 8);
+
+done:
+	if (infile.f_op->release)
+		infile.f_op->release(&inode, &infile);
+	set_fs(fs);
+	rd_loading = 0;
+}
+
+#ifdef BUILD_CRAMDISK
+
+#include <string.h>
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+
+#define memzero(s, n)     memset ((s), 0, (n))
+
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define INBUFSIZ 4096
+#define WSIZE 0x8000    /* window size--must be a power of two, and */
+			/*  at least 32K for zip's deflate method */
+
+static uch *inbuf;
+static uch *window;
+
+static unsigned insize = 0;  /* valid bytes in inbuf */
+static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0;  /* bytes in output buffer */
+static exit_code = 0;
+static long bytes_out = 0;
+static struct file *crd_infp, *crd_outfp;
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+		
+/* Diagnostic functions (stubbed out) */
+#define Assert(cond,msg)
+#define Trace(x)
+#define Tracev(x)
+#define Tracevv(x)
+#define Tracec(c,x)
+#define Tracecv(c,x)
+
+#define STATIC static
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void *malloc(int size);
+static void free(void *where);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+#include "../../lib/inflate.c"
+
+static void *malloc(int size)
+{
+	return kmalloc(size, GFP_KERNEL);
+}
+
+static void free(void *where)
+{
+	kfree(where);
+}
+
+static void gzip_mark(void **ptr)
+{
+}
+
+static void gzip_release(void **ptr)
+{
+}
+
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf()
+{
+	if (exit_code) return -1;
+	
+	insize = crd_infp->f_op->read(crd_infp->f_inode, crd_infp,
+				      inbuf, INBUFSIZ);
+	if (insize == 0) return -1;
+
+	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.)
+ */
+static void flush_window()
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, ch;
+    
+    crd_outfp->f_op->write(crd_outfp->f_inode, crd_outfp, window,
+			   outcnt);
+    in = window;
+    for (n = 0; n < outcnt; n++) {
+	    ch = *in++;
+	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void error(char *x)
+{
+	printk(KERN_ERR "%s", x);
+	exit_code = 1;
+}
+
+static int
+crd_load(struct file * fp, struct file *outfp)
+{
+	int result;
+	
+	crd_infp = fp;
+	crd_outfp = outfp;
+	inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
+	if (inbuf == 0) {
+		printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n");
+		return -1;
+	}
+	window = kmalloc(WSIZE, GFP_KERNEL);
+	if (window == 0) {
+		printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n");
+		kfree(inbuf);
+		return -1;
+	}
+	makecrc();
+	result = gunzip();
+	kfree(inbuf);
+	kfree(window);
+	return result;
+}
+
+#endif
+
+
+
diff -u --recursive --new-file v1.3.47/linux/drivers/block/triton.c linux/drivers/block/triton.c
--- v1.3.47/linux/drivers/block/triton.c	Mon Dec 11 15:42:01 1995
+++ linux/drivers/block/triton.c	Sun Dec 17 11:17:19 1995
@@ -71,6 +71,20 @@
  *	- much better than its 1Gig cousin, this drive is reported to work
  *	  very well with DMA (7.3MB/sec).
  *
+ * Other drives:
+ *
+ *   Maxtor 7540AV (515Meg w/32kB buffer), DMA modes mword0/sword2, PIO mode3.
+ *	- a budget drive, with budget performance, around 3MB/sec.
+ *
+ *   Western Digital AC2850F (814Meg w/64kB buffer), DMA mode1, PIO mode3.
+ *	- another "caviar" drive, similar to the AC31000, except that this one
+ *	  worked with DMA in at least one system.  Throughput is about 3.8MB/sec
+ *	  for both DMA and PIO.
+ *
+ *   Conner CFS850A (812Meg w/64kB buffer), DMA mode2, PIO mode4.
+ *	- like most Conner models, this drive proves that even a fast interface
+ *	  cannot improve slow media.  Both DMA and PIO peak around 3.5MB/sec.
+ *
  * If you have any drive models to add, email your results to:  mlord@bnr.ca
  * Keep an eye on /var/adm/messages for "DMA disabled" messages.
  *
diff -u --recursive --new-file v1.3.47/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v1.3.47/linux/drivers/cdrom/cdu31a.c	Mon Nov 27 12:48:29 1995
+++ linux/drivers/cdrom/cdu31a.c	Thu Dec 14 16:24:58 1995
@@ -170,7 +170,6 @@
  */
 
 #include <linux/major.h>
-#include <linux/config.h>
 
 #include <linux/module.h>
 
diff -u --recursive --new-file v1.3.47/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v1.3.47/linux/drivers/cdrom/sbpcd.c	Tue Nov 21 13:22:09 1995
+++ linux/drivers/cdrom/sbpcd.c	Thu Dec 14 16:25:43 1995
@@ -285,6 +285,7 @@
 #include <asm/segment.h>
 #include <stdarg.h>
 #include <linux/sbpcd.h>
+#include <linux/config.h>
 
 #if !(SBPCD_ISSUE-1)
 #define MAJOR_NR MATSUSHITA_CDROM_MAJOR
diff -u --recursive --new-file v1.3.47/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog
--- v1.3.47/linux/drivers/char/ChangeLog	Thu Nov  9 11:23:48 1995
+++ linux/drivers/char/ChangeLog	Thu Dec 14 08:16:52 1995
@@ -1,3 +1,14 @@
+Tue Dec  5 13:21:27 1995    <tytso@rsts-11.mit.edu>
+
+	* serial.c (check_modem_status, rs_ioctl): Support the new
+		ioctl()'s TIOCGICOUNT, TIOCMIWAIT.  These allow an
+		application program to wait on a modem serial register
+		status bit change, and to find out how many changes have
+		taken place for the MSR bits.
+
+		(rs_write): Eliminate a race condition which is introduced
+		if it is necessary to wait for the semaphore.
+
 Sat Nov  4 17:14:45 1995    <tytso@rsts-11.mit.edu>
 
 	* tty_io.c (tty_init): Move registration of TTY_MAJOR and
diff -u --recursive --new-file v1.3.47/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v1.3.47/linux/drivers/char/busmouse.c	Tue Nov 21 13:22:09 1995
+++ linux/drivers/char/busmouse.c	Thu Dec 14 08:16:53 1995
@@ -30,6 +30,7 @@
  * Replaced dumb busy loop with udelay()  16 Nov 95
  *   Nathan Laredo <laredo@gnu.ai.mit.edu>
  *
+ * Track I/O ports with request_region().  12 Dec 95 Philip Blundell 
  */
 
 #include <linux/module.h>
@@ -43,6 +44,7 @@
 #include <linux/mouse.h>
 #include <linux/random.h>
 #include <linux/delay.h>
+#include <linux/ioport.h>
 
 #include <asm/io.h>
 #include <asm/segment.h>
@@ -137,7 +139,7 @@
 		return -EINVAL;
 	if (mouse.active++)
 		return 0;
-	if (request_irq(mouse_irq, mouse_interrupt, 0, "Busmouse")) {
+	if (request_irq(mouse_irq, mouse_interrupt, 0, "busmouse")) {
 		mouse.active--;
 		return -EBUSY;
 	}
@@ -242,7 +244,10 @@
 
 int bus_mouse_init(void)
 {
-	int i;
+	if (check_region(LOGIBM_BASE, LOGIBM_EXTENT)) {
+	  mouse.present = 0;
+	  return -EIO;
+	}
 
 	outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
 	outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT);
@@ -253,6 +258,9 @@
 	}
 	outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT);
 	MSE_INT_OFF();
+	
+	request_region(LOGIBM_BASE, LOGIBM_EXTENT, "busmouse");
+
 	mouse.present = 1;
 	mouse.active = 0;
 	mouse.ready = 0;
@@ -260,7 +268,7 @@
 	mouse.dx = 0;
 	mouse.dy = 0;
 	mouse.wait = NULL;
-	printk("Logitech Bus mouse detected and installed with IRQ %d.\n",
+	printk("Logitech bus mouse detected, using IRQ %d.\n",
 	       mouse_irq);
 	mouse_register(&bus_mouse);
 	return 0;
@@ -276,5 +284,6 @@
 void cleanup_module(void)
 {
 	mouse_deregister(&bus_mouse);
+	release_region(LOGIBM_BASE, LOGIBM_EXTENT);
 }
 #endif
diff -u --recursive --new-file v1.3.47/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v1.3.47/linux/drivers/char/serial.c	Tue Oct 10 18:46:34 1995
+++ linux/drivers/char/serial.c	Thu Dec 14 08:16:52 1995
@@ -11,6 +11,8 @@
  *  set_serial_info fixed to set the flags, custom divisor, and uart
  * 	type fields.  Fix suggested by Michael K. Johnson 12/12/92.
  *
+ *  TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk>
+ *
  * This module exports the following rs232 io functions:
  *
  *	int rs_init(void);
@@ -455,6 +457,19 @@
 	
 	status = serial_in(info, UART_MSR);
 
+	if (status & UART_MSR_ANY_DELTA) {
+		/* update input line counters */
+		if (status & UART_MSR_TERI)
+			info->icount.rng++;
+		if (status & UART_MSR_DDSR)
+			info->icount.dsr++;
+		if (status & UART_MSR_DDCD)
+			info->icount.dcd++;
+		if (status & UART_MSR_DCTS)
+			info->icount.cts++;
+		wake_up_interruptible(&info->delta_msr_wait);
+	}
+
 	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
 #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
 		printk("ttys%d CD now %s...", info->line,
@@ -1304,6 +1319,8 @@
 	if (!tty || !info->xmit_buf || !tmp_buf)
 		return 0;
 	    
+	if (from_user)
+		down(&tmp_buf_sem);
 	save_flags(flags);
 	while (1) {
 		cli();		
@@ -1313,12 +1330,10 @@
 			break;
 
 		if (from_user) {
-			down(&tmp_buf_sem);
 			memcpy_fromfs(tmp_buf, buf, c);
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
-			up(&tmp_buf_sem);
 		} else
 			memcpy(info->xmit_buf + info->xmit_head, buf, c);
 		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
@@ -1328,6 +1343,8 @@
 		count -= c;
 		total += c;
 	}
+	if (from_user)
+		up(&tmp_buf_sem);
 	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
@@ -1843,13 +1860,16 @@
 	int error;
 	struct async_struct * info = (struct async_struct *)tty->driver_data;
 	int retval;
+	struct async_icount cprev, cnow;	/* kernel counter temps */
+	struct serial_icounter_struct *p_cuser;	/* user space */
 
 	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
 		return -ENODEV;
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
 	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
-	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
+	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) &&
+	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -1949,6 +1969,55 @@
 		case TIOCSERSETMULTI:
 			return set_multiport_struct(info,
 				       (struct serial_multiport_struct *) arg);
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+		 * - mask passed in arg for lines of interest
+ 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+		 case TIOCMIWAIT:
+			cli();
+			cprev = info->icount;	/* note the counters on entry */
+			sti();
+			while (1) {
+				interruptible_sleep_on(&info->delta_msr_wait);
+				/* see if a signal did it */
+				if (current->signal & ~current->blocked)
+					return -ERESTARTSYS;
+				cli();
+				cnow = info->icount;	/* atomic copy */
+				sti();
+				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+				     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+					return 0;
+				}
+				cprev = cnow;
+			}
+			/* NOTREACHED */
+
+		/* 
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+		case TIOCGICOUNT:
+			error = verify_area(VERIFY_WRITE, (void *) arg,
+				sizeof(struct serial_icounter_struct));
+			if (error)
+				return error;
+			cli();
+			cnow = info->icount;
+			sti();
+			p_cuser = (struct serial_icounter_struct *) arg;
+			put_user(cnow.cts, &p_cuser->cts);
+			put_user(cnow.dsr, &p_cuser->dsr);
+			put_user(cnow.rng, &p_cuser->rng);
+			put_user(cnow.dcd, &p_cuser->dcd);
+			return 0;
+
 		default:
 			return -ENOIOCTLCMD;
 		}
@@ -2662,6 +2731,9 @@
 		info->normal_termios = serial_driver.init_termios;
 		info->open_wait = 0;
 		info->close_wait = 0;
+		info->delta_msr_wait = 0;
+		info->icount.cts = info->icount.dsr = 
+			info->icount.rng = info->icount.dcd = 0;
 		info->next_port = 0;
 		info->prev_port = 0;
 		if (info->irq == 2)
diff -u --recursive --new-file v1.3.47/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v1.3.47/linux/drivers/net/8390.c	Wed Dec 13 09:02:46 1995
+++ linux/drivers/net/8390.c	Fri Dec 15 06:45:43 1995
@@ -612,9 +612,7 @@
     
     dev->hard_start_xmit = &ei_start_xmit;
     dev->get_stats	= get_stats;
-#ifdef HAVE_MULTICAST
     dev->set_multicast_list = &set_multicast_list;
-#endif
 
     ether_setup(dev);
         
diff -u --recursive --new-file v1.3.47/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v1.3.47/linux/drivers/net/de4x5.c	Mon Dec 11 15:42:03 1995
+++ linux/drivers/net/de4x5.c	Fri Dec 15 06:46:15 1995
@@ -716,9 +716,7 @@
     dev->hard_start_xmit = &de4x5_queue_pkt;
     dev->stop = &de4x5_close;
     dev->get_stats = &de4x5_get_stats;
-#ifdef HAVE_MULTICAST
     dev->set_multicast_list = &set_multicast_list;
-#endif
     dev->do_ioctl = &de4x5_ioctl;
     
     dev->mem_start = 0;
diff -u --recursive --new-file v1.3.47/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v1.3.47/linux/drivers/net/ewrk3.c	Sat Nov 25 19:04:46 1995
+++ linux/drivers/net/ewrk3.c	Fri Dec 15 06:46:30 1995
@@ -625,9 +625,7 @@
       dev->hard_start_xmit = &ewrk3_queue_pkt;
       dev->stop = &ewrk3_close;
       dev->get_stats = &ewrk3_get_stats;
-#ifdef HAVE_MULTICAST
       dev->set_multicast_list = &set_multicast_list;
-#endif
       dev->do_ioctl = &ewrk3_ioctl;
 
       dev->mem_start = 0;
diff -u --recursive --new-file v1.3.47/linux/drivers/net/znet.c linux/drivers/net/znet.c
--- v1.3.47/linux/drivers/net/znet.c	Sat Nov 25 19:04:47 1995
+++ linux/drivers/net/znet.c	Fri Dec 15 06:47:26 1995
@@ -623,7 +623,6 @@
 		return &lp->stats;
 }
 
-#ifdef HAVE_MULTICAST
 /* Set or clear the multicast filter for this adaptor.
    As a side effect this routine must also initialize the device parameters.
    This is taken advantage of in open().
@@ -662,7 +661,6 @@
 	}
 #endif
 }
-#endif
 
 void show_dma(void)
 {
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v1.3.47/linux/drivers/scsi/Config.in	Fri Nov 17 08:42:26 1995
+++ linux/drivers/scsi/Config.in	Thu Dec 14 08:16:51 1995
@@ -23,15 +23,15 @@
 dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
 dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI
 dep_tristate 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
-bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380
+dep_tristate 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
 if [ "$CONFIG_PCI" = "y" ]; then
   dep_tristate 'NCR53c7,8xx SCSI support'  CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI
 fi
 dep_tristate 'Always IN2000 SCSI support (test release)' CONFIG_SCSI_IN2000 $CONFIG_SCSI
-bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16
+dep_tristate 'PAS16 SCSI support' CONFIG_SCSI_PAS16 $CONFIG_SCSI
 dep_tristate 'QLOGIC SCSI support' CONFIG_SCSI_QLOGIC $CONFIG_SCSI
 dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
-bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128
+dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI
 dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI
 dep_tristate '7000FASST SCSI support' CONFIG_SCSI_7000FASST $CONFIG_SCSI
 dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v1.3.47/linux/drivers/scsi/Makefile	Fri Nov 17 08:42:26 1995
+++ linux/drivers/scsi/Makefile	Thu Dec 14 15:44:09 1995
@@ -18,7 +18,7 @@
 MOD_LIST_NAME := SCSI_MODULES
 SCSI_SRCS = $(wildcard $(L_OBJS:%.o=%.c))
 
-AHA152X	= -DDEBUG_AHA152X -DAUTOCONF -DSKIP_BIOSTEST -DIRQ=11
+AHA152X	= -DDEBUG_AHA152X -DAUTOCONF
 
 ifeq (${CFLAGS},)
 CFLAGS = -D__KERNEL__=1 \
@@ -170,6 +170,10 @@
 
 ifeq ($(CONFIG_SCSI_GENERIC_NCR5380),y)
 L_OBJS += g_NCR5380.o
+else
+  ifeq ($(CONFIG_SCSI_GENERIC_NCR5380),m)
+  M_OBJS += g_NCR5380.o
+  endif
 endif
 
 ifeq ($(CONFIG_SCSI_NCR53C7xx),y)
@@ -182,6 +186,10 @@
 
 ifeq ($(CONFIG_SCSI_PAS16),y)
 L_OBJS += pas16.o
+else
+  ifeq ($(CONFIG_SCSI_PAS16),m)
+  M_OBJS += pas16.o
+  endif
 endif
 
 ifeq ($(CONFIG_SCSI_SEAGATE),y)
@@ -211,6 +219,10 @@
 
 ifeq ($(CONFIG_SCSI_T128),y)
 L_OBJS += t128.o
+else
+  ifeq ($(CONFIG_SCSI_T128),m)
+  M_OBJS += t128.o
+  endif
 endif
 
 ifeq ($(CONFIG_SCSI_ULTRASTOR),y)
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/README.st linux/drivers/scsi/README.st
--- v1.3.47/linux/drivers/scsi/README.st	Wed Sep 27 15:59:59 1995
+++ linux/drivers/scsi/README.st	Sun Dec 17 10:59:24 1995
@@ -1,5 +1,5 @@
 This file contains brief information about the SCSI tape driver.
-Last modified: Sun Sep 24 23:40:06 1995 by root@kai.makisara.fi
+Last modified: Sun Nov 26 12:54:21 1995 by root@kai.makisara.fi
 
 BASICS
 
@@ -43,7 +43,17 @@
 The buffer size is defined (in 1024 byte units) by ST_BUFFER_BLOCKS or
 at boot time. If this size is not enough, the driver tries to allocate
 a large enough temporary buffer that is released when the device is
-closed.
+closed. The maximum buffer size is defined by the kernel memory
+allocation (currently 256 kB for Alphas and 128 kB for other
+architectures).
+
+Allocation of the buffers is done at run-time when they are
+needed. Allocation of the specified number of buffers can be done at
+initialization if ST_RUNTIME_BUFFERS is defined non-zero. The
+advantage of run-time allocation is that memory is not wasted for
+buffers not being used. The disadvantage is that there may not be
+memory available at the time when a buffer is needed for the first
+time (once a buffer is allocated, it is not released).
 
 The maximum number of buffers allocated at initialization is defined by
 ST_MAX_BUFFERS. One buffer is allocated for each drive detected when
@@ -54,14 +64,10 @@
 default for ST_EXTRA_DEVS is two. The driver tries to allocate new
 buffers at run-time if necessary.
 
-Allocation of the buffers can be postponed to run-time if
-(ST_RUNTIME_BUFFERS). The advantage is that memory is not wasted for
-buffers not being used. The disadvantage is that there may not be
-memory available at the time when a buffer is needed for the first
-time (once a buffer is allocated, it is not released).
-
 The threshold for triggering asynchronous write in fixed block mode
-is defined by ST_WRITE_THRESHOLD.
+is defined by ST_WRITE_THRESHOLD. This may be optimized for each
+use pattern. The default triggers asynchronous write after three
+default sized writes (10 kB) from tar.
 
 
 BOOT TIME CONFIGURATION
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v1.3.47/linux/drivers/scsi/aha152x.c	Wed Dec 13 09:02:46 1995
+++ linux/drivers/scsi/aha152x.c	Thu Dec 14 15:45:44 1995
@@ -1,6 +1,6 @@
 /* aha152x.c -- Adaptec AHA-152x driver
- * Author: Juergen E. Fischer, fischer@server.et-inf.fho-emden.de
- * Copyright 1993, 1994 Juergen E. Fischer
+ * Author: Juergen E. Fischer, fischer@et-inf.fho-emden.de
+ * Copyright 1993, 1994, 1995 Juergen E. Fischer
  *
  *
  * This driver is based on
@@ -8,22 +8,28 @@
  * which is
  *   Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
  *
-
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2, or (at your option) any
  * later version.
-
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
- 
  *
- * $Id: aha152x.c,v 1.9 1995/03/18 09:20:24 root Exp root $
  *
-
+ * $Id: aha152x.c,v 1.11 1995/12/06 21:18:35 fischer Exp $
+ *
  * $Log: aha152x.c,v $
+ * Revision 1.11  1995/12/06  21:18:35  fischer
+ * - some minor updates
+ *
+ * Revision 1.10  1995/07/22  19:18:45  fischer
+ * - support for 2 controllers
+ * - started synchronous data transfers (not working yet)
+ *
  * Revision 1.9  1995/03/18  09:20:24  root
  * - patches for PCMCIA and modules
  *
@@ -145,7 +151,7 @@
  * Revision 0.0  1993/08/14  19:54:25  root
  * empty function bodies; detect() works.
  *
-
+ *
  **************************************************************************
 
 
@@ -158,23 +164,28 @@
 
  PER-DEFINE CONFIGURABLE OPTIONS:
 
- AUTOCONF       : use configuration the controller reports (only 152x)
- IRQ            : override interrupt channel (9,10,11 or 12) (default 11)
- SCSI_ID        : override scsiid of AIC-6260 (0-7) (default 7)
- RECONNECT      : override target dis-/reconnection/multiple outstanding commands (default on)
- PARITY		: override parity check (default on)
- SKIP_BIOSTEST  : Don't test for BIOS signature (AHA-1510 or disabled BIOS)
- PORTBASE       : Force port base. Don't try to probe
+ AUTOCONF:
+   use configuration the controller reports (only 152x)
+
+ SKIP_BIOSTEST:
+   Don't test for BIOS signature (AHA-1510 or disabled BIOS)
+
+ SETUP0	{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS }:
+   override for the first controller
+   
+ SETUP1	{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS }:
+   override for the second controller
 
 
  LILO COMMAND LINE OPTIONS:
 
- aha152x=<PORTBASE>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>]]]]
+ aha152x=<IOPORT>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>]]]]]
 
  The normal configuration can be overridden by specifying a command line.
  When you do this, the BIOS test is skipped. Entered values have to be
- valid (known). Don't use values that aren't support under normal operation.
- If you think that you need other values: contact me.
+ valid (known). Don't use values that aren't supported under normal operation.
+ If you think that you need other values: contact me.  For two controllers
+ use the aha152x statement twice.
 
 
  REFERENCES USED:
@@ -225,7 +236,7 @@
 #include <linux/proc_fs.h>
 
 #include "aha152x.h"
-#include<linux/stat.h>
+#include <linux/stat.h>
 
 struct proc_dir_entry proc_scsi_aha152x = {
     PROC_SCSI_AHA152X, 7, "aha152x",
@@ -241,26 +252,10 @@
 #endif
 #endif
 
-/* If auto configuration is disabled, IRQ, SCSI_ID and RECONNECT have to
-   be predefined */
-#if !defined(AUTOCONF)
-#if !defined(IRQ)
-#error undefined IRQ; define AUTOCONF or IRQ
-#endif
-#if !defined(SCSI_ID)
-#error undefined SCSI_ID; define AUTOCONF or SCSI_ID
-#endif
-#if !defined(RECONNECT)
-#error undefined RECONNECT; define AUTOCONF or RECONNECT
-#endif
-#if !defined(PARITY)
-#error undefined PARITY; define AUTOCONF or PARITY
-#endif
+#if !defined(AUTOCONF) && !defined(SETUP0)
+#error define AUTOCONF or SETUP0
 #endif
 
-/* I use this when I'm looking for weird bugs */
-#define DEBUG_TIMING 
-
 #if defined(DEBUG_AHA152X)
 
 #undef  SKIP_PORTS              /* don't display ports */
@@ -287,6 +282,7 @@
 #if 0
 #endif
 
+#define DEBUG_SELECTION
 #define DEBUG_PHASES
 #define DEBUG_RESET
 #define DEBUG_ABORT
@@ -297,66 +293,89 @@
 
 /* END OF DEFINES */
 
+extern long loops_per_sec;
+
 /* some additional "phases" for getphase() */
 #define P_BUSFREE  1
 #define P_PARITY   2
 
-static int port_base      = 0;
-static int this_host      = 0;
-static int can_disconnect = 0;
-static int can_doparity   = 0;
-static int commands       = 0;
+/* possible irq range */
+#define IRQ_MIN 9
+#define IRQ_MAX 12
+#define IRQS    IRQ_MAX-IRQ_MIN+1
 
-#ifdef DEBUG_AHA152X
-unsigned int aha152x_debug  = DEBUG_DEFAULT;
-#endif
+enum {
+  not_issued   = 0x0001,
+  in_selection = 0x0002,
+  disconnected = 0x0004,
+  aborted      = 0x0008,
+  sent_ident   = 0x0010,
+  in_other     = 0x0020,
+  in_sync      = 0x0040,
+  sync_ok      = 0x0080,
+};
 
 /* set by aha152x_setup according to the command line */
-static int setup_called    = 0;
-static int setup_portbase  = 0;
-static int setup_irq       = 0;
-static int setup_scsiid    = 0;
-static int setup_reconnect = 0;
-static int setup_doparity  = 0;
-
+static int  setup_count=0;
+static struct aha152x_setup {
+  char *conf;
+  int io_port;
+  int irq;
+  int scsiid;
+  int reconnect;
+  int parity;
+  int synchronous;
 #ifdef DEBUG_AHA152X
-static int setup_debug     = 0;
+  int debug;
 #endif
+} setup[2];
 
-static char *setup_str = (char *)NULL;
+static struct Scsi_Host *aha152x_host[IRQS];
 
-enum {
-   not_issued   = 0x01,
-   in_selection = 0x02,
-   disconnected = 0x04,
-   aborted      = 0x08,
-   sent_ident   = 0x10,
-   in_other     = 0x20,
-};
+#define HOSTDATA(shpnt)   ((struct aha152x_hostdata *) &shpnt->hostdata)
+#define CURRENT_SC	  (HOSTDATA(shpnt)->current_SC)
+#define ISSUE_SC	  (HOSTDATA(shpnt)->issue_SC)
+#define DISCONNECTED_SC	  (HOSTDATA(shpnt)->disconnected_SC)
+#define SYNCRATE	  (HOSTDATA(shpnt)->syncrate[CURRENT_SC->target])
+#define MSG(i)            (HOSTDATA(shpnt)->message[i])
+#define MSGLEN            (HOSTDATA(shpnt)->message_len)
+#define ADDMSG(x)	  (MSG(MSGLEN++)=x)
+
+struct aha152x_hostdata {
+  Scsi_Cmnd     *issue_SC;
+  Scsi_Cmnd     *current_SC;
+  Scsi_Cmnd     *disconnected_SC;
+  int           aborting;
+  int           abortion_complete;
+  int           abort_result;
+  int           commands;
+  
+  int           reconnect;
+  int           parity;
+  int           synchronous;
  
-/*
- * Command queues:
- * issue_SC        : commands that are queued to be issued 
- * current_SC      : command that's currently using the bus
- * disconnected_SC : commands that that have been disconnected 
- */
-static Scsi_Cmnd            *issue_SC        = NULL;
-static Scsi_Cmnd            *current_SC      = NULL;
-static Scsi_Cmnd            *disconnected_SC = NULL;
+  unsigned char syncrate[8];
+  
+  unsigned char message[256];
+  int           message_len;
 
-static int aborting=0, abortion_complete=0, abort_result;
+#ifdef DEBUG_AHA152X
+  int           debug;
+#endif
+};
 
-void aha152x_intr( int irq, struct pt_regs * );
-void aha152x_done( int error );
-void aha152x_setup( char *str, int *ints );
+void aha152x_intr(int irq, struct pt_regs *);
+void aha152x_done(struct Scsi_Host *shpnt, int error);
+void aha152x_setup(char *str, int *ints);
+int aha152x_checksetup(struct aha152x_setup *setup);
 
-static void aha152x_reset_ports(void);
-static void aha152x_panic(const char *msg);
+static void aha152x_reset_ports(struct Scsi_Host *shpnt);
+static void aha152x_panic(struct Scsi_Host *shpnt, char *msg);
 
-static void disp_ports(void);
+static void disp_ports(struct Scsi_Host *shpnt);
 static void show_command(Scsi_Cmnd *ptr);
-static void show_queues(void);
-static void disp_enintr(void);
+static void show_queues(struct Scsi_Host *shpnt);
+static void disp_enintr(struct Scsi_Host *shpnt);
 
 #if defined(DEBUG_RACE)
 static void enter_driver(const char *);
@@ -369,10 +388,7 @@
   0x340,      /* default first */
   0x140
 };
-#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
-
-/* possible interrupt channels */
-static unsigned short irqs[] = { 9, 10, 11, 12, 0 };
+#define PORT_COUNT (sizeof(ports) / sizeof(unsigned short))
 
 #if !defined(SKIP_BIOSTEST)
 /* possible locations for the Adaptec BIOS */
@@ -385,10 +401,10 @@
   (void *) 0xd4000,
   (void *) 0xd8000,
   (void *) 0xe0000,
-  (void *) 0xf0000,
   (void *) 0xeb800,   /* VTech Platinum SMP */
+  (void *) 0xf0000,
 };
-#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( void * ))
+#define ADDRESS_COUNT (sizeof(addresses) / sizeof(void *))
 
 /* signatures for various AIC-6[23]60 based controllers.
    The point in detecting signatures is to avoid useless
@@ -408,14 +424,17 @@
   { "Adaptec BIOS: ASW-B626",       0x0f, 22 },  /* on-board controller */
   { "Adaptec ASW-B626 S2",        0x2e6c, 19 },  /* on-board controller */
   { "Adaptec BIOS:AIC-6360",         0xc, 21 },  /* on-board controller */
-  { "ScsiPro SP-360 BIOS",        0x2873, 19 },  /* ScsiPro-Controller with AIC-6360 */
+  { "ScsiPro SP-360 BIOS",        0x2873, 19 },  /* ScsiPro-Controller  */
   { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 },  /* Gigabyte Local-Bus-SCSI */
+  { "Adaptec BIOS:AVA-282X",         0xc, 21 },  /* Adaptec 282x */
+  { "Adaptec IBM Dock II SCSI",   0x2edd, 24 },  /* IBM Thinkpad Dock II */
+  { "Adaptec BIOS:AHA-1532P",       0x1c, 22 },  /* IBM Thinkpad Dock II SCSI */
 };
-#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
+#define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature))
 #endif
 
 
-static void do_pause( unsigned amount ) /* Pause for amount*10 milliseconds */
+static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */
 {
    unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
 
@@ -426,7 +445,7 @@
 /*
  *  queue services:
  */
-static inline void append_SC( Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
+static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
 {
   Scsi_Cmnd *end;
 
@@ -435,15 +454,13 @@
     *SC=new_SC;
   else
     {
-      for( end=*SC;
-	   end->host_scribble;
-	   end = (Scsi_Cmnd *) end->host_scribble )
+      for(end=*SC; end->host_scribble; end = (Scsi_Cmnd *) end->host_scribble)
 	;
       end->host_scribble = (unsigned char *) new_SC;
     }
 }
 
-static inline Scsi_Cmnd *remove_first_SC( Scsi_Cmnd **SC )
+static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC)
 {
   Scsi_Cmnd *ptr;
 
@@ -453,13 +470,13 @@
   return ptr;
 }
 
-static inline Scsi_Cmnd *remove_SC( Scsi_Cmnd **SC, int target, int lun )
+static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
 {
   Scsi_Cmnd *ptr, *prev;
 
-  for( ptr=*SC, prev=NULL;
+  for(ptr=*SC, prev=NULL;
        ptr && ((ptr->target!=target) || (ptr->lun!=lun));
-       prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble )
+      prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
     ;
 
   if(ptr)
@@ -473,13 +490,13 @@
 /*
  * read inbound byte and wait for ACK to get low
  */
-static void make_acklow(void)
+static void make_acklow(struct Scsi_Host *shpnt)
 {
-  SETPORT( SXFRCTL0, CH1|SPIOEN );
+  SETPORT(SXFRCTL0, CH1|SPIOEN);
   GETPORT(SCSIDAT);
-  SETPORT( SXFRCTL0, CH1 );
+  SETPORT(SXFRCTL0, CH1);
 
-  while( TESTHI( SCSISIG, ACKI ) )
+  while(TESTHI(SCSISIG, ACKI))
     ;
 }
 
@@ -493,37 +510,36 @@
  *   P_BUSFREE   BUS FREE phase detected
  *   P_PARITY    parity error in DATA phase
  */
-static int getphase(void)
+static int getphase(struct Scsi_Host *shpnt)
 {
   int phase, sstat1;
   
-  while( 1 )
+  while(1)
     {
       do
 	{
-	  while( !( ( sstat1 = GETPORT( SSTAT1 ) ) & (BUSFREE|SCSIRSTI|REQINIT ) ) )
+          while(!((sstat1 = GETPORT(SSTAT1)) & (BUSFREE|SCSIRSTI|REQINIT)))
 	    ;
-	  if( sstat1 & BUSFREE )
+          if(sstat1 & BUSFREE)
 	    return P_BUSFREE;
-	  if( sstat1 & SCSIRSTI )
+          if(sstat1 & SCSIRSTI)
 	    {
-	      /* IBM drive responds with RSTI to RSTO */
 	      printk("aha152x: RESET IN\n");
-	      SETPORT( SSTAT1, SCSIRSTI );
+              SETPORT(SSTAT1, SCSIRSTI);
 	    }
 	}
-      while( TESTHI( SCSISIG, ACKI ) || TESTLO( SSTAT1, REQINIT ) );
+      while(TESTHI(SCSISIG, ACKI) || TESTLO(SSTAT1, REQINIT));
 
-      SETPORT( SSTAT1, CLRSCSIPERR );
+      SETPORT(SSTAT1, CLRSCSIPERR);
   
-      phase = GETPORT( SCSISIG ) & P_MASK ;
+      phase = GETPORT(SCSISIG) & P_MASK ;
 
-      if( TESTHI( SSTAT1, SCSIPERR ) )
+      if(TESTHI(SSTAT1, SCSIPERR))
 	{
-	  if( (phase & (CDO|MSGO))==0 )                         /* DATA phase */
+          if((phase & (CDO|MSGO))==0)                        /* DATA phase */
 	    return P_PARITY;
 
-	  make_acklow();
+          make_acklow(shpnt);
 	}
       else
 	return phase;
@@ -531,148 +547,170 @@
 }
 
 /* called from init/main.c */
-void aha152x_setup( char *str, int *ints)
+void aha152x_setup(char *str, int *ints)
 {
-  if(setup_called)
-    panic("aha152x: aha152x_setup called twice.\n");
-
-  setup_called=ints[0];
-  setup_str=str;
+  if(setup_count>2)
+    panic("aha152x: you can only configure up to two controllers\n");
 
-  setup_portbase  = ints[0] >= 1 ? ints[1] : 0x340;
-  setup_irq       = ints[0] >= 2 ? ints[2] : 11;
-  setup_scsiid	  = ints[0] >= 3 ? ints[3] : 7;
-  setup_reconnect = ints[0] >= 4 ? ints[4] : 1;
-  setup_doparity  = ints[0] >= 5 ? ints[5] : 1;
+  setup[setup_count].conf        = str;
+  setup[setup_count].io_port     = ints[0] >= 1 ? ints[1] : 0x340;
+  setup[setup_count].irq         = ints[0] >= 2 ? ints[2] : 11;
+  setup[setup_count].scsiid      = ints[0] >= 3 ? ints[3] : 7;
+  setup[setup_count].reconnect   = ints[0] >= 4 ? ints[4] : 1;
+  setup[setup_count].parity      = ints[0] >= 5 ? ints[5] : 1;
+  setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 0 /* FIXME: 1 */;
 #ifdef DEBUG_AHA152X
-  setup_debug     = ints[0] >= 6 ? ints[6] : DEBUG_DEFAULT;
+  setup[setup_count].debug       = ints[0] >= 7 ? ints[7] : DEBUG_DEFAULT;
+  if(ints[0]>7)
+    { 
+      printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>"
+ 	         "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>,[,<DEBUG>]]]]]]\n");
+#else
+  if(ints[0]>6)
+    {
+      printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>"
+             "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>]]]]]\n");
 #endif
+    }
+  else 
+    setup_count++;
 }
 
 /*
    Test, if port_base is valid.
  */
-static int aha152x_porttest(int port_base)
+static int aha152x_porttest(int io_port)
 {
   int i;
 
-  if(check_region(port_base, 0x20))
+  if(check_region(io_port, IO_RANGE))
     return 0;
 
-  SETPORT( DMACNTRL1, 0 );          /* reset stack pointer */
+  SETPORT(io_port+O_DMACNTRL1, 0);          /* reset stack pointer */
   for(i=0; i<16; i++)
-    SETPORT( STACK, i );
+    SETPORT(io_port+O_STACK, i);
 
-  SETPORT( DMACNTRL1, 0 );          /* reset stack pointer */
-  for(i=0; i<16 && GETPORT(STACK)==i; i++)
+  SETPORT(io_port+O_DMACNTRL1, 0);          /* reset stack pointer */
+  for(i=0; i<16 && GETPORT(io_port+O_STACK)==i; i++)
     ;
 
   return(i==16);
 }
 
+int aha152x_checksetup(struct aha152x_setup *setup)
+{
+  int i;
+  
+#ifndef PCMCIA
+  for(i=0; i<PORT_COUNT && (setup->io_port != ports[i]); i++)
+    ;
+  
+  if(i==PORT_COUNT)
+    return 0;
+#endif
+  
+  if(!aha152x_porttest(setup->io_port))
+    return 0;
+  
+  if((setup->irq < IRQ_MIN) && (setup->irq > IRQ_MAX))
+    return 0;
+  
+  if((setup->scsiid < 0) || (setup->scsiid > 7))
+    return 0;
+  
+  if((setup->reconnect < 0) || (setup->reconnect > 1))
+    return 0;
+  
+  if((setup->parity < 0) || (setup->parity > 1))
+    return 0;
+  
+  if((setup->synchronous < 0) || (setup->synchronous > 1))
+    return 0;
+  
+  return 1;
+}
+
+
 int aha152x_detect(Scsi_Host_Template * tpnt)
 {
-  int                 i, ok;
+  int                 i, j, ok;
 #if defined(AUTOCONF)
   aha152x_config      conf;
 #endif
-  int                 interrupt_level;
-  struct Scsi_Host    *hreg;
   
   tpnt->proc_dir = &proc_scsi_aha152x;
 
-  if(setup_called)
+  for(i=0; i<IRQS; i++)
+    aha152x_host[i] = (struct Scsi_Host *) NULL;
+  
+  if(setup_count)
     {
       printk("aha152x: processing commandline: ");
    
-#ifdef DEBUG_AHA152X
-      if(setup_called>6)
-#else
-      if(setup_called>5)
-#endif
+      for(i=0; i<setup_count; i++)
+        if(!aha152x_checksetup(&setup[i]))
 	{
-	  printk("\naha152x: %s\n", setup_str );
-#ifdef DEBUG_AHA152X
-	  printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>[,<RECONNECT>[,<PARITY>[,<DEBUG>]]]]]\n");
-#else
-	  printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>[,<RECONNECT>[,<PARITY>]]]]\n");
-#endif
-	  panic("aha152x panics in line %d", __LINE__);
+                printk("\naha152x: %s\n", setup[i].conf);
+                printk("aha152x: invalid line (controller=%d)\n", i+1);
 	}
 
-      port_base       = setup_portbase;
-      interrupt_level = setup_irq;
-      this_host       = setup_scsiid;
-      can_disconnect  = setup_reconnect;
-      can_doparity    = setup_doparity;
-#ifdef DEBUG_AHA152X
-      aha152x_debug   = setup_debug;
-#endif
-
-#ifndef PCMCIA
-      for( i=0; i<PORT_COUNT && (port_base != ports[i]); i++)
-	;
-
-      if(i==PORT_COUNT)
-	{
-	  printk("unknown portbase 0x%03x\n", port_base);
-	  panic("aha152x panics in line %d", __LINE__);
+      printk("ok\n");
 	}
-#endif
 
-      if(!aha152x_porttest(port_base))
+#ifdef SETUP0
+  if(setup_count<2)
 	{
-	  printk("portbase 0x%03x fails probe\n", port_base);
-#ifdef PCMCIA
-	  return 0;
-#else
-	  panic("aha152x panics in line %d", __LINE__);
-#endif
-	}
+      struct aha152x_setup override = SETUP0;
 
-#ifndef PCMCIA
-      i=0;
-      while(irqs[i] && (interrupt_level!=irqs[i]))
-	i++;
-      if(!irqs[i])
+      if(setup_count==0 || (override.io_port != setup[0].io_port))
+        if(!aha152x_checksetup(&override))
 	{
-	  printk("illegal IRQ %d\n", interrupt_level);
-	  panic("aha152x panics in line %d", __LINE__);
+                printk("\naha152x: SETUP0 (0x%x, %d, %d, %d, %d, %d) invalid\n",
+        	      override.io_port,
+        	      override.irq,
+        	      override.scsiid,
+        	      override.reconnect,
+        	      override.parity,
+        	      override.synchronous);
 	}
-#endif
-      
-      if( (this_host < 0) || (this_host > 7) )
-	{
-	  printk("illegal SCSI ID %d\n", this_host);
-	  panic("aha152x panics in line %d", __LINE__);
+        else
+          setup[setup_count++] = override;
 	}
+#endif
 
-      if( (can_disconnect < 0) || (can_disconnect > 1) )
+#ifdef SETUP1
+  if(setup_count<2)
 	{
-	  printk("reconnect %d should be 0 or 1\n", can_disconnect);
-	  panic("aha152x panics in line %d", __LINE__);
-	}
+      struct aha152x_setup override = SETUP1;
 
-      if( (can_doparity < 0) || (can_doparity > 1) )
+      if(setup_count==0 || (override.io_port != setup[0].io_port))
+        if(!aha152x_checksetup(&override))
 	{
-	  printk("parity %d should be 0 or 1\n", can_doparity);
-	  panic("aha152x panics in line %d", __LINE__);
-	}
-      printk("ok\n");
+                printk("\naha152x: SETUP1 (0x%x, %d, %d, %d, %d, %d) invalid\n",
+        	       override.io_port,
+        	       override.irq,
+        	       override.scsiid,
+        	       override.reconnect,
+        	       override.parity,
+        	       override.synchronous);
     }
   else
+          setup[setup_count++] = override;
+    }
+#endif
+  
+#if defined(AUTOCONF)
+  if(setup_count<2)
     {
 #if !defined(SKIP_BIOSTEST)
-      int j;
-
       ok=0;
-      for( i=0; i < ADDRESS_COUNT && !ok; i++)
-	for( j=0; (j < SIGNATURE_COUNT) && !ok; j++)
+      for(i=0; i < ADDRESS_COUNT && !ok; i++)
+            for(j=0; (j < SIGNATURE_COUNT) && !ok; j++)
 	  ok=!memcmp((void *) addresses[i]+signatures[j].sig_offset,
 		     (void *) signatures[j].signature,
 		     (int) signatures[j].sig_length);
 
-      if(!ok)
+      if(!ok && setup_count==0)
 	return 0;
 
       printk("aha152x: BIOS test: passed, ");
@@ -680,137 +718,149 @@
       printk("aha152x: ");
 #endif /* !SKIP_BIOSTEST */
  
-#if !defined(PORTBASE)
-      printk("porttest: ");
-      for( i=0; i<PORT_COUNT && !aha152x_porttest(ports[i]); i++)
-	;
-
-      if(i==PORT_COUNT)
-	{
-	  printk("failed\n");
-	  return 0;
+      for(i=0; i<PORT_COUNT && setup_count<2; i++)
+            {
+              if((setup_count==1) && (setup[0].io_port == ports[i]))
+                continue;
+
+              if(aha152x_porttest(ports[i]))
+	{
+                  setup[setup_count].io_port = ports[i];
+              
+                  conf.cf_port =
+        	        (GETPORT(ports[i]+O_PORTA)<<8) + GETPORT(ports[i]+O_PORTB);
+              
+                  setup[setup_count].irq         = IRQ_MIN + conf.cf_irq;
+                  setup[setup_count].scsiid      = conf.cf_id;
+                  setup[setup_count].reconnect   = conf.cf_tardisc;
+                  setup[setup_count].parity      = !conf.cf_parity;
+                  setup[setup_count].synchronous = 0 /* FIXME: conf.cf_syncneg */;
+                  setup[setup_count].debug       = DEBUG_DEFAULT;
+                  setup_count++;
+                }
 	}
-      else
-	port_base=ports[i];
-      printk("ok, ");
-#else
-      port_base=PORTBASE;
-#endif /* !PORTBASE */
 
-#if defined(AUTOCONF)
+      printk("auto configuration: ok, ");
+    }
+#endif
 
-      conf.cf_port = (GETPORT(PORTA)<<8) + GETPORT(PORTB);
+  printk("detection complete\n");
 
-      interrupt_level = irqs[conf.cf_irq];
-      this_host       = conf.cf_id;
-      can_disconnect  = conf.cf_tardisc;
-      can_doparity    = !conf.cf_parity;
+  for(i=0; i<setup_count; i++)
+    {
+      struct Scsi_Host        *shpnt;
 
-      printk("auto configuration: ok, ");
+      shpnt = aha152x_host[setup[i].irq-IRQ_MIN] =
+        scsi_register(tpnt, sizeof(struct aha152x_hostdata));
 
-#endif /* AUTOCONF */
+      shpnt->io_port                     = setup[i].io_port;
+      shpnt->n_io_port                   = IO_RANGE;
+      shpnt->irq                         = setup[i].irq;
 
-#if defined(IRQ)
-      interrupt_level = IRQ; 
-#endif
+      ISSUE_SC                           = (Scsi_Cmnd *) NULL;
+      CURRENT_SC                         = (Scsi_Cmnd *) NULL;
+      DISCONNECTED_SC                    = (Scsi_Cmnd *) NULL;
 
-#if defined(SCSI_ID)
-      this_host = SCSI_ID;
-#endif
+      HOSTDATA(shpnt)->reconnect         = setup[i].reconnect;
+      HOSTDATA(shpnt)->parity            = setup[i].parity;
+      HOSTDATA(shpnt)->synchronous       = setup[i].synchronous;
+      HOSTDATA(shpnt)->debug             = setup[i].debug;
 
-#if defined(RECONNECT)
-      can_disconnect=RECONNECT;
-#endif
+      HOSTDATA(shpnt)->aborting          = 0;
+      HOSTDATA(shpnt)->abortion_complete = 0;
+      HOSTDATA(shpnt)->abort_result      = 0;
+      HOSTDATA(shpnt)->commands          = 0;
 
-#if defined(PARITY)
-      can_doparity=PARITY;
-#endif
-    }
+      HOSTDATA(shpnt)->message_len       = 0;
 
-  printk("detection complete\n");
+      for(j=0; j<8; j++)
+        HOSTDATA(shpnt)->syncrate[j] = 0;
  
-  ok = request_irq(interrupt_level, aha152x_intr, SA_INTERRUPT, "aha152x");
+      ok = request_irq(setup[i].irq, aha152x_intr, SA_INTERRUPT, "aha152x");
   
   if(ok<0)
     {
       if(ok == -EINVAL)
 	{
-	   printk("aha152x: bad IRQ %d.\n", interrupt_level);
+              printk("aha152x%d: bad IRQ %d.\n", i, setup[i].irq);
 	   printk("         Contact author.\n");
 	}
       else
-	if( ok == -EBUSY)
-	  printk( "aha152x: IRQ %d already in use. Configure another.\n",
-		  interrupt_level);
+            if(ok == -EBUSY)
+              printk("aha152x%d: IRQ %d already in use. Configure another.\n",
+        	     i, setup[i].irq);
 	else
 	  {
-	    printk( "\naha152x: Unexpected error code on requesting IRQ %d.\n",
-		    interrupt_level);
+                printk("\naha152x%d: Unexpected error code on"
+        	       " requesting IRQ %d.\n", i, setup[i].irq);
 	    printk("         Contact author.\n");
 	  }
-      panic("aha152x: driver needs an IRQ.\n");
+          printk("aha152x: driver needs an IRQ.\n");
+          continue;
     }
 
-  SETPORT( SCSIID, this_host << 4 );
-  tpnt->this_id=this_host;
+      SETPORT(SCSIID, setup[i].scsiid << 4);
+      shpnt->this_id=setup[i].scsiid;
   
-  if(can_disconnect)
-    tpnt->can_queue=AHA152X_MAXQUEUE;
+      if(setup[i].reconnect)
+        shpnt->hostt->can_queue=AHA152X_MAXQUEUE;
 
   /* RESET OUT */
-  SETBITS(SCSISEQ, SCSIRSTO );
+      SETBITS(SCSISEQ, SCSIRSTO);
   do_pause(30);
-  CLRBITS(SCSISEQ, SCSIRSTO );
+      CLRBITS(SCSISEQ, SCSIRSTO);
   do_pause(60);
 
-  aha152x_reset(NULL);
+      aha152x_reset_ports(shpnt);
+      
+      printk("aha152x%d: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d,"
+             " reconnect=%s, parity=%s, synchronous=%s\n",
+      	     i,
+             shpnt->io_port,
+             shpnt->irq,
+             shpnt->this_id,
+             HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled",
+             HOSTDATA(shpnt)->parity ? "enabled" : "disabled",
+             HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled");
 
-  printk("aha152x: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d, reconnect=%s, parity=%s\n",
-	 port_base,
-	 interrupt_level,
-	 this_host,
-	 can_disconnect ? "enabled" : "disabled",
-	 can_doparity ? "enabled" : "disabled");
-
-  request_region(port_base, 0x20, "aha152x");        /* Register */
-
-  hreg = scsi_register(tpnt, 0);
-  hreg->io_port = port_base;
-  hreg->n_io_port = 0x20;
-  hreg->irq = interrupt_level;
+      request_region(shpnt->io_port, IO_RANGE, "aha152x");  /* Register */
   
   /* not expecting any interrupts */
   SETPORT(SIMODE0, 0);
   SETPORT(SIMODE1, 0);
 
-  SETBITS( DMACNTRL0, INTEN);
-  return 1;
+      SETBITS(DMACNTRL0, INTEN);
+    }
+  
+  return (setup_count>0);
 }
 
 /* 
  *  Queue a command and setup interrupts for a free bus.
  */
-int aha152x_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 {
+  struct Scsi_Host *shpnt = SCpnt->host;
   unsigned long flags;
 
 #if defined(DEBUG_RACE)
   enter_driver("queue");
 #else
 #if defined(DEBUG_QUEUE)
-  if(aha152x_debug & debug_queue)
+  if(HOSTDATA(shpnt)->debug & debug_queue)
     printk("aha152x: queue(), ");
 #endif
 #endif
 
 #if defined(DEBUG_QUEUE)
-  if(aha152x_debug & debug_queue)
+  if(HOSTDATA(shpnt)->debug & debug_queue)
   {
-    printk( "SCpnt (target = %d lun = %d cmnd = ", SCpnt->target, SCpnt->lun);
+      printk("SCpnt (target = %d lun = %d cmnd = ",
+             SCpnt->target, SCpnt->lun);
     print_command(SCpnt->cmnd);
-    printk( ", cmd_len=%d, pieces = %d size = %u), ",
-	    SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen );
-    disp_ports();
+      printk(", cmd_len=%d, pieces = %d size = %u), ",
+             SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen);
+      disp_ports(shpnt);
   }
 #endif
 
@@ -825,7 +875,8 @@
   SCpnt->SCp.phase = not_issued;
   if (SCpnt->use_sg)
     {
-      SCpnt->SCp.buffer           = (struct scatterlist *)SCpnt->request_buffer;
+      SCpnt->SCp.buffer =
+        (struct scatterlist *) SCpnt->request_buffer;
       SCpnt->SCp.ptr              = SCpnt->SCp.buffer->address;
       SCpnt->SCp.this_residual    = SCpnt->SCp.buffer->length;
       SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
@@ -846,21 +897,21 @@
   /* Turn led on, when this is the first command. */
   save_flags(flags);
   cli();
-  commands++;
-  if(commands==1)
-    SETPORT( PORTA, 1 );
+  HOSTDATA(shpnt)->commands++;
+  if(HOSTDATA(shpnt)->commands==1)
+    SETPORT(PORTA, 1);
 
 #if defined(DEBUG_QUEUES)
-  if(aha152x_debug & debug_queues)
-    printk("i+ (%d), ", commands );
+  if(HOSTDATA(shpnt)->debug & debug_queues)
+    printk("i+ (%d), ", HOSTDATA(shpnt)->commands);
 #endif
-  append_SC( &issue_SC, SCpnt);
+  append_SC(&ISSUE_SC, SCpnt);
   
   /* Enable bus free interrupt, when we aren't currently on the bus */
-  if(!current_SC)
+  if(!CURRENT_SC)
     {
-      SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-      SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
     }
   restore_flags(flags);
 
@@ -872,11 +923,11 @@
 }
 
 /*
- *  We only support command in interrupt-driven fashion
+ *  We only support commands in interrupt-driven fashion
  */
-int aha152x_command( Scsi_Cmnd *SCpnt )
+int aha152x_command(Scsi_Cmnd *SCpnt)
 {
-  printk( "aha152x: interrupt driven driver; use aha152x_queue()\n" );
+  printk("aha152x: interrupt driven driver; use aha152x_queue()\n");
   return -1;
 }
 
@@ -884,8 +935,9 @@
  *  Abort a queued command
  *  (commands that are on the bus can't be aborted easily)
  */
-int aha152x_abort( Scsi_Cmnd *SCpnt)
+int aha152x_abort(Scsi_Cmnd *SCpnt)
 {
+  struct Scsi_Host *shpnt = SCpnt->host;
   unsigned long flags;
   Scsi_Cmnd *ptr, *prev;
 
@@ -893,16 +945,15 @@
   cli();
 
 #if defined(DEBUG_ABORT)
-  if(aha152x_debug & debug_abort)
+  if(HOSTDATA(shpnt)->debug & debug_abort)
   { 
-    printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt );
-
-    show_queues();
+      printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt);
+      show_queues(shpnt);
   }
 #endif
 
   /* look for command in issue queue */
-  for( ptr=issue_SC, prev=NULL;
+  for(ptr=ISSUE_SC, prev=NULL;
        ptr && ptr!=SCpnt;
        prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
     ;
@@ -913,7 +964,7 @@
       if(prev)
 	prev->host_scribble = ptr->host_scribble;
       else
-	issue_SC = (Scsi_Cmnd *) ptr->host_scribble;
+        ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble;
       restore_flags(flags);
 
       ptr->host_scribble = NULL;
@@ -924,11 +975,11 @@
 
   /* if the bus is busy or a command is currently processed,
      we can't do anything more */
-  if ( TESTLO(SSTAT1, BUSFREE) || (current_SC && current_SC!=SCpnt))
+  if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC!=SCpnt))
     {
       /* fail abortion, if bus is busy */
 
-      if(!current_SC)
+      if(!CURRENT_SC)
 	printk("bus busy w/o current command, ");
  
       restore_flags(flags);
@@ -937,56 +988,58 @@
 
   /* bus is free */
 
-  if(current_SC)
+  if(CURRENT_SC)
   { 
     /* target entered bus free before COMMAND COMPLETE, nothing to abort */
     restore_flags(flags);
-    current_SC->result = DID_ERROR << 16;
-    current_SC->scsi_done(current_SC);
-    current_SC = (Scsi_Cmnd *) NULL;
+      CURRENT_SC->result = DID_ERROR << 16;
+      CURRENT_SC->scsi_done(CURRENT_SC);
+      CURRENT_SC = (Scsi_Cmnd *) NULL;
     return SCSI_ABORT_SUCCESS;
   }
 
   /* look for command in disconnected queue */
-  for( ptr=disconnected_SC, prev=NULL;
+  for(ptr=DISCONNECTED_SC, prev=NULL;
        ptr && ptr!=SCpnt;
        prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
     ;
 
   if(ptr)
-    if(!aborting)
+    if(!HOSTDATA(shpnt)->aborting)
       {
 	/* dequeue */
 	if(prev)
 	  prev->host_scribble = ptr->host_scribble;
 	else
-	  disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble;
+          DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;
   
 	/* set command current and initiate selection,
 	   let the interrupt routine take care of the abortion */
-	current_SC     = ptr;
+        CURRENT_SC     = ptr;
 	ptr->SCp.phase = in_selection|aborted;
-	SETPORT( SCSIID, (this_host << OID_) | current_SC->target );
+        SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
+        
+        ADDMSG(ABORT);
   
 	/* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
-	SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
-	SETPORT( SIMODE1, ENSELTIMO );
+        SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
+        SETPORT(SIMODE1, ENSELTIMO);
   
 	/* Enable SELECTION OUT sequence */
-	SETBITS(SCSISEQ, ENSELO | ENAUTOATNO );
+        SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
   
-	SETBITS( DMACNTRL0, INTEN );
-	abort_result=SCSI_ABORT_SUCCESS;
-	aborting++;
-	abortion_complete=0;
+        SETBITS(DMACNTRL0, INTEN);
+        HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS;
+        HOSTDATA(shpnt)->aborting++;
+        HOSTDATA(shpnt)->abortion_complete=0;
 
 	sti();  /* Hi Eric, guess what ;-) */
   
 	/* sleep until the abortion is complete */
-	while(!abortion_complete)
+        while(!HOSTDATA(shpnt)->abortion_complete)
 	  barrier();
-	aborting=0;
-	return abort_result;
+        HOSTDATA(shpnt)->aborting=0;
+        return HOSTDATA(shpnt)->abort_result;
       }
     else
       {
@@ -1004,7 +1057,7 @@
 /*
  *  Restore default values to the AIC-6260 registers and reset the fifos
  */
-static void aha152x_reset_ports(void)
+static void aha152x_reset_ports(struct Scsi_Host *shpnt)
 {
   /* disable interrupts */
   SETPORT(DMACNTRL0, RSTFIFO);
@@ -1012,7 +1065,7 @@
   SETPORT(SCSISEQ, 0);
 
   SETPORT(SXFRCTL1, 0);
-  SETPORT( SCSISIG, 0);
+  SETPORT(SCSISIG, 0);
   SETPORT(SCSIRATE, 0);
 
   /* clear all interrupt conditions */
@@ -1031,45 +1084,47 @@
   SETPORT(SXFRCTL0, CH1);
 
   /* enable interrupts */
-  SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-  SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+  SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+  SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 }
 
 /*
  *  Reset registers, reset a hanging bus and
  *  kill active and disconnected commands for target w/o soft reset
  */
-int aha152x_reset(Scsi_Cmnd * __unused)
+int aha152x_reset(Scsi_Cmnd *SCpnt)
 {
+  struct Scsi_Host *shpnt = SCpnt->host;
   unsigned long flags;
   Scsi_Cmnd *ptr, *prev, *next;
 
-  aha152x_reset_ports();
+  aha152x_reset_ports(shpnt);
 
   /* Reset, if bus hangs */
-  if( TESTLO( SSTAT1, BUSFREE ) )
+  if(TESTLO(SSTAT1, BUSFREE))
     {
-       CLRBITS( DMACNTRL0, INTEN );
+       CLRBITS(DMACNTRL0, INTEN);
 
 #if defined(DEBUG_RESET)
-  if(aha152x_debug & debug_reset)
+       if(HOSTDATA(shpnt)->debug & debug_reset)
   {
        printk("aha152x: reset(), bus not free: SCSI RESET OUT\n");
-       show_queues();
+           show_queues(shpnt);
   }
 #endif
 
-       if(current_SC && !current_SC->device->soft_reset)
+       ptr=CURRENT_SC;
+       if(ptr && !ptr->device->soft_reset)
 	 {
-	   current_SC->host_scribble = NULL;
-	   current_SC->result = DID_RESET << 16;
-	   current_SC->scsi_done(current_SC);
-	   current_SC=NULL;
+           ptr->host_scribble = NULL;
+           ptr->result = DID_RESET << 16;
+           ptr->scsi_done(CURRENT_SC);
+           CURRENT_SC=NULL;
 	 }
 
        save_flags(flags);
        cli();
-       prev=NULL; ptr=disconnected_SC;
+       prev=NULL; ptr=DISCONNECTED_SC;
        while(ptr)
 	 {
 	   if(!ptr->device->soft_reset)
@@ -1077,13 +1132,13 @@
 	       if(prev)
 		 prev->host_scribble = ptr->host_scribble;
 	       else
-		 disconnected_SC = (Scsi_Cmnd *) ptr->host_scribble;
+        	 DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;
 
 	       next = (Scsi_Cmnd *) ptr->host_scribble;
   
 	       ptr->host_scribble = NULL;
 	       ptr->result        = DID_RESET << 16;
-	       ptr->scsi_done(ptr);
+               ptr->scsi_done(ptr);
   
 	       ptr = next; 
 	     }
@@ -1095,11 +1150,11 @@
 	 }
        restore_flags(flags);
 
-#if defined( DEBUG_RESET )
-       if(aha152x_debug & debug_reset)
+#if defined(DEBUG_RESET)
+       if(HOSTDATA(shpnt)->debug & debug_reset)
        {
 	 printk("commands on targets w/ soft-resets:\n");
-	 show_queues();
+           show_queues(shpnt);
        }
 #endif
 
@@ -1109,10 +1164,10 @@
        SETPORT(SCSISEQ, 0);
        do_pause(60);
 
-       SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-       SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+       SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+       SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
-       SETPORT( DMACNTRL0, INTEN );
+       SETPORT(DMACNTRL0, INTEN);
     }
 
   return SCSI_RESET_SUCCESS;
@@ -1121,14 +1176,13 @@
 /*
  * Return the "logical geometry"
  */
-int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array )
+int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
 {
   int size = disk->capacity;
 
 #if defined(DEBUG_BIOSPARAM)
-  if(aha152x_debug & debug_biosparam)
-    printk("aha152x_biosparam: dev=%s, size=%d, ",
-	   kdevname(dev), size);
+  if(HOSTDATA(shpnt)->debug & debug_biosparam)
+    printk("aha152x_biosparam: dev=%s, size=%d, ", kdevname(dev), size);
 #endif
   
 /* I took this from other SCSI drivers, since it provides
@@ -1138,7 +1192,7 @@
   info_array[2]=size>>11;
 
 #if defined(DEBUG_BIOSPARAM)
-  if(aha152x_debug & debug_biosparam)
+  if(HOSTDATA(shpnt)->debug & debug_biosparam)
   {
     printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
 	   info_array[0], info_array[1], info_array[2]);
@@ -1152,54 +1206,54 @@
 /*
  *  Internal done function
  */
-void aha152x_done( int error )
+void aha152x_done(struct Scsi_Host *shpnt, int error)
 {
   unsigned long flags;
   Scsi_Cmnd *done_SC;
 
 #if defined(DEBUG_DONE)
-  if(aha152x_debug & debug_done)
+  if(HOSTDATA(shpnt)->debug & debug_done)
   {
     printk("\naha152x: done(), ");
-    disp_ports();
+    disp_ports(shpnt);
   }
 #endif
 
-  if (current_SC)
+  if (CURRENT_SC)
     {
 #if defined(DEBUG_DONE)
-      if(aha152x_debug & debug_done)
+      if(HOSTDATA(shpnt)->debug & debug_done)
 	printk("done(%x), ", error);
 #endif
 
       save_flags(flags);
       cli();
 
-      done_SC = current_SC;
-      current_SC = NULL;
+      done_SC = CURRENT_SC;
+      CURRENT_SC = NULL;
 
       /* turn led off, when no commands are in the driver */
-      commands--;
-      if(!commands)
-	SETPORT( PORTA, 0 );                                  /* turn led off */
+      HOSTDATA(shpnt)->commands--;
+      if(!HOSTDATA(shpnt)->commands)
+        SETPORT(PORTA, 0);                                  /* turn led off */
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues) 
-	printk("ok (%d), ", commands);
+      if(HOSTDATA(shpnt)->debug & debug_queues) 
+        printk("ok (%d), ", HOSTDATA(shpnt)->commands);
 #endif
       restore_flags(flags);
 
-      SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-      SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
 #if defined(DEBUG_PHASES)
-      if(aha152x_debug & debug_phases)
+      if(HOSTDATA(shpnt)->debug & debug_phases)
 	printk("BUS FREE loop, ");
 #endif
-      while( TESTLO( SSTAT1, BUSFREE ) )
+      while(TESTLO(SSTAT1, BUSFREE))
 	;
 #if defined(DEBUG_PHASES)
-      if(aha152x_debug & debug_phases)
+      if(HOSTDATA(shpnt)->debug & debug_phases)
 	printk("BUS FREE\n");
 #endif
 
@@ -1207,27 +1261,28 @@
       if(done_SC->scsi_done)
 	{
 #if defined(DEBUG_DONE)
-	  if(aha152x_debug & debug_done)
+          if(HOSTDATA(shpnt)->debug & debug_done)
 	    printk("calling scsi_done, ");
 #endif
-	  done_SC->scsi_done( done_SC );
+          done_SC->scsi_done(done_SC);
 #if defined(DEBUG_DONE)
-	  if(aha152x_debug & debug_done)
+          if(HOSTDATA(shpnt)->debug & debug_done)
 	    printk("done returned, ");
 #endif
 	}
       else
-	panic( "aha152x: current_SC->scsi_done() == NULL" );
+        panic("aha152x: current_SC->scsi_done() == NULL");
     }
   else
-    aha152x_panic( "done() called outside of command" );
+    aha152x_panic(shpnt, "done() called outside of command");
 }
 
 /*
  * Interrupts handler (main routine of the driver)
  */
-void aha152x_intr( int irqno, struct pt_regs * regs )
+void aha152x_intr(int irqno, struct pt_regs * regs)
 {
+  struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];
   unsigned int flags;
   int done=0, phase;
 
@@ -1235,7 +1290,7 @@
   enter_driver("intr");
 #else
 #if defined(DEBUG_INTR)
-  if(aha152x_debug & debug_intr)
+  if(HOSTDATA(shpnt)->debug & debug_intr)
     printk("\naha152x: intr(), ");
 #endif
 #endif
@@ -1244,74 +1299,76 @@
      INTEN has to be restored, when we're ready to leave
      intr(). To avoid race conditions we have to return
      immediately afterwards. */
-  CLRBITS( DMACNTRL0, INTEN);
+  CLRBITS(DMACNTRL0, INTEN);
   sti();  /* Yes, sti() really needs to be here */
 
   /* disconnected target is trying to reconnect.
      Only possible, if we have disconnected nexuses and
      nothing is occupying the bus.
   */
-  if( TESTHI( SSTAT0, SELDI ) &&
-      disconnected_SC &&
-      ( !current_SC || ( current_SC->SCp.phase & in_selection ) )
+  if(TESTHI(SSTAT0, SELDI) &&
+      DISCONNECTED_SC &&
+      (!CURRENT_SC || (CURRENT_SC->SCp.phase & in_selection))
     )
     {
       int identify_msg, target, i;
 
       /* Avoid conflicts when a target reconnects
 	 while we are trying to connect to another. */
-      if(current_SC)
+      if(CURRENT_SC)
 	{
 #if defined(DEBUG_QUEUES)
-	  if(aha152x_debug & debug_queues)
+          if(HOSTDATA(shpnt)->debug & debug_queues)
 	  printk("i+, ");
 #endif
 	  save_flags(flags);
 	  cli();
-	  append_SC( &issue_SC, current_SC);
-	  current_SC=NULL;
+          append_SC(&ISSUE_SC, CURRENT_SC);
+          CURRENT_SC=NULL;
 	  restore_flags(flags);
 	}
 
       /* disable sequences */
-      SETPORT( SCSISEQ, 0 );
-      SETPORT( SSTAT0, CLRSELDI );
-      SETPORT( SSTAT1, CLRBUSFREE );
+      SETPORT(SCSISEQ, 0);
+      SETPORT(SSTAT0, CLRSELDI);
+      SETPORT(SSTAT1, CLRBUSFREE);
 
 #if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_queues|debug_phases))
+      if(HOSTDATA(shpnt)->debug & (debug_queues|debug_phases))
 	printk("reselected, ");
 #endif
 
-      i = GETPORT(SELID) & ~(1 << this_host);
+      i = GETPORT(SELID) & ~(1 << shpnt->this_id);
       target=0;
       if(i)
-	for( ; (i & 1)==0; target++, i>>=1)
+        for(; (i & 1)==0; target++, i>>=1)
 	  ;
       else
-	aha152x_panic("reconnecting target unknown");
+        aha152x_panic(shpnt, "reconnecting target unknown");
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues)
-	printk("SELID=%02x, target=%d, ", GETPORT(SELID), target );
+      if(HOSTDATA(shpnt)->debug & debug_queues)
+        printk("SELID=%02x, target=%d, ", GETPORT(SELID), target);
 #endif
-      SETPORT( SCSIID, (this_host << OID_) | target );
-      SETPORT( SCSISEQ, ENRESELI );
+      SETPORT(SCSIID, (shpnt->this_id << OID_) | target);
+      SETPORT(SCSISEQ, ENRESELI);
+
+      if(TESTLO(SSTAT0, SELDI))
+        aha152x_panic(shpnt, "RESELI failed");
 
-      if(TESTLO( SSTAT0, SELDI ))
-	aha152x_panic("RESELI failed");
+      SETPORT(SCSIRATE, HOSTDATA(shpnt)->syncrate[target]&0x7f);
 
-      SETPORT( SCSISIG, P_MSGI );
+      SETPORT(SCSISIG, P_MSGI);
 
       /* Get identify message */
-      if((i=getphase())!=P_MSGI)
+      if((i=getphase(shpnt))!=P_MSGI)
 	{
 	  printk("target doesn't enter MSGI to identify (phase=%02x)\n", i);
-	  aha152x_panic("unknown lun");
+          aha152x_panic(shpnt, "unknown lun");
 	}
-      SETPORT( SCSISEQ, 0 );
+      SETPORT(SCSISEQ, 0);
 
-      SETPORT( SXFRCTL0, CH1);
+      SETPORT(SXFRCTL0, CH1);
 
       identify_msg = GETPORT(SCSIBUS);
 
@@ -1319,87 +1376,87 @@
 	{
 	  printk("target=%d, inbound message (%02x) != IDENTIFY\n",
 		 target, identify_msg);
-	  aha152x_panic("unknown lun");
+          aha152x_panic(shpnt, "unknown lun");
 	}
 
-      make_acklow();
-      getphase();
+      make_acklow(shpnt);
+      getphase(shpnt);
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues)
-	printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f );
+      if(HOSTDATA(shpnt)->debug & debug_queues)
+        printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f);
 #endif
 
       save_flags(flags);
       cli();
 
 #if defined(DEBUG_QUEUES)
-      if(aha152x_debug & debug_queues)
+      if(HOSTDATA(shpnt)->debug & debug_queues)
 	printk("d-, ");
 #endif
-      current_SC = remove_SC( &disconnected_SC,
+      CURRENT_SC = remove_SC(&DISCONNECTED_SC,
 			      target,
-			      identify_msg & 0x3f );
+        		     identify_msg & 0x3f);
 
-      if(!current_SC)
+      if(!CURRENT_SC)
 	{
-	  printk("lun=%d, ", identify_msg & 0x3f );
-	  aha152x_panic("no disconnected command for that lun");
+          printk("lun=%d, ", identify_msg & 0x3f);
+          aha152x_panic(shpnt, "no disconnected command for that lun");
 	}
 
-      current_SC->SCp.phase &= ~disconnected;
+      CURRENT_SC->SCp.phase &= ~disconnected;
       restore_flags(flags);
 
-      SETPORT( SIMODE0, 0 );
-      SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+      SETPORT(SIMODE0, 0);
+      SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 #if defined(DEBUG_RACE)
       leave_driver("(reselected) intr");
 #endif
-      SETBITS( DMACNTRL0, INTEN);
+      SETBITS(DMACNTRL0, INTEN);
       return;
     }
   
   /* Check, if we aren't busy with a command */
-  if(!current_SC)
+  if(!CURRENT_SC)
     {
       /* bus is free to issue a queued command */
-      if(TESTHI( SSTAT1, BUSFREE) && issue_SC)
+      if(TESTHI(SSTAT1, BUSFREE) && ISSUE_SC)
 	{
 	  save_flags(flags);
 	  cli();
 #if defined(DEBUG_QUEUES)
-	  if(aha152x_debug & debug_queues)
+          if(HOSTDATA(shpnt)->debug & debug_queues)
 	    printk("i-, ");
 #endif
-	  current_SC = remove_first_SC( &issue_SC );
+          CURRENT_SC = remove_first_SC(&ISSUE_SC);
 	  restore_flags(flags);
 
 #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-	  if(aha152x_debug & (debug_intr|debug_selection|debug_phases))
+          if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))
 	    printk("issuing command, ");
 #endif
-	  current_SC->SCp.phase = in_selection;
+          CURRENT_SC->SCp.phase = in_selection;
 
-  #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-	  if(aha152x_debug & (debug_intr|debug_selection|debug_phases))
-	    printk("selecting %d, ", current_SC->target); 
-  #endif
-	  SETPORT( SCSIID, (this_host << OID_) | current_SC->target );
+#if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
+          if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))
+            printk("selecting %d, ", CURRENT_SC->target); 
+#endif
+          SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
 
 	  /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */
-	  SETPORT( SXFRCTL1, can_doparity ? (ENSPCHK|ENSTIMER) : ENSTIMER);
+          SETPORT(SXFRCTL1, HOSTDATA(shpnt)->parity ? (ENSPCHK|ENSTIMER) : ENSTIMER);
 
 	  /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
-	  SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
-	  SETPORT( SIMODE1, ENSELTIMO );
+          SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
+          SETPORT(SIMODE1, ENSELTIMO);
 
 	  /* Enable SELECTION OUT sequence */
-	  SETBITS(SCSISEQ, ENSELO | ENAUTOATNO );
+          SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
 	
-  #if defined(DEBUG_RACE)
+#if defined(DEBUG_RACE)
 	  leave_driver("(selecting) intr");
-  #endif
-	  SETBITS( DMACNTRL0, INTEN );
+#endif
+          SETBITS(DMACNTRL0, INTEN);
 	  return;
 	}
 
@@ -1411,200 +1468,229 @@
   /* the bus is busy with something */
 
 #if defined(DEBUG_INTR)
-  if(aha152x_debug & debug_intr)
-    disp_ports();
+  if(HOSTDATA(shpnt)->debug & debug_intr)
+    disp_ports(shpnt);
 #endif
 
   /* we are waiting for the result of a selection attempt */
-  if(current_SC->SCp.phase & in_selection)
+  if(CURRENT_SC->SCp.phase & in_selection)
     {
-      if( TESTLO( SSTAT1, SELTO ) )
+      if(TESTLO(SSTAT1, SELTO))
 	/* no timeout */
-	if( TESTHI( SSTAT0, SELDO ) )
+        if(TESTHI(SSTAT0, SELDO))
 	  {
 	    /* clear BUS FREE interrupt */
-	    SETPORT( SSTAT1, CLRBUSFREE);
+            SETPORT(SSTAT1, CLRBUSFREE);
 
 	    /* Disable SELECTION OUT sequence */
-	    CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );
+            CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO);
 
 	    /* Disable SELECTION OUT DONE interrupt */
 	    CLRBITS(SIMODE0, ENSELDO);
 	    CLRBITS(SIMODE1, ENSELTIMO);
 
-	    if( TESTLO(SSTAT0, SELDO) )
+            if(TESTLO(SSTAT0, SELDO))
 	      {
 		printk("aha152x: passing bus free condition\n");
 
 #if defined(DEBUG_RACE)
 		leave_driver("(passing bus free) intr");
 #endif
-		SETBITS( DMACNTRL0, INTEN);
+        	SETBITS(DMACNTRL0, INTEN);
 
-		if(current_SC->SCp.phase & aborted)
+        	if(CURRENT_SC->SCp.phase & aborted)
 		  {
-		    abort_result=SCSI_ABORT_ERROR;
-		    abortion_complete++;
+        	    HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR;
+        	    HOSTDATA(shpnt)->abortion_complete++;
 		  }
 
-		aha152x_done( DID_NO_CONNECT << 16 );
+        	aha152x_done(shpnt, DID_NO_CONNECT << 16);
 		return;
 	      }
 #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-	    if(aha152x_debug & (debug_selection|debug_phases))
+            if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases))
 	      printk("SELDO (SELID=%x), ", GETPORT(SELID));
 #endif
 
 	    /* selection was done */
-	    SETPORT( SSTAT0, CLRSELDO );
+            SETPORT(SSTAT0, CLRSELDO);
 
 #if defined(DEBUG_ABORT)
-	    if((aha152x_debug & debug_abort) && (current_SC->SCp.phase & aborted))
+            if((HOSTDATA(shpnt)->debug & debug_abort) && (CURRENT_SC->SCp.phase & aborted))
 	      printk("(ABORT) target selected, ");
 #endif
 
-	    current_SC->SCp.phase &= ~in_selection;
-	    current_SC->SCp.phase |= in_other;
+            CURRENT_SC->SCp.phase &= ~in_selection;
+            CURRENT_SC->SCp.phase |= in_other;
+
+            ADDMSG(IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun));
+
+            if(!(SYNCRATE&0x80) && HOSTDATA(shpnt)->synchronous)
+              {
+                ADDMSG(EXTENDED_MESSAGE);
+                ADDMSG(3);
+                ADDMSG(EXTENDED_SDTR);
+        	ADDMSG(50);
+                ADDMSG(8);
+
+                printk("outbound SDTR: ");
+                print_msg(&MSG(MSGLEN-5));
+
+        	SYNCRATE=0x80;
+                CURRENT_SC->SCp.phase |= in_sync;
+              }
 
 #if defined(DEBUG_RACE)
 	    leave_driver("(SELDO) intr");
 #endif
+            SETPORT(SCSIRATE, SYNCRATE&0x7f);
 
-	    SETPORT( SCSISIG, P_MSGO );
+            SETPORT(SCSISIG, P_MSGO);
 
-	    SETPORT( SIMODE0, 0 );
-	    SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
-	    SETBITS( DMACNTRL0, INTEN);
+            SETPORT(SIMODE0, 0);
+            SETPORT(SIMODE1, ENREQINIT|ENBUSFREE);
+            SETBITS(DMACNTRL0, INTEN);
 	    return;
 	  }
 	else
-	  aha152x_panic("neither timeout nor selection\007");
+          aha152x_panic(shpnt, "neither timeout nor selection\007");
       else
 	{
 #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-	  if(aha152x_debug & (debug_selection|debug_phases))
+          if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases))
 	  printk("SELTO, ");
 #endif
 	  /* end selection attempt */
-	  CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO );
+          CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO);
 
 	  /* timeout */
-	  SETPORT( SSTAT1, CLRSELTIMO );
+          SETPORT(SSTAT1, CLRSELTIMO);
 
-	  SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-	  SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
-	  SETBITS( DMACNTRL0, INTEN );
+          SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+          SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+          SETBITS(DMACNTRL0, INTEN);
 #if defined(DEBUG_RACE)
 	  leave_driver("(SELTO) intr");
 #endif
 
-	  if(current_SC->SCp.phase & aborted)
+          if(CURRENT_SC->SCp.phase & aborted)
 	    {
 #if defined(DEBUG_ABORT)
-	      if(aha152x_debug & debug_abort)
+              if(HOSTDATA(shpnt)->debug & debug_abort)
 		printk("(ABORT) selection timeout, ");
 #endif
-	      abort_result=SCSI_ABORT_ERROR;
-	      abortion_complete++;
+              HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR;
+              HOSTDATA(shpnt)->abortion_complete++;
 	    }
 
-	  if( TESTLO( SSTAT0, SELINGO ) )
+          if(TESTLO(SSTAT0, SELINGO))
 	    /* ARBITRATION not won */
-	    aha152x_done( DID_BUS_BUSY << 16 );
+            aha152x_done(shpnt, DID_BUS_BUSY << 16);
 	  else
 	    /* ARBITRATION won, but SELECTION failed */
-	    aha152x_done( DID_NO_CONNECT << 16 );
+            aha152x_done(shpnt, DID_NO_CONNECT << 16);
+
 	  return;
 	}
     }
 
   /* enable interrupt, when target leaves current phase */
-  phase = getphase();
+  phase = getphase(shpnt);
   if(!(phase & ~P_MASK))                                      /* "real" phase */
     SETPORT(SCSISIG, phase);
   SETPORT(SSTAT1, CLRPHASECHG);
-  current_SC->SCp.phase =
-    (current_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16 );
+  CURRENT_SC->SCp.phase =
+    (CURRENT_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16);
 
   /* information transfer phase */
-  switch( phase )
+  switch(phase)
     {
     case P_MSGO:                                               /* MESSAGE OUT */
       {
-	unsigned char message;
+        int i, identify=0, abort=0;
 
 #if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES)
-	if(aha152x_debug & (debug_intr|debug_msgo|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgo|debug_phases))
 	  printk("MESSAGE OUT, ");
 #endif
-
-	if( current_SC->SCp.phase & aborted )
+        if(MSGLEN==0)
 	  {
-#if defined(DEBUG_MSGO) || defined(DEBUG_ABORT)
-	    if(aha152x_debug & (debug_msgo|debug_abort))
-	      printk("ABORT, ");
+            ADDMSG(MESSAGE_REJECT);
+#if defined(DEBUG_MSGO)
+            if(HOSTDATA(shpnt)->debug & debug_msgo)
+              printk("unexpected MSGO; rejecting, ");
 #endif
-	    message=ABORT;
 	  }
-	else
-	  /* If we didn't identify yet, do it. Otherwise there's nothing to do,
-	     but reject (probably we got an message before, that we have to
-	     reject (SDTR, WDTR, etc.) */
-	  if( !(current_SC->SCp.phase & sent_ident))
-	    {
-	      message=IDENTIFY(can_disconnect,current_SC->lun);
+        
+        
+        CLRBITS(SXFRCTL0, ENDMA);
+        
+        SETPORT(SIMODE0, 0);
+        SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE);
+        
+        /* wait for data latch to become ready or a phase change */
+        while(TESTLO(DMASTAT, INTSTAT))
+          ;
+        
 #if defined(DEBUG_MSGO)
-	      if(aha152x_debug & debug_msgo)
-		printk("IDENTIFY (reconnect=%s;lun=%d), ", 
-			can_disconnect ? "enabled" : "disabled", current_SC->lun);
-#endif
+        if(HOSTDATA(shpnt)->debug & debug_msgo)
+          {
+            int i;
+            
+            printk("messages (");
+            for(i=0; i<MSGLEN; i+=print_msg(&MSG(i)), printk(" "))
+              ;
+            printk("), ");
 	    }
-	  else
+#endif
+        
+        for(i=0; i<MSGLEN && TESTLO(SSTAT1, PHASEMIS); i++)
 	    {
-	      message=MESSAGE_REJECT;
 #if defined(DEBUG_MSGO)
-	      if(aha152x_debug & debug_msgo)
-		printk("REJECT, ");
+            if(HOSTDATA(shpnt)->debug & debug_msgo)
+              printk("%x ", MSG(i));
 #endif
+            if(i==MSGLEN-1)
+              {
+                /* Leave MESSAGE OUT after transfer */
+                SETPORT(SSTAT1, CLRATNO);
 	    }
 	  
-	CLRBITS( SXFRCTL0, ENDMA);
+            SETPORT(SCSIDAT, MSG(i));
 
-	SETPORT( SIMODE0, 0 );
-	SETPORT( SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE );
+            make_acklow(shpnt);
+            getphase(shpnt);
 
-	/* wait for data latch to become ready or a phase change */
-	while( TESTLO( DMASTAT, INTSTAT ) )
-	  ;
+            if(MSG(i)==IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun))
+              identify++;
 
-	if( TESTHI( SSTAT1, PHASEMIS ) )
-	  aha152x_panic("unable to send message");
+            if(MSG(i)==ABORT)
+              abort++;
 
-	/* Leave MESSAGE OUT after transfer */
-	SETPORT( SSTAT1, CLRATNO);
+          }
 
-	SETPORT( SCSIDAT, message );
+        MSGLEN=0;
 
-	make_acklow();
-	getphase();
+        if(MSGLEN>0)
+          aha152x_panic(shpnt, "oops, MSGLEN>0 !?");
 
-	if(message==IDENTIFY(can_disconnect,current_SC->lun))
-	  current_SC->SCp.phase |= sent_ident;
+        if(identify)
+          CURRENT_SC->SCp.phase |= sent_ident;
 
-	if(message==ABORT)
+        if(abort)
 	  {
 	    /* revive abort(); abort() enables interrupts */
-	    abort_result=SCSI_ABORT_SUCCESS;
-	    abortion_complete++;
+            HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS;
+            HOSTDATA(shpnt)->abortion_complete++;
 
-	    current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
+            CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
 
 	    /* exit */
-	    SETBITS( DMACNTRL0, INTEN );
+            SETBITS(DMACNTRL0, INTEN);
 #if defined(DEBUG_RACE)
 	    leave_driver("(ABORT) intr");
 #endif
-	    aha152x_done(DID_ABORT<<16);
+            aha152x_done(shpnt, DID_ABORT<<16);
 	    return;
 	  }
       }
@@ -1612,291 +1698,263 @@
 
     case P_CMD:                                          /* COMMAND phase */
 #if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_intr|debug_cmd|debug_phases))
+      if(HOSTDATA(shpnt)->debug & (debug_intr|debug_cmd|debug_phases))
 	printk("COMMAND, ");
 #endif
-      if( !(current_SC->SCp.sent_command) )
+      if(!(CURRENT_SC->SCp.sent_command))
 	{
-	  if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
-	    printk("aha152x: P_CMD: %d(%d) bytes left in FIFO, resetting\n",
-		   GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
-
-	  /* reset fifo and enable writes */
-	  SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
-	  SETPORT(DMACNTRL0, ENDMA|WRITE_READ);
-
-	  /* clear transfer count and scsi fifo */
-	  SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 );
-	  SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
-  
-	  /* missing phase raises INTSTAT */
-	  SETPORT( SIMODE0, 0 );
-	  SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
-  
-#if defined(DEBUG_CMD)
-	  if(aha152x_debug & debug_cmd)
-	    printk("waiting, ");
-#endif
-	  /* wait for FIFO to get empty */
-	  while( TESTLO ( DMASTAT, DFIFOEMP|INTSTAT ) )
+          int i;
+
+          CLRBITS(SXFRCTL0, ENDMA);
+
+          SETPORT(SIMODE0, 0);
+          SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE);
+  
+          /* wait for data latch to become ready or a phase change */
+          while(TESTLO(DMASTAT, INTSTAT))
 	    ;
   
-	  if( TESTHI( SSTAT1, PHASEMIS ) )
-	    aha152x_panic("target left COMMAND phase");
-
-#if defined(DEBUG_CMD)
-	  if(aha152x_debug & debug_cmd)
+          for(i=0; i<CURRENT_SC->cmd_len && TESTLO(SSTAT1, PHASEMIS); i++)
 	  {
-	    printk("DFIFOEMP, outsw (%d bytes, %d words), ",
-		   current_SC->cmd_len, current_SC->cmd_len >> 1 );
-	    disp_ports();
-	  }
-#endif
-  
-	  outsw( DATAPORT, &current_SC->cmnd, current_SC->cmd_len >> 1 );
+              SETPORT(SCSIDAT, CURRENT_SC->cmnd[i]);
 
-#if defined(DEBUG_CMD)
-	  if(aha152x_debug & debug_cmd)
-	  {
-	    printk("FCNT=%d, STCNT=%d, ", GETPORT(FIFOSTAT), GETSTCNT() );
-	    disp_ports();
+              make_acklow(shpnt);
+              getphase(shpnt);
 	  }
-#endif
-
-#if defined(DEBUG_CMD)
-	  if(aha152x_debug & debug_cmd)
-	    printk("waiting for SEMPTY, ");
-#endif
-
-	  /* wait for SCSI FIFO to get empty.
-	     very important to send complete commands. */
-	  while( TESTLO ( SSTAT2, SEMPTY ) )
-	    ;
 
-#if defined(DEBUG_CMD)
-	  if(aha152x_debug & debug_cmd)
-	    printk("SEMPTY, ");
-#endif
-
-	  CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
-	  /* transfer can be considered ended, when SCSIEN reads back zero */
-	  while( TESTHI( SXFRCTL0, SCSIEN ) )
-	    ;
-
-#if defined(DEBUG_CMD)
-	  if(aha152x_debug & debug_cmd)
-	    printk("!SEMPTY, ");
-#endif
-
-	  CLRBITS(DMACNTRL0, ENDMA);
-
-#if defined(DEBUG_CMD) || defined(DEBUG_INTR)
-	  if(debug_cmd & debug_intr)
-	    printk("sent %d/%d command bytes, ", GETSTCNT(),
-		   current_SC->cmd_len);
-#endif
+          if(i<CURRENT_SC->cmd_len && TESTHI(SSTAT1, PHASEMIS))
+            aha152x_panic(shpnt, "target left COMMAND");
 
+          CURRENT_SC->SCp.sent_command++;
 	}
       else
-	aha152x_panic("Nothing to sent while in COMMAND OUT");
+        aha152x_panic(shpnt, "Nothing to send while in COMMAND");
       break;
 
     case P_MSGI:                                          /* MESSAGE IN phase */
+      {
+        int start_sync=0;
+        
 #if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_intr|debug_msgi|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgi|debug_phases))
 	printk("MESSAGE IN, ");
 #endif
-      SETPORT( SXFRCTL0, CH1);
+        SETPORT(SXFRCTL0, CH1);
 
-      SETPORT( SIMODE0, 0);
-      SETPORT( SIMODE1, ENBUSFREE);
+        SETPORT(SIMODE0, 0);
+        SETPORT(SIMODE1, ENBUSFREE);
   
-      while( phase == P_MSGI ) 
+        while(phase == P_MSGI) 
 	{
-	  current_SC->SCp.Message = GETPORT( SCSIBUS );
-	  switch(current_SC->SCp.Message)
+            CURRENT_SC->SCp.Message = GETPORT(SCSIDAT);
+            switch(CURRENT_SC->SCp.Message)
 	    {
 	    case DISCONNECT:
 #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-	      if(aha152x_debug & (debug_msgi|debug_phases))
+        	if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases))
 		printk("target disconnected, ");
 #endif
-	      current_SC->SCp.Message = 0;
-	      current_SC->SCp.phase   |= disconnected;
-	      if(!can_disconnect)
-		aha152x_panic("target was not allowed to disconnect");
+        	CURRENT_SC->SCp.Message = 0;
+        	CURRENT_SC->SCp.phase   |= disconnected;
+        	if(!HOSTDATA(shpnt)->reconnect)
+        	  aha152x_panic(shpnt, "target was not allowed to disconnect");
 	      break;
 	
 	    case COMMAND_COMPLETE:
 #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-	      if(aha152x_debug & (debug_msgi|debug_phases))
-		printk("inbound message ( COMMAND COMPLETE ), ");
+        	if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases))
+        	  printk("inbound message (COMMAND COMPLETE), ");
 #endif
 	      done++;
 	      break;
 
 	    case MESSAGE_REJECT:
+        	if(CURRENT_SC->SCp.phase & in_sync)
+        	  { 
+        	    CURRENT_SC->SCp.phase &= ~in_sync;
+        	    SYNCRATE=0x80;
+        	    printk("synchronous rejected, ");
+        	  }
+        	else
+        	  printk("inbound message (MESSAGE REJECT), ");
 #if defined(DEBUG_MSGI)
-	      if(aha152x_debug & debug_msgi)
-		printk("inbound message ( MESSAGE REJECT ), ");
+        	if(HOSTDATA(shpnt)->debug & debug_msgi)
+        	  printk("inbound message (MESSAGE REJECT), ");
 #endif
 	      break;
 
 	    case SAVE_POINTERS:
 #if defined(DEBUG_MSGI)
-	      if(aha152x_debug & debug_msgi)
-		printk("inbound message ( SAVE DATA POINTERS ), ");
+        	if(HOSTDATA(shpnt)->debug & debug_msgi)
+        	  printk("inbound message (SAVE DATA POINTERS), ");
 #endif
 	      break;
 
 	    case EXTENDED_MESSAGE:
 	      { 
-		int           i, code;
+        	  char buffer[16];
+        	  int  i;
 
 #if defined(DEBUG_MSGI)
-		if(aha152x_debug & debug_msgi)
-		  printk("inbound message ( EXTENDED MESSAGE ), ");
+        	  if(HOSTDATA(shpnt)->debug & debug_msgi)
+        	    printk("inbound message (EXTENDED MESSAGE), ");
 #endif
-		make_acklow();
-		if(getphase()!=P_MSGI)
+        	  make_acklow(shpnt);
+        	  if(getphase(shpnt)!=P_MSGI)
 		  break;
   
-		i=GETPORT(SCSIBUS);
+        	  buffer[0]=EXTENDED_MESSAGE;
+        	  buffer[1]=GETPORT(SCSIDAT);
+        	  
+        	  for(i=0; i<buffer[1] &&
+        	      (make_acklow(shpnt), getphase(shpnt)==P_MSGI); i++)
+        	    buffer[2+i]=GETPORT(SCSIDAT);
 
 #if defined(DEBUG_MSGI)
-		if(aha152x_debug & debug_msgi)
-		  printk("length (%d), code ( ", i);
+        	  if(HOSTDATA(shpnt)->debug & debug_msgi)
+        	    print_msg(buffer);
 #endif
 
-		make_acklow();
-		if(getphase()!=P_MSGI)
+        	  switch(buffer [2])
+        	    {
+        	    case EXTENDED_SDTR:
+        	      {
+        		long ticks;
+        		
+        		if(buffer[1]!=3)
+        		  aha152x_panic(shpnt, "SDTR message length != 3");
+        		
+        		if(!HOSTDATA(shpnt)->synchronous)
 		  break;
 
-		code = GETPORT(SCSIBUS);
+        		printk("inbound SDTR: "); print_msg(buffer);
+        		
+        		ticks=(buffer[3]*4+49)/50;
 
-		switch( code )
+        		if(CURRENT_SC->SCp.phase & in_sync)
 		  {
-		  case 0x00:
-#if defined(DEBUG_MSGI)
-		    if(aha152x_debug & debug_msgi)
-		      printk("MODIFY DATA POINTER ");
-#endif
-		    SETPORT(SCSISIG, P_MSGI|ATNO);
-		    break;
-		  case 0x01:
-#if defined(DEBUG_MSGI)
-		    if(aha152x_debug & debug_msgi)
-		      printk("SYNCHRONOUS DATA TRANSFER REQUEST ");
-#endif
-		    SETPORT(SCSISIG, P_MSGI|ATNO);
-		    break;
-		  case 0x02:
-#if defined(DEBUG_MSGI)
-		    if(aha152x_debug & debug_msgi)
-		      printk("EXTENDED IDENTIFY ");
-#endif
-		    break;
-		  case 0x03:
-#if defined(DEBUG_MSGI)
-		    if(aha152x_debug & debug_msgi)
-		      printk("WIDE DATA TRANSFER REQUEST ");
-#endif
-		    SETPORT(SCSISIG, P_MSGI|ATNO);
-		    break;
-		  default:
-#if defined(DEBUG_MSGI)
-		    if(aha152x_debug & debug_msgi)
-		      if( code & 0x80 )
-			printk("reserved (%d) ", code );
+        		    /* we initiated SDTR */
+        		    if(ticks>9 || buffer[4]<1 || buffer[4]>8)
+        		      aha152x_panic(shpnt, "received SDTR invalid");
+        		    
+        		    SYNCRATE |= ((ticks-2)<<4) + buffer[4];
+        		  }
+        		else if(ticks<=9 && buffer[4]>=1)
+        		  {
+        		    if(buffer[4]>8)
+        		      buffer[4]=8;
+        		    
+        		    ADDMSG(EXTENDED_MESSAGE);
+        		    ADDMSG(3);
+        		    ADDMSG(EXTENDED_SDTR);
+        		    if(ticks<4)
+        		      {
+        			    ticks=4;
+        			    ADDMSG(50);
+        		      }
 		      else
-			printk("vendor specific (%d) ", code);
-#endif
-		    SETPORT(SCSISIG, P_MSGI|ATNO);
-		    break;
+        		      ADDMSG(buffer[3]);
+        		    
+        		    ADDMSG(buffer[4]);
+        		    
+        		    printk("outbound SDTR: ");
+                            print_msg(&MSG(MSGLEN-5));
+        		    
+        		    CURRENT_SC->SCp.phase |= in_sync;
+        		    
+                            SYNCRATE |= ((ticks-2)<<4) + buffer[4];
+        		    
+        		    start_sync++;
 		  }
-#if defined(DEBUG_MSGI)
-		if(aha152x_debug & debug_msgi)
-		  printk(" ), data ( ");
-#endif
-		while( --i && (make_acklow(), getphase()==P_MSGI))
+        		else
 		  {
-#if defined(DEBUG_MSGI)
-		    if(aha152x_debug & debug_msgi)
-		      printk("%x ", GETPORT(SCSIBUS) );
-#else
-		    GETPORT(SCSIBUS);
-#endif
+        		    /* request SDTR is to slow, do it asynchronously */
+        		    ADDMSG(MESSAGE_REJECT);
+                            SYNCRATE = 0;
+        		  } 
+        		
+        		SETPORT(SCSIRATE, SYNCRATE&0x7f);
+        	      }
+        	      break;
+        	      
+        	    case EXTENDED_MODIFY_DATA_POINTER:
+        	    case EXTENDED_EXTENDED_IDENTIFY:
+        	    case EXTENDED_WDTR:
+        	    default:
+        	      ADDMSG(MESSAGE_REJECT);
+        	      break;
 		  }
-#if defined(DEBUG_MSGI)
-		if(aha152x_debug & debug_msgi)
-		  printk(" ), ");
-#endif
-		/* We reject all extended messages. To do this
-		   we just enter MSGO by asserting ATN. Since
-		   we have already identified a REJECT message
-		   will be sent. */
-		SETPORT(SCSISIG, P_MSGI|ATNO);
 	      }
 	      break;
        
 	    default:
-	      printk("unsupported inbound message %x, ", current_SC->SCp.Message);
+        	printk("unsupported inbound message %x, ", 
+        	       CURRENT_SC->SCp.Message);
 	      break;
 
 	    }
 
-	  make_acklow();
-	  phase=getphase();
+            make_acklow(shpnt);
+            phase=getphase(shpnt);
 	} 
 
+        if(start_sync)
+          CURRENT_SC->SCp.phase |= in_sync;
+        else
+          CURRENT_SC->SCp.phase &= ~in_sync;
+        
+        if(MSGLEN>0)
+          SETPORT(SCSISIG, P_MSGI|ATNO);
+        
       /* clear SCSI fifo on BUSFREE */
       if(phase==P_BUSFREE)
 	SETPORT(SXFRCTL0, CH1|CLRCH1);
 
-      if(current_SC->SCp.phase & disconnected)
+        if(CURRENT_SC->SCp.phase & disconnected)
 	{
 	  save_flags(flags);
 	  cli();
 #if defined(DEBUG_QUEUES)
-	  if(aha152x_debug & debug_queues)
+            if(HOSTDATA(shpnt)->debug & debug_queues)
 	    printk("d+, ");
 #endif
-	  append_SC( &disconnected_SC, current_SC);
-	  current_SC = NULL;
+            append_SC(&DISCONNECTED_SC, CURRENT_SC);
+            CURRENT_SC = NULL;
 	  restore_flags(flags);
 
-	  SETBITS( SCSISEQ, ENRESELI );
+            SETBITS(SCSISEQ, ENRESELI);
 
-	  SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-	  SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
+            SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+            SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
-	  SETBITS( DMACNTRL0, INTEN );
+            SETBITS(DMACNTRL0, INTEN);
 	  return;
 	}
+      }
       break;
 
     case P_STATUS:                                         /* STATUS IN phase */
 #if defined(DEBUG_STATUS) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-      if(aha152x_debug & (debug_status|debug_intr|debug_phases))
+      if(HOSTDATA(shpnt)->debug & (debug_status|debug_intr|debug_phases))
 	printk("STATUS, ");
 #endif
-      SETPORT( SXFRCTL0, CH1);
+      SETPORT(SXFRCTL0, CH1);
 
-      SETPORT( SIMODE0, 0 );
-      SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
+      SETPORT(SIMODE0, 0);
+      SETPORT(SIMODE1, ENREQINIT|ENBUSFREE);
 
-      if( TESTHI( SSTAT1, PHASEMIS ) )
+      if(TESTHI(SSTAT1, PHASEMIS))
 	printk("aha152x: passing STATUS phase");
 	
-      current_SC->SCp.Status = GETPORT( SCSIBUS );
-      make_acklow();
-      getphase();
+      CURRENT_SC->SCp.Status = GETPORT(SCSIBUS);
+      make_acklow(shpnt);
+      getphase(shpnt);
 
 #if defined(DEBUG_STATUS)
-      if(aha152x_debug & debug_status)
+      if(HOSTDATA(shpnt)->debug & debug_status)
       {
 	printk("inbound status ");
-	print_status( current_SC->SCp.Status );
+          print_status(CURRENT_SC->SCp.Status);
 	printk(", ");
       }
 #endif
@@ -1907,117 +1965,130 @@
 	int fifodata, data_count, done;
 
 #if defined(DEBUG_DATAI) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-	if(aha152x_debug & (debug_datai|debug_intr|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr|debug_phases))
 	  printk("DATA IN, ");
 #endif
 
+#if 0
 	if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
 	  printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n",
 		 GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
+#endif
 
 	/* reset host fifo */
 	SETPORT(DMACNTRL0, RSTFIFO);
 	SETPORT(DMACNTRL0, RSTFIFO|ENDMA);
 
-	SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN );
+        SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
 
-	SETPORT( SIMODE0, 0 );
-	SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+        SETPORT(SIMODE0, 0);
+        SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 
 	/* done is set when the FIFO is empty after the target left DATA IN */
 	done=0;
       
 	/* while the target stays in DATA to transfer data */
-	while ( !done ) 
+        while (!done) 
 	  {
 #if defined(DEBUG_DATAI)
-	    if(aha152x_debug & debug_datai)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
 	      printk("expecting data, ");
 #endif
 	    /* wait for PHASEMIS or full FIFO */
-	    while( TESTLO ( DMASTAT, DFIFOFULL|INTSTAT ) )
+            while(TESTLO (DMASTAT, DFIFOFULL|INTSTAT))
 	      ;
 
-	    if( TESTHI( DMASTAT, DFIFOFULL ) )
+#if defined(DEBUG_DATAI)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
+              printk("ok, ");
+#endif
+            
+            if(TESTHI(DMASTAT, DFIFOFULL))
 	      fifodata=GETPORT(FIFOSTAT);
 	    else
 	      {
 		/* wait for SCSI fifo to get empty */
-		while( TESTLO( SSTAT2, SEMPTY ) )
+        	while(TESTLO(SSTAT2, SEMPTY))
 		  ;
 
 		/* rest of data in FIFO */
 		fifodata=GETPORT(FIFOSTAT);
 #if defined(DEBUG_DATAI)
-		if(aha152x_debug & debug_datai)
+        	if(HOSTDATA(shpnt)->debug & debug_datai)
 		  printk("last transfer, ");
 #endif
 		done=1;
 	      }
   
 #if defined(DEBUG_DATAI)
-	    if(aha152x_debug & debug_datai)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
 	      printk("fifodata=%d, ", fifodata);
 #endif
 
-	    while( fifodata && current_SC->SCp.this_residual )
+            while(fifodata && CURRENT_SC->SCp.this_residual)
 	      {
 		data_count=fifodata;
   
 		/* limit data transfer to size of first sg buffer */
-		if (data_count > current_SC->SCp.this_residual)
-		  data_count = current_SC->SCp.this_residual;
+        	if (data_count > CURRENT_SC->SCp.this_residual)
+        	  data_count = CURRENT_SC->SCp.this_residual;
   
 		fifodata -= data_count;
 
 #if defined(DEBUG_DATAI)
-		if(aha152x_debug & debug_datai)
+        	if(HOSTDATA(shpnt)->debug & debug_datai)
 		  printk("data_count=%d, ", data_count);
 #endif
   
 		if(data_count&1)
 		  {
 		    /* get a single byte in byte mode */
-		    SETBITS(DMACNTRL0, _8BIT );
-		    *current_SC->SCp.ptr++ = GETPORT( DATAPORT );
-		    current_SC->SCp.this_residual--;
+        	    SETBITS(DMACNTRL0, _8BIT);
+        	    *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
+        	    CURRENT_SC->SCp.this_residual--;
 		  }
 		if(data_count>1)
 		  {
-		    CLRBITS(DMACNTRL0, _8BIT );
+        	    CLRBITS(DMACNTRL0, _8BIT);
 		    data_count >>= 1; /* Number of words */
-		    insw( DATAPORT, current_SC->SCp.ptr, data_count );
+        	    insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
 #if defined(DEBUG_DATAI)
-		    if(aha152x_debug & debug_datai)
-/* show what comes with the last transfer */
+        	    if(HOSTDATA(shpnt)->debug & debug_datai)
+        	      /* show what comes with the last transfer */
 		      if(done)
 			{
+#ifdef 0
 			  int           i;
 			  unsigned char *data;
+#endif
   
+        		  printk("data on last transfer (%d bytes) ",
+        			 2*data_count);
+#ifdef 0
 			  printk("data on last transfer (%d bytes: ",
 				 2*data_count);
-			  data = (unsigned char *) current_SC->SCp.ptr;
-			  for( i=0; i<2*data_count; i++)
+        		  data = (unsigned char *) CURRENT_SC->SCp.ptr;
+        		  for(i=0; i<2*data_count; i++)
 			    printk("%2x ", *data++);
 			  printk("), ");
+#endif
 			}
 #endif
-		    current_SC->SCp.ptr           += 2 * data_count;
-		    current_SC->SCp.this_residual -= 2 * data_count;
+        	    CURRENT_SC->SCp.ptr           += 2 * data_count;
+        	    CURRENT_SC->SCp.this_residual -= 2 * data_count;
 		  }
 	      
 		/* if this buffer is full and there are more buffers left */
-		if (!current_SC->SCp.this_residual &&
-		     current_SC->SCp.buffers_residual)
+        	if (!CURRENT_SC->SCp.this_residual &&
+        	    CURRENT_SC->SCp.buffers_residual)
 		  {
 		    /* advance to next buffer */
-		    current_SC->SCp.buffers_residual--;
-		    current_SC->SCp.buffer++;
-		    current_SC->SCp.ptr =
-		      current_SC->SCp.buffer->address;
-		    current_SC->SCp.this_residual =
-		      current_SC->SCp.buffer->length;
+        	    CURRENT_SC->SCp.buffers_residual--;
+        	    CURRENT_SC->SCp.buffer++;
+        	    CURRENT_SC->SCp.ptr =
+        	      CURRENT_SC->SCp.buffer->address;
+        	    CURRENT_SC->SCp.this_residual =
+        	      CURRENT_SC->SCp.buffer->length;
 		  } 
 	      }
  
@@ -2028,15 +2099,15 @@
 	      {
 		printk("aha152x: more data than expected (%d bytes)\n",
 		       GETPORT(FIFOSTAT));
-		SETBITS(DMACNTRL0, _8BIT );
-		printk("aha152x: data ( ");
+        	SETBITS(DMACNTRL0, _8BIT);
+        	printk("aha152x: data (");
 		while(fifodata--)
-		  printk("%2x ", GETPORT( DATAPORT ));
+        	  printk("%2x ", GETPORT(DATAPORT));
 		printk(")\n");
 	      }
 
 #if defined(DEBUG_DATAI)
-	    if(aha152x_debug & debug_datai)
+            if(HOSTDATA(shpnt)->debug & debug_datai)
 	      if(!fifodata)
 		printk("fifo empty, ");
 	      else
@@ -2045,23 +2116,25 @@
 	  }
 
 #if defined(DEBUG_DATAI)
-	if((aha152x_debug & debug_datai) && (current_SC->SCp.buffers_residual || current_SC->SCp.this_residual))
+        if((HOSTDATA(shpnt)->debug & debug_datai) &&
+           (CURRENT_SC->SCp.buffers_residual ||
+            CURRENT_SC->SCp.this_residual))
 	  printk("left buffers (buffers=%d, bytes=%d), ",
-		 current_SC->SCp.buffers_residual, 
-		 current_SC->SCp.this_residual);
+        	 CURRENT_SC->SCp.buffers_residual, 
+        	 CURRENT_SC->SCp.this_residual);
 #endif
 	/* transfer can be considered ended, when SCSIEN reads back zero */
 	CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
-	while( TESTHI( SXFRCTL0, SCSIEN ) )
+        while(TESTHI(SXFRCTL0, SCSIEN))
 	  ;
-	CLRBITS(DMACNTRL0, ENDMA );
+        CLRBITS(DMACNTRL0, ENDMA);
 
 #if defined(DEBUG_DATAI) || defined(DEBUG_INTR)
-	if(aha152x_debug & (debug_datai|debug_intr))
+        if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr))
 	  printk("got %d bytes, ", GETSTCNT());
 #endif
 
-	current_SC->SCp.have_data_in++;
+        CURRENT_SC->SCp.have_data_in++;
       }
       break;
 
@@ -2070,95 +2143,96 @@
 	int data_count;
 
 #if defined(DEBUG_DATAO) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-	if(aha152x_debug & (debug_datao|debug_intr|debug_phases))
+        if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr|debug_phases))
 	  printk("DATA OUT, ");
 #endif
 #if defined(DEBUG_DATAO)
-	if(aha152x_debug & debug_datao)
+        if(HOSTDATA(shpnt)->debug & debug_datao)
 	  printk("got data to send (bytes=%d, buffers=%d), ",
-		 current_SC->SCp.this_residual,
-		 current_SC->SCp.buffers_residual );
+        	 CURRENT_SC->SCp.this_residual,
+        	 CURRENT_SC->SCp.buffers_residual);
 #endif
 
-	if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT) )
+        if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
 	  {
-	    printk("%d(%d) left in FIFO, ", GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT) );
-	    aha152x_panic("FIFO should be empty");
+            printk("%d(%d) left in FIFO, ",
+        	   GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
+            aha152x_panic(shpnt, "FIFO should be empty");
 	  }
 
+        SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1);
+        SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
+        
 	SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
 	SETPORT(DMACNTRL0, ENDMA|WRITE_READ);
 
-	SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 );
-	SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
- 
-	SETPORT( SIMODE0, 0 );
-	SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+        SETPORT(SIMODE0, 0);
+        SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 
 	/* while current buffer is not empty or
 	   there are more buffers to transfer */
-	while( TESTLO( SSTAT1, PHASEMIS ) &&
-		 (current_SC->SCp.this_residual ||
-		  current_SC->SCp.buffers_residual) )
+        while(TESTLO(SSTAT1, PHASEMIS) &&
+              (CURRENT_SC->SCp.this_residual ||
+               CURRENT_SC->SCp.buffers_residual))
 	  {
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
 	      printk("sending data (left: bytes=%d, buffers=%d), waiting, ",
-		     current_SC->SCp.this_residual,
-		     current_SC->SCp.buffers_residual);
+        	     CURRENT_SC->SCp.this_residual,
+        	     CURRENT_SC->SCp.buffers_residual);
 #endif
 	    /* transfer rest of buffer, but max. 128 byte */
-	    data_count = current_SC->SCp.this_residual > 128 ?
-			 128 : current_SC->SCp.this_residual ;
+            data_count =
+              CURRENT_SC->SCp.this_residual > 128 ?
+              128 : CURRENT_SC->SCp.this_residual ;
 
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
 	      printk("data_count=%d, ", data_count);
 #endif
   
 	    if(data_count&1)
 	      {
 		/* put a single byte in byte mode */
-		SETBITS(DMACNTRL0, _8BIT );
-		SETPORT(DATAPORT, *current_SC->SCp.ptr++);
-		current_SC->SCp.this_residual--;
+        	SETBITS(DMACNTRL0, _8BIT);
+        	SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++);
+        	CURRENT_SC->SCp.this_residual--;
 	      }
 	    if(data_count>1)
 	      {
-		CLRBITS(DMACNTRL0, _8BIT );
-		data_count >>= 1; /* Number of words */
-		outsw( DATAPORT, current_SC->SCp.ptr, data_count );
-		current_SC->SCp.ptr           += 2 * data_count;
-		current_SC->SCp.this_residual -= 2 * data_count;
+        	CLRBITS(DMACNTRL0, _8BIT);
+        	data_count >>= 1; /* number of words */
+        	outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
+        	CURRENT_SC->SCp.ptr           += 2 * data_count;
+        	CURRENT_SC->SCp.this_residual -= 2 * data_count;
 	      }
 
 	    /* wait for FIFO to get empty */
-	    while( TESTLO ( DMASTAT, DFIFOEMP|INTSTAT ) )
+            while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT))
 	      ;
 
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
 	      printk("fifo (%d bytes), transfered (%d bytes), ",
-		     GETPORT(FIFOSTAT), GETSTCNT() );
+        	     GETPORT(FIFOSTAT), GETSTCNT());
 #endif
 
 	    /* if this buffer is empty and there are more buffers left */
-	    if ( TESTLO( SSTAT1, PHASEMIS ) &&
-		 !current_SC->SCp.this_residual &&
-		  current_SC->SCp.buffers_residual)
+            if (TESTLO(SSTAT1, PHASEMIS) &&
+        	!CURRENT_SC->SCp.this_residual &&
+        	CURRENT_SC->SCp.buffers_residual)
 	      {
 		 /* advance to next buffer */
-		 current_SC->SCp.buffers_residual--;
-		 current_SC->SCp.buffer++;
-		 current_SC->SCp.ptr =
-		   current_SC->SCp.buffer->address;
-		 current_SC->SCp.this_residual =
-		 current_SC->SCp.buffer->length;
+        	CURRENT_SC->SCp.buffers_residual--;
+        	CURRENT_SC->SCp.buffer++;
+        	CURRENT_SC->SCp.ptr =
+        	  CURRENT_SC->SCp.buffer->address;
+        	CURRENT_SC->SCp.this_residual =
+        	  CURRENT_SC->SCp.buffer->length;
 	      }
 	  }
 
-	if ( current_SC->SCp.this_residual ||
-	     current_SC->SCp.buffers_residual )
+        if (CURRENT_SC->SCp.this_residual || CURRENT_SC->SCp.buffers_residual)
 	  {
 	    /* target leaves DATA OUT for an other phase
 	       (perhaps disconnect) */
@@ -2167,46 +2241,47 @@
 	    data_count = GETPORT(SSTAT2) & (SFULL|SFCNT);
 
 	    data_count += GETPORT(FIFOSTAT) ;
-	    current_SC->SCp.ptr           -= data_count;
-	    current_SC->SCp.this_residual += data_count;
+            CURRENT_SC->SCp.ptr           -= data_count;
+            CURRENT_SC->SCp.this_residual += data_count;
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
-	      printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), transfer incomplete, resetting fifo, ",
-		     current_SC->SCp.this_residual,
-		     current_SC->SCp.buffers_residual,
-		     data_count );
+            if(HOSTDATA(shpnt)->debug & debug_datao)
+              printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), "
+        	     "transfer incomplete, resetting fifo, ",
+        	     CURRENT_SC->SCp.this_residual,
+        	     CURRENT_SC->SCp.buffers_residual,
+        	     data_count);
 #endif
 	    SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
-	    CLRBITS(SXFRCTL0, SCSIEN|DMAEN );
+            CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
 	    CLRBITS(DMACNTRL0, ENDMA);
 	  }
 	else
 	  {
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
 	      printk("waiting for SCSI fifo to get empty, ");
 #endif
 	    /* wait for SCSI fifo to get empty */
-	    while( TESTLO( SSTAT2, SEMPTY ) )
+            while(TESTLO(SSTAT2, SEMPTY))
 	      ;
 #if defined(DEBUG_DATAO)
-	    if(aha152x_debug & debug_datao)
+            if(HOSTDATA(shpnt)->debug & debug_datao)
 	      printk("ok, left data (bytes=%d, buffers=%d) ",
-		     current_SC->SCp.this_residual,
-		     current_SC->SCp.buffers_residual);
+        	     CURRENT_SC->SCp.this_residual,
+        	     CURRENT_SC->SCp.buffers_residual);
 #endif
 	    CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
 
 	    /* transfer can be considered ended, when SCSIEN reads back zero */
-	    while( TESTHI( SXFRCTL0, SCSIEN ) )
+            while(TESTHI(SXFRCTL0, SCSIEN))
 	      ;
 
 	    CLRBITS(DMACNTRL0, ENDMA);
 	  }
 
 #if defined(DEBUG_DATAO) || defined(DEBUG_INTR)
-	if(aha152x_debug & (debug_datao|debug_intr))
-	  printk("sent %d data bytes, ", GETSTCNT() );
+        if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr))
+          printk("sent %d data bytes, ", GETSTCNT());
 #endif
       }
       break;
@@ -2216,12 +2291,12 @@
       leave_driver("(BUSFREE) intr");
 #endif
 #if defined(DEBUG_PHASES)
-      if(aha152x_debug & debug_phases)
+      if(HOSTDATA(shpnt)->debug & debug_phases)
 	printk("unexpected BUS FREE, ");
 #endif
-      current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
+      CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
 
-      aha152x_done( DID_ERROR << 16 );               /* Don't know any better */
+      aha152x_done(shpnt, DID_ERROR << 16);         /* Don't know any better */
       return;
       break;
 
@@ -2231,10 +2306,10 @@
 #endif
       printk("PARITY error in DATA phase, ");
 
-      current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16));
+      CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
 
-      SETBITS( DMACNTRL0, INTEN );
-      aha152x_done( DID_PARITY << 16 );
+      SETBITS(DMACNTRL0, INTEN);
+      aha152x_done(shpnt, DID_PARITY << 16);
       return;
       break;
 
@@ -2246,85 +2321,86 @@
   if(done)
     {
 #if defined(DEBUG_INTR)
-      if(aha152x_debug & debug_intr)
+      if(HOSTDATA(shpnt)->debug & debug_intr)
 	printk("command done.\n");
 #endif
 #if defined(DEBUG_RACE)
       leave_driver("(done) intr");
 #endif
 
-      SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
-      SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
-      SETPORT(SCSISEQ, disconnected_SC ? ENRESELI : 0 );
-
-      SETBITS( DMACNTRL0, INTEN );
-
-      aha152x_done(   (current_SC->SCp.Status  & 0xff)
-		    | ( (current_SC->SCp.Message & 0xff) << 8)
-		    | ( DID_OK << 16) );
+      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+      SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0);
+      
+      SETBITS(DMACNTRL0, INTEN);
+      
+      aha152x_done(shpnt,
+        	   (CURRENT_SC->SCp.Status  & 0xff)
+        	   | ((CURRENT_SC->SCp.Message & 0xff) << 8)
+        	   | (DID_OK << 16));
 
 #if defined(DEBUG_RACE)
       printk("done returned (DID_OK: Status=%x; Message=%x).\n",
-	     current_SC->SCp.Status, current_SC->SCp.Message);
+             CURRENT_SC->SCp.Status, CURRENT_SC->SCp.Message);
 #endif
       return;
     }
 
-  if(current_SC)
-    current_SC->SCp.phase |= 1<<16 ;
+  if(CURRENT_SC)
+    CURRENT_SC->SCp.phase |= 1<<16 ;
 
-  SETPORT( SIMODE0, 0 );
-  SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
+  SETPORT(SIMODE0, 0);
+  SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
 #if defined(DEBUG_INTR)
-  if(aha152x_debug & debug_intr)
-    disp_enintr();
+  if(HOSTDATA(shpnt)->debug & debug_intr)
+    disp_enintr(shpnt);
 #endif
 #if defined(DEBUG_RACE)
   leave_driver("(PHASEEND) intr");
 #endif
 
-  SETBITS( DMACNTRL0, INTEN);
+  SETBITS(DMACNTRL0, INTEN);
   return;
 }
 
 /* 
  * Dump the current driver status and panic...
  */
-static void aha152x_panic(const char *msg)
+static void aha152x_panic(struct Scsi_Host *shpnt, char *msg)
 {
-  printk("\naha152x_panic: %s\n", msg);
-  show_queues();
+  printk("\naha152x: %s\n", msg);
+  show_queues(shpnt);
   panic("aha152x panic");
 }
 
 /*
  * Display registers of AIC-6260
  */
-static void disp_ports(void)
+static void disp_ports(struct Scsi_Host *shpnt)
 {
 #ifdef DEBUG_AHA152X
   int s;
 
 #ifdef SKIP_PORTS
-  if(aha152x_debug & debug_skipports)
+  if(HOSTDATA(shpnt)->debug & debug_skipports)
 	return;
 #endif
 
-  printk("\n%s: ", current_SC ? "on bus" : "waiting");
+  printk("\n%s: ", CURRENT_SC ? "on bus" : "waiting");
 
   s=GETPORT(SCSISEQ);
-  printk("SCSISEQ ( ");
-  if( s & TEMODEO )     printk("TARGET MODE ");
-  if( s & ENSELO )      printk("SELO ");
-  if( s & ENSELI )      printk("SELI ");
-  if( s & ENRESELI )    printk("RESELI ");
-  if( s & ENAUTOATNO )  printk("AUTOATNO ");
-  if( s & ENAUTOATNI )  printk("AUTOATNI ");
-  if( s & ENAUTOATNP )  printk("AUTOATNP ");
-  if( s & SCSIRSTO )    printk("SCSIRSTO ");
+  printk("SCSISEQ (");
+  if(s & TEMODEO)     printk("TARGET MODE ");
+  if(s & ENSELO)      printk("SELO ");
+  if(s & ENSELI)      printk("SELI ");
+  if(s & ENRESELI)    printk("RESELI ");
+  if(s & ENAUTOATNO)  printk("AUTOATNO ");
+  if(s & ENAUTOATNI)  printk("AUTOATNI ");
+  if(s & ENAUTOATNP)  printk("AUTOATNP ");
+  if(s & SCSIRSTO)    printk("SCSIRSTO ");
   printk(");");
 
-  printk(" SCSISIG ( ");
+  printk(" SCSISIG (");
   s=GETPORT(SCSISIG);
   switch(s & P_MASK)
     {
@@ -2351,132 +2427,131 @@
       break;
     }
   
-  printk(" ); ");
+  printk("); ");
 
-  printk("INTSTAT ( %s ); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
+  printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
 
-  printk("SSTAT ( ");
+  printk("SSTAT (");
   s=GETPORT(SSTAT0);
-  if( s & TARGET )   printk("TARGET ");
-  if( s & SELDO )    printk("SELDO ");
-  if( s & SELDI )    printk("SELDI ");
-  if( s & SELINGO )  printk("SELINGO ");
-  if( s & SWRAP )    printk("SWRAP ");
-  if( s & SDONE )    printk("SDONE ");
-  if( s & SPIORDY )  printk("SPIORDY ");
-  if( s & DMADONE )  printk("DMADONE ");
+  if(s & TARGET)   printk("TARGET ");
+  if(s & SELDO)    printk("SELDO ");
+  if(s & SELDI)    printk("SELDI ");
+  if(s & SELINGO)  printk("SELINGO ");
+  if(s & SWRAP)    printk("SWRAP ");
+  if(s & SDONE)    printk("SDONE ");
+  if(s & SPIORDY)  printk("SPIORDY ");
+  if(s & DMADONE)  printk("DMADONE ");
 
   s=GETPORT(SSTAT1);
-  if( s & SELTO )     printk("SELTO ");
-  if( s & ATNTARG )   printk("ATNTARG ");
-  if( s & SCSIRSTI )  printk("SCSIRSTI ");
-  if( s & PHASEMIS )  printk("PHASEMIS ");
-  if( s & BUSFREE )   printk("BUSFREE ");
-  if( s & SCSIPERR )  printk("SCSIPERR ");
-  if( s & PHASECHG )  printk("PHASECHG ");
-  if( s & REQINIT )   printk("REQINIT ");
+  if(s & SELTO)     printk("SELTO ");
+  if(s & ATNTARG)   printk("ATNTARG ");
+  if(s & SCSIRSTI)  printk("SCSIRSTI ");
+  if(s & PHASEMIS)  printk("PHASEMIS ");
+  if(s & BUSFREE)   printk("BUSFREE ");
+  if(s & SCSIPERR)  printk("SCSIPERR ");
+  if(s & PHASECHG)  printk("PHASECHG ");
+  if(s & REQINIT)   printk("REQINIT ");
   printk("); ");
 
 
-  printk("SSTAT ( ");
+  printk("SSTAT (");
 
   s=GETPORT(SSTAT0) & GETPORT(SIMODE0);
 
-  if( s & TARGET )    printk("TARGET ");
-  if( s & SELDO )     printk("SELDO ");
-  if( s & SELDI )     printk("SELDI ");
-  if( s & SELINGO )   printk("SELINGO ");
-  if( s & SWRAP )     printk("SWRAP ");
-  if( s & SDONE )     printk("SDONE ");
-  if( s & SPIORDY )   printk("SPIORDY ");
-  if( s & DMADONE )   printk("DMADONE ");
+  if(s & TARGET)    printk("TARGET ");
+  if(s & SELDO)     printk("SELDO ");
+  if(s & SELDI)     printk("SELDI ");
+  if(s & SELINGO)   printk("SELINGO ");
+  if(s & SWRAP)     printk("SWRAP ");
+  if(s & SDONE)     printk("SDONE ");
+  if(s & SPIORDY)   printk("SPIORDY ");
+  if(s & DMADONE)   printk("DMADONE ");
 
   s=GETPORT(SSTAT1) & GETPORT(SIMODE1);
 
-  if( s & SELTO )     printk("SELTO ");
-  if( s & ATNTARG )   printk("ATNTARG ");
-  if( s & SCSIRSTI )  printk("SCSIRSTI ");
-  if( s & PHASEMIS )  printk("PHASEMIS ");
-  if( s & BUSFREE )   printk("BUSFREE ");
-  if( s & SCSIPERR )  printk("SCSIPERR ");
-  if( s & PHASECHG )  printk("PHASECHG ");
-  if( s & REQINIT )   printk("REQINIT ");
+  if(s & SELTO)     printk("SELTO ");
+  if(s & ATNTARG)   printk("ATNTARG ");
+  if(s & SCSIRSTI)  printk("SCSIRSTI ");
+  if(s & PHASEMIS)  printk("PHASEMIS ");
+  if(s & BUSFREE)   printk("BUSFREE ");
+  if(s & SCSIPERR)  printk("SCSIPERR ");
+  if(s & PHASECHG)  printk("PHASECHG ");
+  if(s & REQINIT)   printk("REQINIT ");
   printk("); ");
 
-  printk("SXFRCTL0 ( ");
+  printk("SXFRCTL0 (");
 
   s=GETPORT(SXFRCTL0);
-  if( s & SCSIEN )    printk("SCSIEN ");
-  if( s & DMAEN )     printk("DMAEN ");
-  if( s & CH1 )       printk("CH1 ");
-  if( s & CLRSTCNT )  printk("CLRSTCNT ");
-  if( s & SPIOEN )    printk("SPIOEN ");
-  if( s & CLRCH1 )    printk("CLRCH1 ");
+  if(s & SCSIEN)    printk("SCSIEN ");
+  if(s & DMAEN)     printk("DMAEN ");
+  if(s & CH1)       printk("CH1 ");
+  if(s & CLRSTCNT)  printk("CLRSTCNT ");
+  if(s & SPIOEN)    printk("SPIOEN ");
+  if(s & CLRCH1)    printk("CLRCH1 ");
   printk("); ");
 
-  printk("SIGNAL ( ");
+  printk("SIGNAL (");
 
   s=GETPORT(SCSISIG);
-  if( s & ATNI )  printk("ATNI ");
-  if( s & SELI )  printk("SELI ");
-  if( s & BSYI )  printk("BSYI ");
-  if( s & REQI )  printk("REQI ");
-  if( s & ACKI )  printk("ACKI ");
+  if(s & ATNI)  printk("ATNI ");
+  if(s & SELI)  printk("SELI ");
+  if(s & BSYI)  printk("BSYI ");
+  if(s & REQI)  printk("REQI ");
+  if(s & ACKI)  printk("ACKI ");
   printk("); ");
 
-  printk("SELID ( %02x ), ", GETPORT(SELID) );
+  printk("SELID (%02x), ", GETPORT(SELID));
 
-  printk("SSTAT2 ( ");
+  printk("SSTAT2 (");
 
   s=GETPORT(SSTAT2);
-  if( s & SOFFSET)  printk("SOFFSET ");
-  if( s & SEMPTY)   printk("SEMPTY ");
-  if( s & SFULL)    printk("SFULL ");
-  printk("); SFCNT ( %d ); ", s & (SFULL|SFCNT) );
+  if(s & SOFFSET)  printk("SOFFSET ");
+  if(s & SEMPTY)   printk("SEMPTY ");
+  if(s & SFULL)    printk("SFULL ");
+  printk("); SFCNT (%d); ", s & (SFULL|SFCNT));
 
-#if 0
-  printk("SSTAT4 ( ");
+  s=GETPORT(SSTAT3);
+  printk("SCSICNT (%d), OFFCNT(%d), ", (s&0xf0)>>4, s&0x0f);
+  
+  printk("SSTAT4 (");
   s=GETPORT(SSTAT4);
-  if( s & SYNCERR)   printk("SYNCERR ");
-  if( s & FWERR)     printk("FWERR ");
-  if( s & FRERR)     printk("FRERR ");
+  if(s & SYNCERR)   printk("SYNCERR ");
+  if(s & FWERR)     printk("FWERR ");
+  if(s & FRERR)     printk("FRERR ");
   printk("); ");
-#endif
-
-  printk("FCNT ( %d ); ", GETPORT(FIFOSTAT) );
 
-  printk("DMACNTRL0 ( ");
+  printk("DMACNTRL0 (");
   s=GETPORT(DMACNTRL0);
-  printk( "%s ", s & _8BIT      ? "8BIT"  : "16BIT" );
-  printk( "%s ", s & DMA        ? "DMA"   : "PIO"   );
-  printk( "%s ", s & WRITE_READ ? "WRITE" : "READ"  );
-  if( s & ENDMA )    printk("ENDMA ");
-  if( s & INTEN )    printk("INTEN ");
-  if( s & RSTFIFO )  printk("RSTFIFO ");
-  if( s & SWINT )    printk("SWINT ");
+  printk("%s ", s & _8BIT      ? "8BIT"  : "16BIT");
+  printk("%s ", s & DMA        ? "DMA"   : "PIO"  );
+  printk("%s ", s & WRITE_READ ? "WRITE" : "READ" );
+  if(s & ENDMA)    printk("ENDMA ");
+  if(s & INTEN)    printk("INTEN ");
+  if(s & RSTFIFO)  printk("RSTFIFO ");
+  if(s & SWINT)    printk("SWINT ");
   printk("); ");
 
 
 #if 0
-  printk("DMACNTRL1 ( ");
+  printk("DMACNTRL1 (");
 
   s=GETPORT(DMACNTRL1);
-  if( s & PWRDWN )    printk("PWRDN ");
+  if(s & PWRDWN)    printk("PWRDN ");
   printk("); ");
 
 
-  printk("STK ( %d ); ", s & 0xf);
+  printk("STK (%d); ", s & 0xf);
+  
+#endif
 
   printk("DMASTAT (");
   s=GETPORT(DMASTAT);
-  if( s & ATDONE )     printk("ATDONE ");
-  if( s & WORDRDY )    printk("WORDRDY ");
-  if( s & DFIFOFULL )  printk("DFIFOFULL ");
-  if( s & DFIFOEMP )   printk("DFIFOEMP ");
+  if(s & ATDONE)     printk("ATDONE ");
+  if(s & WORDRDY)    printk("WORDRDY ");
+  if(s & DFIFOFULL)  printk("DFIFOFULL ");
+  if(s & DFIFOEMP)   printk("DFIFOEMP ");
   printk(")");
 
-#endif
-
   printk("\n");
 #endif
 }
@@ -2484,29 +2559,29 @@
 /*
  * display enabled interrupts
  */
-static void disp_enintr(void)
+static void disp_enintr(struct Scsi_Host *shpnt)
 {
   int s;
 
-  printk("enabled interrupts ( ");
+  printk("enabled interrupts (");
   
   s=GETPORT(SIMODE0);
-  if( s & ENSELDO )    printk("ENSELDO ");
-  if( s & ENSELDI )    printk("ENSELDI ");
-  if( s & ENSELINGO )  printk("ENSELINGO ");
-  if( s & ENSWRAP )    printk("ENSWRAP ");
-  if( s & ENSDONE )    printk("ENSDONE ");
-  if( s & ENSPIORDY )  printk("ENSPIORDY ");
-  if( s & ENDMADONE )  printk("ENDMADONE ");
+  if(s & ENSELDO)    printk("ENSELDO ");
+  if(s & ENSELDI)    printk("ENSELDI ");
+  if(s & ENSELINGO)  printk("ENSELINGO ");
+  if(s & ENSWRAP)    printk("ENSWRAP ");
+  if(s & ENSDONE)    printk("ENSDONE ");
+  if(s & ENSPIORDY)  printk("ENSPIORDY ");
+  if(s & ENDMADONE)  printk("ENDMADONE ");
 
   s=GETPORT(SIMODE1);
-  if( s & ENSELTIMO )    printk("ENSELTIMO ");
-  if( s & ENATNTARG )    printk("ENATNTARG ");
-  if( s & ENPHASEMIS )   printk("ENPHASEMIS ");
-  if( s & ENBUSFREE )    printk("ENBUSFREE ");
-  if( s & ENSCSIPERR )   printk("ENSCSIPERR ");
-  if( s & ENPHASECHG )   printk("ENPHASECHG ");
-  if( s & ENREQINIT )    printk("ENREQINIT ");
+  if(s & ENSELTIMO)    printk("ENSELTIMO ");
+  if(s & ENATNTARG)    printk("ENATNTARG ");
+  if(s & ENPHASEMIS)   printk("ENPHASEMIS ");
+  if(s & ENBUSFREE)    printk("ENBUSFREE ");
+  if(s & ENSCSIPERR)   printk("ENSCSIPERR ");
+  if(s & ENPHASECHG)   printk("ENPHASECHG ");
+  if(s & ENREQINIT)    printk("ENREQINIT ");
   printk(")\n");
 }
 
@@ -2560,7 +2635,7 @@
  */
 static void show_command(Scsi_Cmnd *ptr)
 {
-  printk("0x%08x: target=%d; lun=%d; cmnd=( ",
+  printk("0x%08x: target=%d; lun=%d; cmnd=(",
 	 (unsigned int) ptr, ptr->target, ptr->lun);
   
   print_command(ptr->cmnd);
@@ -2568,15 +2643,15 @@
   printk("); residual=%d; buffers=%d; phase |",
 	 ptr->SCp.this_residual, ptr->SCp.buffers_residual);
 
-  if( ptr->SCp.phase & not_issued   )  printk("not issued|");
-  if( ptr->SCp.phase & in_selection )  printk("in selection|");
-  if( ptr->SCp.phase & disconnected )  printk("disconnected|");
-  if( ptr->SCp.phase & aborted      )  printk("aborted|");
-  if( ptr->SCp.phase & sent_ident   )  printk("send_ident|");
-  if( ptr->SCp.phase & in_other )
+  if(ptr->SCp.phase & not_issued  )  printk("not issued|");
+  if(ptr->SCp.phase & in_selection)  printk("in selection|");
+  if(ptr->SCp.phase & disconnected)  printk("disconnected|");
+  if(ptr->SCp.phase & aborted     )  printk("aborted|");
+  if(ptr->SCp.phase & sent_ident  )  printk("send_ident|");
+  if(ptr->SCp.phase & in_other)
     { 
       printk("; in other(");
-      switch( (ptr->SCp.phase >> 16) & P_MASK )
+      switch((ptr->SCp.phase >> 16) & P_MASK)
 	{
 	case P_DATAO:
 	  printk("DATA OUT");
@@ -2610,7 +2685,7 @@
 /*
  * Dump the queued data
  */
-static void show_queues(void)
+static void show_queues(struct Scsi_Host *shpnt)
 {
   unsigned long flags;
   Scsi_Cmnd *ptr;
@@ -2618,22 +2693,241 @@
   save_flags(flags);
   cli();
   printk("QUEUE STATUS:\nissue_SC:\n");
-  for(ptr=issue_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble )
+  for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
     show_command(ptr);
 
   printk("current_SC:\n");
-  if(current_SC)
-    show_command(current_SC);
+  if(CURRENT_SC)
+    show_command(CURRENT_SC);
   else
     printk("none\n");
 
   printk("disconnected_SC:\n");
-  for(ptr=disconnected_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble )
+  for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
     show_command(ptr);
 
-  disp_ports();
-  disp_enintr();
+  disp_ports(shpnt);
+  disp_enintr(shpnt);
+  restore_flags(flags);
+}
+
+int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
+{
+  return(-ENOSYS);  /* Currently this is a no-op */
+}
+
+#undef SPRINTF
+#define SPRINTF(args...) pos += sprintf(pos, ## args)
+
+static int get_command(char *pos, Scsi_Cmnd *ptr)
+{
+  char *start = pos;
+  int i;
+  
+  SPRINTF("0x%08x: target=%d; lun=%d; cmnd=(",
+          (unsigned int) ptr, ptr->target, ptr->lun);
+  
+  for(i=0; i<COMMAND_SIZE(ptr->cmnd[0]); i++)
+    SPRINTF("0x%02x", ptr->cmnd[i]);
+  
+  SPRINTF("); residual=%d; buffers=%d; phase |",
+          ptr->SCp.this_residual, ptr->SCp.buffers_residual);
+  
+  if(ptr->SCp.phase & not_issued  )  SPRINTF("not issued|");
+  if(ptr->SCp.phase & in_selection)  SPRINTF("in selection|");
+  if(ptr->SCp.phase & disconnected)  SPRINTF("disconnected|");
+  if(ptr->SCp.phase & aborted     )  SPRINTF("aborted|");
+  if(ptr->SCp.phase & sent_ident  )  SPRINTF("send_ident|");
+  if(ptr->SCp.phase & in_other)
+    { 
+      SPRINTF("; in other(");
+      switch((ptr->SCp.phase >> 16) & P_MASK)
+        {
+        case P_DATAO:
+          SPRINTF("DATA OUT");
+          break;
+        case P_DATAI:
+          SPRINTF("DATA IN");
+          break;
+        case P_CMD:
+          SPRINTF("COMMAND");
+          break;
+        case P_STATUS:
+          SPRINTF("STATUS");
+          break;
+        case P_MSGO:
+          SPRINTF("MESSAGE OUT");
+          break;
+        case P_MSGI:
+          SPRINTF("MESSAGE IN");
+          break;
+        default: 
+          SPRINTF("*illegal*");
+          break;
+        }
+      SPRINTF(")");
+      if(ptr->SCp.phase & (1<<16))
+        SPRINTF("; phaseend");
+    }
+  SPRINTF("; next=0x%08x\n", (unsigned int) ptr->host_scribble);
+  
+  return(pos-start);
+}
+
+#undef SPRINTF
+#define SPRINTF(args...) do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
+
+int aha152x_proc_info(
+        	      char *buffer,
+        	      char **start,
+        	      off_t offset,
+        	      int length,
+        	      int hostno,
+        	      int inout
+        	      )
+{
+  int i;
+  char *pos = buffer;
+  Scsi_Device *scd;
+  struct Scsi_Host *shpnt;
+  unsigned long flags;
+  Scsi_Cmnd *ptr;
+  
+  for(i=0, shpnt= (struct Scsi_Host *) NULL; i<IRQS; i++)
+    if(aha152x_host[i] && aha152x_host[i]->host_no == hostno)
+      shpnt=aha152x_host[i];
+  
+  if(!shpnt)
+    return(-ESRCH);
+  
+  if(inout) /* Has data been written to the file ? */ 
+    return(aha152x_set_info(buffer, length, shpnt));
+  
+  SPRINTF(AHA152X_REVID "\n");
+  
+  save_flags(flags);
+  cli();
+  
+  SPRINTF("vital data:\nioports 0x%04x to 0x%04x\n",
+          shpnt->io_port, shpnt->io_port+shpnt->n_io_port-1);
+  SPRINTF("interrupt 0x%02x\n", shpnt->irq);
+  SPRINTF("disconnection/reconnection %s\n", 
+          HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled");
+  SPRINTF("parity checking %s\n", 
+          HOSTDATA(shpnt)->parity ? "enabled" : "disabled");
+  SPRINTF("synchronous transfers %s\n", 
+          HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled");
+  SPRINTF("current queued %d commands\n",
+          HOSTDATA(shpnt)->commands);
+  
+#if 0
+  SPRINTF("synchronously operating targets (tick=%ld ns):\n",
+          250000000/loops_per_sec);
+  for(i=0; i<8; i++)
+    if(HOSTDATA(shpnt)->syncrate[i]&0x7f)
+      SPRINTF("target %d: period %dT/%ldns; req/ack offset %d\n",
+              i,
+              (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2),
+        	       (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*
+        		 250000000/loops_per_sec,
+        	       HOSTDATA(shpnt)->syncrate[i]&0x0f);
+#else
+  SPRINTF("synchronously operating targets (tick=50 ns):\n");
+  for(i=0; i<8; i++)
+    if(HOSTDATA(shpnt)->syncrate[i]&0x7f)
+      SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n",
+              i,
+              (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2),
+              (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*50,
+              HOSTDATA(shpnt)->syncrate[i]&0x0f);
+#endif
+  
+#ifdef DEBUG_AHA152X
+#define PDEBUG(flags,txt) if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt);
+  
+  SPRINTF("enabled debugging options:\n");
+  
+  PDEBUG(debug_skipports, "skip ports");
+  PDEBUG(debug_queue, "queue");
+  PDEBUG(debug_intr, "interrupt");
+  PDEBUG(debug_selection, "selection");
+  PDEBUG(debug_msgo, "message out");
+  PDEBUG(debug_msgi, "message in");
+  PDEBUG(debug_status, "status");
+  PDEBUG(debug_cmd, "command");
+  PDEBUG(debug_datai, "data in");
+  PDEBUG(debug_datao, "data out");
+  PDEBUG(debug_abort, "abort");
+  PDEBUG(debug_done, "done");
+  PDEBUG(debug_biosparam, "bios parameters");
+  PDEBUG(debug_phases, "phases");
+  PDEBUG(debug_queues, "queues");
+  PDEBUG(debug_reset, "reset");
+  
+  SPRINTF("\n");
+#endif
+  
+  SPRINTF("queue status:\nnot yet issued commands:\n");
+  for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+    pos += get_command(pos, ptr);
+  
+  if(CURRENT_SC)
+    {
+      SPRINTF("current command:\n");
+      pos += get_command(pos, CURRENT_SC);
+    }
+  
+  SPRINTF("disconnected commands:\n");
+  for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+    pos += get_command(pos, ptr);
+  
   restore_flags(flags);
+  
+  scd = scsi_devices;
+  
+  SPRINTF("Attached devices: %s\n", (scd)?"":"none");
+  
+  while (scd) {
+    if (scd->host == shpnt) {
+      
+      SPRINTF("Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
+              scd->channel, scd->id, scd->lun);
+      for (i=0; i<8; i++) {
+        if (scd->vendor[i] >= 0x20)
+          SPRINTF("%c", scd->vendor[i]);
+        else
+          SPRINTF(" ");
+      }
+      SPRINTF(" Model: ");
+      for (i = 0; i < 16; i++) {
+        if (scd->model[i] >= 0x20)
+          SPRINTF("%c", scd->model[i]);
+        else
+          SPRINTF(" ");
+      }
+      SPRINTF(" Rev: ");
+      for (i = 0; i < 4; i++) {
+        if (scd->rev[i] >= 0x20)
+          SPRINTF("%c", scd->rev[i]);
+        else
+          SPRINTF(" ");
+      }
+      SPRINTF("\n");
+      
+      SPRINTF("  Type:   %d ", scd->type);
+      SPRINTF("               ANSI SCSI revision: %02x",
+              (scd->scsi_level < 3)?1:2);
+      
+      if (scd->scsi_level == 2)
+        SPRINTF(" CCS\n");
+      else
+        SPRINTF("\n");
+    }
+    scd = scd->next;
+  }
+  
+  *start=buffer;
+  return (pos-buffer < length ? pos-buffer : length);     
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/aha152x.h linux/drivers/scsi/aha152x.h
--- v1.3.47/linux/drivers/scsi/aha152x.h	Mon Oct 23 18:02:07 1995
+++ linux/drivers/scsi/aha152x.h	Thu Dec 14 15:44:10 1995
@@ -2,7 +2,7 @@
 #define _AHA152X_H
 
 /*
- * $Id: aha152x.h,v 1.9 1995/03/18 09:21:04 root Exp root $
+ * $Id: aha152x.h,v 1.11 1995/12/07 01:03:20 fischer Exp root $
  */
 
 #if defined(__KERNEL__)
@@ -17,20 +17,21 @@
 int        aha152x_abort(Scsi_Cmnd *);
 int        aha152x_reset(Scsi_Cmnd *);
 int        aha152x_biosparam(Disk *, kdev_t, int*);
+int aha152x_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout);
 
 /* number of queueable commands
    (unless we support more than 1 cmd_per_lun this should do) */
 #define AHA152X_MAXQUEUE	7		
 
-#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.9 $"
+#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.11 $"
 
 extern struct proc_dir_entry proc_scsi_aha152x;
 
 /* Initial value of Scsi_Host entry */
 #define AHA152X       { /* next */		NULL,			    \
 			/* usage_count */  	NULL,			    \
-			                        &proc_scsi_aha152x,         \
-						NULL,                       \
+			/* proc_dir */		&proc_scsi_aha152x,         \
+			/* proc_info */		aha152x_proc_info,          \
 			/* name */		AHA152X_REVID, 		    \
 			/* detect */		aha152x_detect,             \
 			/* release */		NULL,			    \
@@ -52,37 +53,44 @@
 
 
 /* port addresses */
-#define SCSISEQ		(port_base+0x00)	/* SCSI sequence control */
-#define SXFRCTL0	(port_base+0x01)	/* SCSI transfer control 0 */
-#define SXFRCTL1	(port_base+0x02)	/* SCSI transfer control 1 */
-#define SCSISIG		(port_base+0x03)	/* SCSI signal in/out */
-#define SCSIRATE	(port_base+0x04)	/* SCSI rate control */
-#define SELID		(port_base+0x05)	/* selection/reselection ID */
+#define SCSISEQ		(shpnt->io_port+0x00)	/* SCSI sequence control */
+#define SXFRCTL0	(shpnt->io_port+0x01)	/* SCSI transfer control 0 */
+#define SXFRCTL1	(shpnt->io_port+0x02)	/* SCSI transfer control 1 */
+#define SCSISIG		(shpnt->io_port+0x03)	/* SCSI signal in/out */
+#define SCSIRATE	(shpnt->io_port+0x04)	/* SCSI rate control */
+#define SELID		(shpnt->io_port+0x05)	/* selection/reselection ID */
 #define SCSIID		SELID			/* SCSI ID */
-#define SCSIDAT		(port_base+0x06)	/* SCSI latched data */
-#define SCSIBUS		(port_base+0x07)	/* SCSI data bus */
-#define STCNT0		(port_base+0x08)	/* SCSI transfer count 0 */
-#define STCNT1		(port_base+0x09)	/* SCSI transfer count 1 */
-#define STCNT2		(port_base+0x0a)	/* SCSI transfer count 2 */
-#define SSTAT0		(port_base+0x0b)	/* SCSI interrupt status 0 */
-#define SSTAT1		(port_base+0x0c)	/* SCSI interrupt status 1 */
-#define SSTAT2		(port_base+0x0d)	/* SCSI interrupt status 2 */
-#define SCSITEST	(port_base+0x0e)	/* SCSI test control */
-#define SSTAT4		(port_base+0x0f)	/* SCSI status 4 */
-#define SIMODE0		(port_base+0x10)	/* SCSI interrupt mode 0 */
-#define SIMODE1		(port_base+0x11)	/* SCSI interrupt mode 1 */
-#define DMACNTRL0	(port_base+0x12)	/* DMA control 0 */
-#define DMACNTRL1	(port_base+0x13)	/* DMA control 1 */
-#define DMASTAT		(port_base+0x14)	/* DMA status */
-#define FIFOSTAT	(port_base+0x15)	/* FIFO status */
-#define DATAPORT	(port_base+0x16)	/* DATA port */
-#define BRSTCNTRL	(port_base+0x18)	/* burst control */
-#define PORTA		(port_base+0x1a)	/* PORT A */
-#define PORTB		(port_base+0x1b)	/* PORT B */
-#define REV		(port_base+0x1c)	/* revision */
-#define STACK		(port_base+0x1d)	/* stack */
-#define TEST		(port_base+0x1e)	/* test register */
-
+#define SCSIDAT		(shpnt->io_port+0x06)	/* SCSI latched data */
+#define SCSIBUS		(shpnt->io_port+0x07)	/* SCSI data bus */
+#define STCNT0		(shpnt->io_port+0x08)	/* SCSI transfer count 0 */
+#define STCNT1		(shpnt->io_port+0x09)	/* SCSI transfer count 1 */
+#define STCNT2		(shpnt->io_port+0x0a)	/* SCSI transfer count 2 */
+#define SSTAT0		(shpnt->io_port+0x0b)	/* SCSI interrupt status 0 */
+#define SSTAT1		(shpnt->io_port+0x0c)	/* SCSI interrupt status 1 */
+#define SSTAT2		(shpnt->io_port+0x0d)	/* SCSI interrupt status 2 */
+#define SCSITEST	(shpnt->io_port+0x0e)	/* SCSI test control */
+#define SSTAT3		SCSITEST                /* SCSI interrupt status 3 */
+#define SSTAT4		(shpnt->io_port+0x0f)	/* SCSI status 4 */
+#define SIMODE0		(shpnt->io_port+0x10)	/* SCSI interrupt mode 0 */
+#define SIMODE1		(shpnt->io_port+0x11)	/* SCSI interrupt mode 1 */
+#define DMACNTRL0	(shpnt->io_port+0x12)	/* DMA control 0 */
+#define DMACNTRL1	(shpnt->io_port+0x13)	/* DMA control 1 */
+#define DMASTAT		(shpnt->io_port+0x14)	/* DMA status */
+#define FIFOSTAT	(shpnt->io_port+0x15)	/* FIFO status */
+#define DATAPORT	(shpnt->io_port+0x16)	/* DATA port */
+#define BRSTCNTRL	(shpnt->io_port+0x18)	/* burst control */
+#define PORTA		(shpnt->io_port+0x1a)	/* PORT A */
+#define PORTB		(shpnt->io_port+0x1b)	/* PORT B */
+#define REV		(shpnt->io_port+0x1c)	/* revision */
+#define STACK		(shpnt->io_port+0x1d)	/* stack */
+#define TEST		(shpnt->io_port+0x1e)	/* test register */
+
+/* used in aha152x_porttest */
+#define O_PORTA		(0x1a)                  /* PORT A */
+#define O_PORTB		(0x1b)                  /* PORT B */
+#define O_DMACNTRL1	(0x13)                  /* DMA control 1 */
+#define O_STACK         (0x1d)                  /* stack */
+#define IO_RANGE	0x20
 
 /* bits and bitmasks to ports */
 
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/constants.c linux/drivers/scsi/constants.c
--- v1.3.47/linux/drivers/scsi/constants.c	Wed Dec 13 09:02:46 1995
+++ linux/drivers/scsi/constants.c	Thu Dec 14 06:44:58 1995
@@ -593,7 +593,7 @@
 }
 #else
 void print_hostbyte(int scsiresult)
-{   printk("Hostbyte=0x%02x ",hostbyte(scsiresult));
+{   printk("Hostbyte=0x%02x ",host_byte(scsiresult));
 }
 #endif
 
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c
--- v1.3.47/linux/drivers/scsi/g_NCR5380.c	Mon Oct 23 18:02:11 1995
+++ linux/drivers/scsi/g_NCR5380.c	Thu Dec 14 08:16:51 1995
@@ -177,3 +177,10 @@
 }
 
 #include "NCR5380.c"
+#ifdef MODULE
+/* Eventually this will go into an include file, but this will be later */
+Scsi_Host_Template driver_template = GENERIC_NCR5380;
+
+#include <linux/module.h>
+#include "scsi_module.c"
+#endif
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/g_NCR5380.h linux/drivers/scsi/g_NCR5380.h
--- v1.3.47/linux/drivers/scsi/g_NCR5380.h	Mon Sep 18 14:53:57 1995
+++ linux/drivers/scsi/g_NCR5380.h	Thu Dec 14 08:16:52 1995
@@ -51,8 +51,7 @@
 #define CAN_QUEUE 16
 #endif
 
-#ifdef HOSTS_C
-
+#if defined(HOSTS_C) || defined(MODULE)
 
 #define GENERIC_NCR5380 {NULL, NULL, NULL, NULL, \
 	"Trantor T128/T128F/T228", 		\
@@ -62,7 +61,10 @@
 	NULL, /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL,		\
 	/* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING}
 
-#else
+#endif
+
+#ifndef HOSTS_C
+
 #define NCR5380_implementation_fields \
     int port
 
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c
--- v1.3.47/linux/drivers/scsi/pas16.c	Mon Oct 23 18:02:11 1995
+++ linux/drivers/scsi/pas16.c	Thu Dec 14 08:16:52 1995
@@ -539,3 +539,11 @@
 }
 
 #include "NCR5380.c"
+
+#ifdef MODULE
+/* Eventually this will go into an include file, but this will be later */
+Scsi_Host_Template driver_template = MV_PAS16;
+
+#include <linux/module.h>
+#include "scsi_module.c"
+#endif
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/pas16.h linux/drivers/scsi/pas16.h
--- v1.3.47/linux/drivers/scsi/pas16.h	Mon Sep 18 14:54:01 1995
+++ linux/drivers/scsi/pas16.h	Thu Dec 14 08:16:52 1995
@@ -138,7 +138,7 @@
  * macros when this is being used solely for the host stub.
  */
 
-#ifdef HOSTS_C
+#if defined(HOSTS_C) || defined(MODULE)
 
 #define MV_PAS16 {NULL, NULL, NULL, NULL, \
 	"Pro Audio Spectrum-16 SCSI", 		\
@@ -148,7 +148,8 @@
 	/* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL,			\
 	/* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING}
 
-#else
+#endif
+#ifndef HOSTS_C
 
 #define NCR5380_implementation_fields \
     volatile unsigned short io_port
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v1.3.47/linux/drivers/scsi/st.c	Thu Nov  9 11:23:51 1995
+++ linux/drivers/scsi/st.c	Sun Dec 17 10:59:24 1995
@@ -11,7 +11,7 @@
   Copyright 1992, 1993, 1994, 1995 Kai Makisara
 		 email Kai.Makisara@metla.fi
 
-  Last modified: Sat Nov  4 22:23:54 1995 by root@kai.makisara.fi
+  Last modified: Thu Dec 14 21:51:16 1995 by root@kai.makisara.fi
   Some small formal changes - aeb, 950809
 */
 
@@ -34,6 +34,11 @@
    is defined and non-zero. */
 #define DEBUG 0
 
+/* The message level for the debug messages is currently set to KERN_NOTICE
+   so that people can easily see the messages. Later when the debugging messages
+   in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
+#define ST_DEB_MSG  KERN_NOTICE
+
 #define MAJOR_NR SCSI_TAPE_MAJOR
 #include <linux/blk.h>
 #include "scsi.h"
@@ -114,7 +119,8 @@
     return 0;
 #if DEBUG
   if (debugging) {
-    printk("st%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n", dev, result,
+    printk(ST_DEB_MSG "st%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
+	   dev, result,
 	   SCpnt->data_cmnd[0], SCpnt->data_cmnd[1], SCpnt->data_cmnd[2],
 	   SCpnt->data_cmnd[3], SCpnt->data_cmnd[4], SCpnt->data_cmnd[5],
 	   SCpnt->request_bufflen);
@@ -129,16 +135,18 @@
       ((sense[0] & 0x70) == 0x70 &&
        scode != NO_SENSE &&
        scode != RECOVERED_ERROR &&
-       scode != UNIT_ATTENTION &&
+/*       scode != UNIT_ATTENTION && */
        scode != BLANK_CHECK &&
        scode != VOLUME_OVERFLOW &&
-       SCpnt->data_cmnd[0] != MODE_SENSE)) {  /* Abnormal conditions for tape */
-    printk("st%d: Error %x. ", dev, result);
+       SCpnt->data_cmnd[0] != MODE_SENSE &&
+       SCpnt->data_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
 #if !DEBUG
-    if (driver_byte(result) & DRIVER_SENSE)
+    if (driver_byte(result) & DRIVER_SENSE) {
+      printk(KERN_WARNING "st%d: Error with sense data: ", dev);
       print_sense("st", SCpnt);
+    }
     else
-      printk("\n");
+      printk(KERN_WARNING "st%d: Error %x.\n", dev, result);
 #endif
   }
 
@@ -159,7 +167,7 @@
 	stp = "write";
       else
 	stp = "ioctl";
-      printk("st%d: Recovered %s error (%d).\n", dev, stp,
+      printk(ST_DEB_MSG "st%d: Recovered %s error (%d).\n", dev, stp,
 	     scsi_tapes[dev].recover_count);
     }
 #endif
@@ -212,7 +220,7 @@
   }
 #if DEBUG
   else if (debugging)
-    printk("st?: Illegal interrupt device %x\n", st_nbr);
+    printk(KERN_ERR "st?: Illegal interrupt device %x\n", st_nbr);
 #endif
 }
 
@@ -224,7 +232,7 @@
 {
   if (SCpnt == NULL)
     if ((SCpnt = allocate_device(NULL, STp->device, 1)) == NULL) {
-      printk("st%d: Can't get SCSI request.\n", TAPE_NR(STp->devt));
+      printk(KERN_ERR "st%d: Can't get SCSI request.\n", TAPE_NR(STp->devt));
       return NULL;
     }
 
@@ -298,7 +306,7 @@
 
   SCpnt->request.rq_status = RQ_INACTIVE;
   if ((STp->buffer)->last_result != 0) {
-    printk("st%d: Backing over filemark failed.\n", TAPE_NR(STp->devt));
+    printk(KERN_ERR "st%d: Backing over filemark failed.\n", TAPE_NR(STp->devt));
     if ((STp->mt_status)->mt_fileno >= 0)
       (STp->mt_status)->mt_fileno += 1;
     (STp->mt_status)->mt_blkno = 0;
@@ -322,8 +330,8 @@
     if ((STp->buffer)->last_result_fatal) {
 #if DEBUG
       if (debugging)
-	printk("st%d: Async write error (flush) %x.\n", TAPE_NR(STp->devt),
-	       (STp->buffer)->last_result);
+	printk(ST_DEB_MSG "st%d: Async write error (flush) %x.\n",
+	       TAPE_NR(STp->devt), (STp->buffer)->last_result);
 #endif
       if ((STp->buffer)->last_result == INT_MAX)
 	return (-ENOSPC);
@@ -342,7 +350,7 @@
 		STp->block_size) * STp->block_size;
 #if DEBUG
     if (debugging)
-      printk("st%d: Flushing %d bytes.\n", TAPE_NR(STp->devt), transfer);
+      printk(ST_DEB_MSG "st%d: Flushing %d bytes.\n", TAPE_NR(STp->devt), transfer);
 #endif
     memset((STp->buffer)->b_data + offset, 0, transfer - offset);
 
@@ -359,7 +367,7 @@
       return (-EBUSY);
 
     if ((STp->buffer)->last_result_fatal != 0) {
-      printk("st%d: Error on flush.\n", TAPE_NR(STp->devt));
+      printk(KERN_ERR "st%d: Error on flush.\n", TAPE_NR(STp->devt));
       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 	  (SCpnt->sense_buffer[2] & 0x40) &&
 	  (SCpnt->sense_buffer[2] & 0x0f) != VOLUME_OVERFLOW) {
@@ -450,9 +458,12 @@
       return (-ENXIO);
     STp = &(scsi_tapes[dev]);
     if (STp->in_use) {
-      printk("st%d: Device already in use.\n", dev);
+#if DEBUG
+      printk(ST_DEB_MSG "st%d: Device already in use.\n", dev);
+#endif
       return (-EBUSY);
     }
+    STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
 
     /* Allocate buffer for this user */
     for (i=0; i < st_nbr_buffers; i++)
@@ -461,7 +472,7 @@
     if (i >= st_nbr_buffers) {
       STp->buffer = new_tape_buffer(FALSE);
       if (STp->buffer == NULL) {
-	printk("st%d: No free buffers.\n", dev);
+	printk(KERN_WARNING "st%d: No free buffers.\n", dev);
 	return (-EBUSY);
       }
     }
@@ -509,7 +520,7 @@
       if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 	  (SCpnt->sense_buffer[2] & 0x0f) == NO_TAPE) {
 	(STp->mt_status)->mt_fileno = STp->drv_block = 0 ;
-	printk("st%d: No tape.\n", dev);
+	printk(KERN_NOTICE "st%d: No tape.\n", dev);
 	STp->ready = ST_NO_TAPE;
       } else {
 	(STp->mt_status)->mt_fileno = STp->drv_block = (-1);
@@ -540,7 +551,7 @@
 	(STp->buffer)->b_data[5];
 #if DEBUG
       if (debugging)
-	printk("st%d: Block limits %d - %d bytes.\n", dev, STp->min_block,
+	printk(ST_DEB_MSG "st%d: Block limits %d - %d bytes.\n", dev, STp->min_block,
 	       STp->max_block);
 #endif
     }
@@ -548,7 +559,7 @@
       STp->min_block = STp->max_block = (-1);
 #if DEBUG
       if (debugging)
-	printk("st%d: Can't read block limits.\n", dev);
+	printk(ST_DEB_MSG "st%d: Can't read block limits.\n", dev);
 #endif
     }
 
@@ -561,7 +572,7 @@
     if ((STp->buffer)->last_result_fatal != 0) {
 #if DEBUG
       if (debugging)
-	printk("st%d: No Mode Sense.\n", dev);
+	printk(ST_DEB_MSG "st%d: No Mode Sense.\n", dev);
 #endif
       STp->block_size = ST_DEFAULT_BLOCK;  /* Educated guess (?) */
       (STp->buffer)->last_result_fatal = 0;  /* Prevent error propagation */
@@ -571,7 +582,8 @@
 
 #if DEBUG
       if (debugging)
-	printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
+	printk(ST_DEB_MSG "st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",
+	       dev,
 	       (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
 	       (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]);
 #endif
@@ -583,7 +595,7 @@
 	  (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
 #if DEBUG
 	if (debugging)
-	  printk("st%d: Density %x, tape length: %x, drv buffer: %d\n",
+	  printk(ST_DEB_MSG "st%d: Density %x, tape length: %x, drv buffer: %d\n",
 		 dev, STp->density, (STp->buffer)->b_data[5] * 65536 +
 		 (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
 		 STp->drv_buffer);
@@ -592,7 +604,7 @@
 
       if (STp->block_size > (STp->buffer)->buffer_size &&
 	  !enlarge_buffer(STp->buffer, STp->block_size)) {
-	printk("st%d: Blocksize %d too large for buffer.\n", dev,
+	printk(KERN_NOTICE "st%d: Blocksize %d too large for buffer.\n", dev,
 	       STp->block_size);
 	(STp->buffer)->in_use = 0;
 	STp->in_use = 0;
@@ -610,7 +622,7 @@
 
 #if DEBUG
     if (debugging)
-      printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
+      printk(ST_DEB_MSG "st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
 	     STp->block_size, (STp->buffer)->buffer_size,
 	     (STp->buffer)->buffer_blocks);
 #endif
@@ -619,7 +631,7 @@
       STp->write_prot = 1;
 #if DEBUG
       if (debugging)
-	printk( "st%d: Write protected\n", dev);
+	printk(ST_DEB_MSG "st%d: Write protected\n", dev);
 #endif
       if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
 	(STp->buffer)->in_use = 0;
@@ -642,7 +654,6 @@
 scsi_tape_close(struct inode * inode, struct file * filp)
 {
     int result;
-    int rewind;
     static unsigned char cmd[10];
     Scsi_Cmnd * SCpnt;
     Scsi_Tape * STp;
@@ -650,8 +661,6 @@
     int dev;
 
     dev = TAPE_NR(devt);
-    rewind = (MINOR(devt) & 0x80) == 0;
-
     STp = &(scsi_tapes[dev]);
 
     if ( STp->rw == ST_WRITING && !(STp->device)->was_reset) {
@@ -660,9 +669,10 @@
 
 #if DEBUG
       if (debugging) {
-	printk("st%d: File length %ld bytes.\n", dev, (long)(filp->f_pos));
-	printk("st%d: Async write waits %d, finished %d.\n", dev,
-	       STp->nbr_waits, STp->nbr_finished);
+	printk(ST_DEB_MSG "st%d: File length %ld bytes.\n",
+	       dev, (long)(filp->f_pos));
+	printk(ST_DEB_MSG "st%d: Async write waits %d, finished %d.\n",
+	       dev, STp->nbr_waits, STp->nbr_finished);
       }
 #endif
 
@@ -679,7 +689,7 @@
 	SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
 
 	if ((STp->buffer)->last_result_fatal != 0)
-	  printk("st%d: Error on write filemark.\n", dev);
+	  printk(KERN_ERR "st%d: Error on write filemark.\n", dev);
 	else {
 	  if ((STp->mt_status)->mt_fileno >= 0)
 	      (STp->mt_status)->mt_fileno++ ;
@@ -691,10 +701,11 @@
 
 #if DEBUG
       if (debugging)
-	printk("st%d: Buffer flushed, %d EOF(s) written\n", dev, cmd[4]);
+	printk(ST_DEB_MSG "st%d: Buffer flushed, %d EOF(s) written\n",
+	       dev, cmd[4]);
 #endif
     }
-    else if (!rewind) {
+    else if (!STp->rew_at_close) {
 #if ST_IN_FILE_POS
       flush_buffer(inode, filp, 0);
 #else
@@ -703,7 +714,7 @@
 #endif
     }
 
-    if (rewind)
+    if (STp->rew_at_close)
       st_int_ioctl(inode, filp, MTREW, 1);
 
     if (STp->door_locked == ST_LOCKED_AUTO)
@@ -749,7 +760,7 @@
 
 #if DEBUG
     if (!STp->in_use) {
-      printk("st%d: Incorrect device.\n", dev);
+      printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
       return (-EIO);
     }
 #endif
@@ -758,18 +769,18 @@
       return (-EACCES);
 
     if (STp->block_size == 0 &&
-	count > (STp->buffer)->buffer_size &&
-	!enlarge_buffer(STp->buffer, count))
+       count > (STp->buffer)->buffer_size &&
+       !enlarge_buffer(STp->buffer, count))
       return (-EOVERFLOW);
 
     if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
-	!st_int_ioctl(inode, filp, MTLOCK, 0))
+       !st_int_ioctl(inode, filp, MTLOCK, 0))
       STp->door_locked = ST_LOCKED_AUTO;
 
     if (STp->rw == ST_READING) {
       retval = flush_buffer(inode, filp, 0);
       if (retval)
-	return retval;
+       return retval;
       STp->rw = ST_WRITING;
     }
 
@@ -781,7 +792,7 @@
       if ((STp->buffer)->last_result_fatal) {
 #if DEBUG
 	if (debugging)
-	  printk("st%d: Async write error (write) %x.\n", dev,
+	  printk(ST_DEB_MSG "st%d: Async write error (write) %x.\n", dev,
 		 (STp->buffer)->last_result);
 #endif
 	if ((STp->buffer)->last_result == INT_MAX) {
@@ -793,7 +804,6 @@
 	return retval;
       }
     }
-
     if (STp->eof == ST_EOM_OK)
       return (-ENOSPC);
     else if (STp->eof == ST_EOM_ERROR)
@@ -852,7 +862,7 @@
       if ((STp->buffer)->last_result_fatal != 0) {
 #if DEBUG
 	if (debugging)
-	  printk("st%d: Error on write:\n", dev);
+	  printk(ST_DEB_MSG "st%d: Error on write:\n", dev);
 #endif
 	if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
 	    (SCpnt->sense_buffer[2] & 0x40)) {
@@ -880,7 +890,7 @@
 	    retval = (-ENOSPC); /* EOM within current request */
 #if DEBUG
 	    if (debugging)
-	      printk("st%d: EOM with %d bytes unwritten.\n",
+	      printk(ST_DEB_MSG "st%d: EOM with %d bytes unwritten.\n",
 		     dev, transfer);
 #endif
 	  }
@@ -890,7 +900,7 @@
 	    retval = (-EIO); /* EOM for old data */
 #if DEBUG
 	    if (debugging)
-	      printk("st%d: EOM with lost data.\n", dev);
+	      printk(ST_DEB_MSG "st%d: EOM with lost data.\n", dev);
 #endif
 	  }
 	}
@@ -994,7 +1004,7 @@
       return (-EIO);
 #if DEBUG
     if (!STp->in_use) {
-      printk("st%d: Incorrect device.\n", dev);
+      printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
       return (-EIO);
     }
 #endif
@@ -1023,7 +1033,7 @@
 
 #if DEBUG
     if (debugging && STp->eof != ST_NOEOF)
-      printk("st%d: EOF flag up. Bytes %d\n", dev,
+      printk(ST_DEB_MSG "st%d: EOF flag up. Bytes %d\n", dev,
 	     (STp->buffer)->buffer_bytes);
 #endif
     if (((STp->buffer)->buffer_bytes == 0) &&
@@ -1070,7 +1080,8 @@
 	if ((STp->buffer)->last_result_fatal) {
 #if DEBUG
 	  if (debugging)
-	    printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev,
+	    printk(ST_DEB_MSG "st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
+		   dev,
 		   SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
 		   SCpnt->sense_buffer[2], SCpnt->sense_buffer[3],
 		   SCpnt->sense_buffer[4], SCpnt->sense_buffer[5],
@@ -1097,7 +1108,7 @@
 		  (STp->buffer)->buffer_bytes = bytes - transfer;
 		}
 		else {
-		  printk("st%d: Incorrect block size.\n", dev);
+		  printk(KERN_NOTICE "st%d: Incorrect block size.\n", dev);
 		  SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
 		  return (-EIO);
 		}
@@ -1111,7 +1122,7 @@
 		    bytes - transfer * STp->block_size;
 #if DEBUG
 		if (debugging)
-		  printk("st%d: EOM detected (%d bytes read).\n", dev,
+		  printk(ST_DEB_MSG "st%d: EOM detected (%d bytes read).\n", dev,
 			 (STp->buffer)->buffer_bytes);
 #endif
 	      }
@@ -1124,7 +1135,7 @@
 		    bytes - transfer * STp->block_size;
 #if DEBUG
 		if (debugging)
-		  printk(
+		  printk(ST_DEB_MSG
 		    "st%d: EOF detected (%d bytes read, transferred %d bytes).\n",
 			 dev, (STp->buffer)->buffer_bytes, total);
 #endif
@@ -1133,7 +1144,7 @@
 	    else { /* nonzero sense key */
 #if DEBUG
 	      if (debugging)
-		printk("st%d: Tape error while reading.\n", dev);
+		printk(ST_DEB_MSG "st%d: Tape error while reading.\n", dev);
 #endif
 	      SCpnt->request.rq_status = RQ_INACTIVE;
 	      STp->drv_block = (-1);
@@ -1143,7 +1154,8 @@
 		       (SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK) {
 #if DEBUG
 		if (debugging)
-		  printk("st%d: Zero returned for first BLANK CHECK after EOF.\n",
+		  printk(ST_DEB_MSG
+			 "st%d: Zero returned for first BLANK CHECK after EOF.\n",
 			 dev);
 #endif
 		STp->eof = ST_EOD;
@@ -1175,7 +1187,7 @@
       if ((STp->buffer)->buffer_bytes > 0) {
 #if DEBUG
 	if (debugging && STp->eof != ST_NOEOF)
-	  printk("st%d: EOF up. Left %d, needed %d.\n", dev,
+	  printk(ST_DEB_MSG "st%d: EOF up. Left %d, needed %d.\n", dev,
 		 (STp->buffer)->buffer_bytes, count - total);
 #endif
 	transfer = (STp->buffer)->buffer_bytes < count - total ?
@@ -1236,24 +1248,24 @@
     STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
 #if DEBUG
     debugging = (options & MT_ST_DEBUGGING) != 0;
-    printk(
-"st%d: options: buffer writes: %d, async writes: %d, read ahead: %d\n",
-	   dev, STp->do_buffer_writes, STp->do_async_writes,
-	   STp->do_read_ahead);
-    printk("              two FMs: %d, fast mteom: %d auto lock: %d, debugging: %d\n",
-	   STp->two_fm, STp->fast_mteom, STp->do_auto_lock, debugging);
+    printk(ST_DEB_MSG
+	   "st%d: options: buffer writes: %d, async writes: %d, read ahead: %d\n",
+	   dev, STp->do_buffer_writes, STp->do_async_writes, STp->do_read_ahead);
+    printk(ST_DEB_MSG
+	   "st%d:          two FMs: %d, fast mteom: %d auto lock: %d, debugging: %d\n",
+	   dev, STp->two_fm, STp->fast_mteom, STp->do_auto_lock, debugging);
 #endif
   }
   else if ((options & MT_ST_OPTIONS) == MT_ST_WRITE_THRESHOLD) {
     value = (options & ~MT_ST_OPTIONS) * ST_BLOCK_SIZE;
     if (value < 1 || value > st_buffer_size) {
-      printk("st: Write threshold %d too small or too large.\n",
+      printk(KERN_WARNING "st: Write threshold %d too small or too large.\n",
 	     value);
       return (-EIO);
     }
     STp->write_threshold = value;
 #if DEBUG
-    printk("st%d: Write threshold set to %d bytes.\n", dev,
+    printk(ST_DEB_MSG "st%d: Write threshold set to %d bytes.\n", dev,
 	   STp->write_threshold);
 #endif
   }
@@ -1297,8 +1309,8 @@
        cmd[4] = arg;
 #if DEBUG
        if (debugging)
-	 printk("st%d: Spacing tape forward over %d filemarks.\n", dev,
-		cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
+	 printk(ST_DEB_MSG "st%d: Spacing tape forward over %d filemarks.\n",
+		dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 #endif
        if (fileno >= 0)
 	 fileno += arg;
@@ -1318,7 +1330,8 @@
 	 if (cmd[2] & 0x80)
 	   ltmp = 0xff000000;
 	 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
-	 printk("st%d: Spacing tape backward over %ld filemarks.\n", dev, (-ltmp));
+	 printk(ST_DEB_MSG "st%d: Spacing tape backward over %ld filemarks.\n",
+		dev, (-ltmp));
        }
 #endif
        if (fileno >= 0)
@@ -1334,7 +1347,7 @@
        cmd[4] = arg;
 #if DEBUG
        if (debugging)
-	 printk("st%d: Spacing tape forward %d blocks.\n", dev,
+	 printk(ST_DEB_MSG "st%d: Spacing tape forward %d blocks.\n", dev,
 		cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 #endif
        if (blkno >= 0)
@@ -1353,7 +1366,7 @@
 	 if (cmd[2] & 0x80)
 	   ltmp = 0xff000000;
 	 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
-	 printk("st%d: Spacing tape backward %ld blocks.\n", dev, (-ltmp));
+	 printk(ST_DEB_MSG "st%d: Spacing tape backward %ld blocks.\n", dev, (-ltmp));
        }
 #endif
        if (blkno >= 0)
@@ -1368,7 +1381,7 @@
        cmd[4] = arg;
 #if DEBUG
        if (debugging)
-	 printk("st%d: Spacing tape forward %d setmarks.\n", dev,
+	 printk(ST_DEB_MSG "st%d: Spacing tape forward %d setmarks.\n", dev,
 		cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 #endif
        if (arg != 0) {
@@ -1388,7 +1401,8 @@
 	 if (cmd[2] & 0x80)
 	   ltmp = 0xff000000;
 	 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
-	 printk("st%d: Spacing tape backward %ld setmarks.\n", dev, (-ltmp));
+	 printk(ST_DEB_MSG "st%d: Spacing tape backward %ld setmarks.\n",
+		dev, (-ltmp));
        }
 #endif
        if (arg != 0) {
@@ -1410,10 +1424,10 @@
 #if DEBUG
        if (debugging) {
 	 if (cmd_in == MTWEOF)
-	   printk("st%d: Writing %d filemarks.\n", dev,
+	   printk(ST_DEB_MSG "st%d: Writing %d filemarks.\n", dev,
 		  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
 	 else
-	   printk("st%d: Writing %d setmarks.\n", dev,
+	   printk(ST_DEB_MSG "st%d: Writing %d setmarks.\n", dev,
 		  cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
        }
 #endif
@@ -1430,26 +1444,32 @@
 #endif
 #if DEBUG
        if (debugging)
-	 printk("st%d: Rewinding tape.\n", dev);
+	 printk(ST_DEB_MSG "st%d: Rewinding tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0 ;
        break; 
      case MTOFFL:
+     case MTLOAD:
+     case MTUNLOAD:
        cmd[0] = START_STOP;
+       if (cmd_in == MTLOAD)
+	 cmd[4] |= 1;
 #if ST_NOWAIT
        cmd[1] = 1;  /* Don't wait for completion */
        timeout = ST_TIMEOUT;
+#else
+       timeout = ST_LONG_TIMEOUT * 8;
 #endif
 #if DEBUG
        if (debugging)
-	 printk("st%d: Unloading tape.\n", dev);
+	 printk(ST_DEB_MSG "st%d: Unloading tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0 ;
        break; 
      case MTNOP:
 #if DEBUG
        if (debugging)
-	 printk("st%d: No op on tape.\n", dev);
+	 printk(ST_DEB_MSG "st%d: No op on tape.\n", dev);
 #endif
        return 0;  /* Should do something ? */
        break;
@@ -1462,7 +1482,7 @@
        cmd[4] = 3;
 #if DEBUG
        if (debugging)
-	 printk("st%d: Retensioning tape.\n", dev);
+	 printk(ST_DEB_MSG "st%d: Retensioning tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0;
        break; 
@@ -1484,7 +1504,7 @@
        cmd[1] = 3;
 #if DEBUG
        if (debugging)
-	 printk("st%d: Spacing to end of recorded medium.\n", dev);
+	 printk(ST_DEB_MSG "st%d: Spacing to end of recorded medium.\n", dev);
 #endif
        blkno = 0;
        at_sm = 0;
@@ -1502,7 +1522,7 @@
 #endif
 #if DEBUG
        if (debugging)
-	 printk("st%d: Erasing tape.\n", dev);
+	 printk(ST_DEB_MSG "st%d: Erasing tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0 ;
        break;
@@ -1511,7 +1531,7 @@
        cmd[4] = SCSI_REMOVAL_PREVENT;
 #if DEBUG
        if (debugging)
-	 printk("st%d: Locking drive door.\n", dev);
+	 printk(ST_DEB_MSG "st%d: Locking drive door.\n", dev);
 #endif;
        break;
      case MTUNLOCK:
@@ -1519,21 +1539,9 @@
        cmd[4] = SCSI_REMOVAL_ALLOW;
 #if DEBUG
        if (debugging)
-	 printk("st%d: Unlocking drive door.\n", dev);
+	 printk(ST_DEB_MSG "st%d: Unlocking drive door.\n", dev);
 #endif;
        break;
-     case MTLOAD:
-     case MTUNLOAD:
-       cmd[0] = START_STOP;
-       if (cmd_in == MTLOAD)
-	 cmd[4] |= 1;
-#if ST_NOWAIT
-       cmd[1] |= 2;  /* Don't wait for completion */
-       timeout = ST_TIMEOUT;
-#else
-       timeout = ST_LONG_TIMEOUT * 8;
-#endif
-       break;
      case MTSEEK:
        if ((STp->device)->scsi_level < SCSI_2) {
 	 cmd[0] = QFA_SEEK_BLOCK;
@@ -1556,7 +1564,7 @@
 #endif
 #if DEBUG
        if (debugging)
-	 printk("st%d: Seeking tape to block %ld.\n", dev, arg);
+	 printk(ST_DEB_MSG "st%d: Seeking tape to block %ld.\n", dev, arg);
 #endif
        fileno = blkno = (-1);
        at_sm = 0;
@@ -1570,7 +1578,7 @@
 	   arg != 0 &&
 	   (arg < STp->min_block || arg > STp->max_block ||
 	    arg > st_buffer_size)) {
-	 printk("st%d: Illegal block size.\n", dev);
+	 printk(KERN_WARNING "st%d: Illegal block size.\n", dev);
 	 return (-EINVAL);
        }
        cmd[0] = MODE_SELECT;
@@ -1598,21 +1606,20 @@
 #if DEBUG
        if (debugging) {
 	 if (cmd_in == MTSETBLK)
-	   printk("st%d: Setting block size to %d bytes.\n", dev,
+	   printk(ST_DEB_MSG "st%d: Setting block size to %d bytes.\n", dev,
 		  (STp->buffer)->b_data[9] * 65536 +
 		  (STp->buffer)->b_data[10] * 256 +
 		  (STp->buffer)->b_data[11]);
 	 else if (cmd_in == MTSETDENSITY)
-	   printk("st%d: Setting density code to %x.\n", dev,
+	   printk(ST_DEB_MSG "st%d: Setting density code to %x.\n", dev,
 		  (STp->buffer)->b_data[4]);
 	 else
-	   printk("st%d: Setting drive buffer code to %d.\n", dev,
+	   printk(ST_DEB_MSG "st%d: Setting drive buffer code to %d.\n", dev,
 		  ((STp->buffer)->b_data[2] >> 4) & 7);
        }
 #endif
        break;
      default:
-       printk("st%d: Unknown st_ioctl command %x.\n", dev, cmd_in);
        return (-ENOSYS);
      }
 
@@ -1665,6 +1672,11 @@
        STp->eof = ST_NOEOF;
        STp->eof_hit = 0;
      }
+     if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
+       STp->rew_at_close = 0;
+     else if (cmd_in == MTLOAD)
+       STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
+
    } else {  /* SCSI command was not completely successful */
      if (SCpnt->sense_buffer[2] & 0x40) {
        if (cmd_in != MTBSF && cmd_in != MTBSFM &&
@@ -1745,7 +1757,7 @@
    STp = &(scsi_tapes[dev]);
 #if DEBUG
    if (debugging && !STp->in_use) {
-     printk("st%d: Incorrect device.\n", dev);
+     printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
      return (-EIO);
    }
 #endif
@@ -1772,6 +1784,18 @@
      memcpy_fromfs((char *) &mtc, (char *)arg, sizeof(struct mtop));
 
      if (!(STp->device)->was_reset) {
+
+       if (STp->eof_hit) {
+	 if (mtc.mt_op == MTFSF || mtc.mt_op == MTEOM) {
+	   mtc.mt_count -= 1;
+	   (STp->mt_status)->mt_fileno += 1;
+	 }
+	 else if (mtc.mt_op == MTBSF) {
+	   mtc.mt_count += 1;
+	   (STp->mt_status)->mt_fileno += 1;
+	 }
+       }
+
        i = flush_buffer(inode, file, mtc.mt_op == MTSEEK ||
 			mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
 			mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
@@ -1796,7 +1820,8 @@
        if (STp->door_locked != ST_UNLOCKED &&
 	   STp->door_locked != ST_LOCK_FAILS) {
 	 if (st_int_ioctl(inode, file, MTLOCK, 0)) {
-	   printk("st%d: Could not relock door after bus reset.\n", dev);
+	   printk(KERN_NOTICE "st%d: Could not relock door after bus reset.\n",
+		  dev);
 	   STp->door_locked = ST_UNLOCKED;
 	 }
        }
@@ -1874,7 +1899,7 @@
        return (-EIO);
 #if DEBUG
      if (debugging)
-       printk("st%d: get tape position.\n", dev);
+       printk(ST_DEB_MSG "st%d: get tape position.\n", dev);
 #endif
      if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos))
        return (-EINVAL);
@@ -1904,7 +1929,7 @@
        mt_pos.mt_blkno = (-1);
 #if DEBUG
        if (debugging)
-	 printk("st%d: Can't read tape position.\n", dev);
+	 printk(ST_DEB_MSG "st%d: Can't read tape position.\n", dev);
 #endif
        result = (-EIO);
      }
@@ -1960,14 +1985,15 @@
     }
   }
   if (!tb) {
-    printk("st: Can't allocate new tape buffer (nbr %d).\n", st_nbr_buffers);
+    printk(KERN_NOTICE "st: Can't allocate new tape buffer (nbr %d).\n",
+	   st_nbr_buffers);
     return NULL;
   }
 
 #if DEBUG
   if (debugging)
-    printk("st: Allocated tape buffer %d (%d bytes).\n", st_nbr_buffers,
-	   a_size);
+    printk(ST_DEB_MSG "st: Allocated tape buffer %d (%d bytes).\n",
+	   st_nbr_buffers, a_size);
 #endif
   tb->in_use = 0;
   tb->buffer_size = a_size;
@@ -1996,7 +2022,7 @@
 
 #if DEBUG
   if (debugging)
-    printk("st: Buffer enlarged to %d bytes.\n", a_size);
+    printk(ST_DEB_MSG "st: Buffer enlarged to %d bytes.\n", a_size);
 #endif
 
   STbuffer->orig_b_data = STbuffer->b_data;
@@ -2021,14 +2047,15 @@
 
 #if DEBUG
   if (debugging)
-    printk("st: Buffer normalized to %d bytes.\n", STbuffer->buffer_size);
+    printk(ST_DEB_MSG "st: Buffer normalized to %d bytes.\n",
+	   STbuffer->buffer_size);
 #endif
 }
 
 
 /* Set the boot options. Syntax: st=xxx,yyy
-   where xxx is buffer size in 512 byte blocks and yyy is write threshold
-   in 512 byte blocks. */
+   where xxx is buffer size in 1024 byte blocks and yyy is write threshold
+   in 1024 byte blocks. */
 	void
 st_setup(char *str, int *ints)
 {
@@ -2107,7 +2134,7 @@
 {
   if(SDp->type != TYPE_TAPE) return 0;
 
-  printk("Detected scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n", 
+  printk(KERN_NOTICE "Detected scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n", 
 	 st_template.dev_noticed++,
 	 SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); 
   
@@ -2129,7 +2156,7 @@
 
   if(!st_registered) {
     if (register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops)) {
-      printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR);
+      printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",MAJOR_NR);
       return 1;
     }
     st_registered++;
@@ -2143,13 +2170,13 @@
     (Scsi_Tape *) scsi_init_malloc(st_template.dev_max * sizeof(Scsi_Tape),
 				   GFP_ATOMIC);
   if (scsi_tapes == NULL) {
-    printk("Unable to allocate descriptors for SCSI tapes.\n");
+    printk(KERN_ERR "Unable to allocate descriptors for SCSI tapes.\n");
     unregister_chrdev(SCSI_TAPE_MAJOR, "st");
     return 1;
   }
 
 #if DEBUG
-  printk("st: Buffer size %d bytes, write threshold %d bytes.\n",
+  printk(ST_DEB_MSG "st: Buffer size %d bytes, write threshold %d bytes.\n",
 	 st_buffer_size, st_write_threshold);
 #endif
 
@@ -2185,7 +2212,7 @@
     (ST_buffer **) scsi_init_malloc(st_template.dev_max * sizeof(ST_buffer *),
 				    GFP_ATOMIC);
   if (st_buffers == NULL) {
-    printk("Unable to allocate tape buffer pointers.\n");
+    printk(KERN_ERR "Unable to allocate tape buffer pointers.\n");
     unregister_chrdev(SCSI_TAPE_MAJOR, "st");
     scsi_init_free((char *) scsi_tapes,
 		   st_template.dev_max * sizeof(Scsi_Tape));
@@ -2204,7 +2231,7 @@
   for (i=st_nbr_buffers=0; i < target_nbr; i++) {
     if (!new_tape_buffer(TRUE)) {
       if (i == 0) {
-	printk("Can't continue without at least one tape buffer.\n");
+	printk(KERN_ERR "Can't continue without at least one tape buffer.\n");
 	unregister_chrdev(SCSI_TAPE_MAJOR, "st");
 	scsi_init_free((char *) st_buffers,
 		       st_template.dev_max * sizeof(ST_buffer *));
@@ -2212,7 +2239,7 @@
 		       st_template.dev_max * sizeof(Scsi_Tape));
 	return 1;
       }
-      printk("Number of tape buffers adjusted.\n");
+      printk(KERN_INFO "Number of tape buffers adjusted.\n");
       break;
     }
   }
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/st.h linux/drivers/scsi/st.h
--- v1.3.47/linux/drivers/scsi/st.h	Mon Oct 23 18:02:12 1995
+++ linux/drivers/scsi/st.h	Sun Dec 17 10:59:24 1995
@@ -45,6 +45,7 @@
   unsigned char fast_mteom;
   unsigned char density;
   unsigned char door_locked;
+  unsigned char rew_at_close;
   ST_buffer * buffer;
   struct semaphore sem;
   int block_size;
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/st_options.h linux/drivers/scsi/st_options.h
--- v1.3.47/linux/drivers/scsi/st_options.h	Wed Sep 27 15:59:59 1995
+++ linux/drivers/scsi/st_options.h	Sun Dec 17 10:59:24 1995
@@ -3,7 +3,7 @@
 
    Copyright 1995 Kai Makisara.
 
-   Last modified: Sun Sep 24 11:46:15 1995 by root@kai.makisara.fi
+   Last modified: Thu Dec 14 21:51:27 1995 by root@kai.makisara.fi
 */
 
 #ifndef _ST_OPTIONS_H
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/t128.c linux/drivers/scsi/t128.c
--- v1.3.47/linux/drivers/scsi/t128.c	Mon Oct 23 18:02:12 1995
+++ linux/drivers/scsi/t128.c	Thu Dec 14 08:16:52 1995
@@ -393,3 +393,10 @@
 }
 
 #include "NCR5380.c"
+
+#ifdef MODULE
+/* Eventually this will go into an include file, but this will be later */
+Scsi_Host_Template driver_template = TRANTOR_T128;
+
+#include "scsi_module.c"
+#endif
diff -u --recursive --new-file v1.3.47/linux/drivers/scsi/t128.h linux/drivers/scsi/t128.h
--- v1.3.47/linux/drivers/scsi/t128.h	Mon Sep 18 14:54:04 1995
+++ linux/drivers/scsi/t128.h	Thu Dec 14 08:16:52 1995
@@ -115,7 +115,7 @@
  * macros when this is being used solely for the host stub.
  */
 
-#ifdef HOSTS_C
+#if defined(HOSTS_C) || defined(MODULE)
 
 #define TRANTOR_T128 {NULL, NULL, NULL, NULL, \
 	"Trantor T128/T128F/T228", t128_detect, NULL,  \
@@ -125,7 +125,9 @@
 	/* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL,			\
 	/* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING}
 
-#else
+#endif
+
+#ifndef(HOSTS_C)
 
 #define NCR5380_implementation_fields \
     volatile unsigned char *base
diff -u --recursive --new-file v1.3.47/linux/fs/buffer.c linux/fs/buffer.c
--- v1.3.47/linux/fs/buffer.c	Mon Dec 11 15:42:03 1995
+++ linux/fs/buffer.c	Thu Dec 14 08:16:52 1995
@@ -588,7 +588,7 @@
 				 continue;
 			 }
 			 
-			 if (bh->b_count || bh->b_size != size)
+			 if (bh->b_count || buffer_protected(bh) || bh->b_size != size)
 				  continue;
 			 
 			 /* Buffers are written in the order they are placed 
@@ -632,6 +632,8 @@
 			 panic("Busy buffer in candidate list\n");
 		if (mem_map[MAP_NR((unsigned long) bh->b_data)].count != 1)
 			 panic("Shared buffer in candidate list\n");
+		if (buffer_protected(bh))
+			panic("Protected buffer in candidate list\n");
 		if (BADNESS(bh)) panic("Buffer in candidate list with BADNESS != 0\n");
 		
 		if(bh->b_dev == B_FREE)
@@ -780,7 +782,7 @@
 	}
 	if (buffer_dirty(buf))
 		dispose = BUF_DIRTY;
-	else if (mem_map[MAP_NR((unsigned long) buf->b_data)].count > 1)
+	else if ((mem_map[MAP_NR((unsigned long) buf->b_data)].count > 1) || buffer_protected(buf))
 		dispose = BUF_SHARED;
 	else if (buffer_locked(buf))
 		dispose = BUF_LOCKED;
@@ -838,6 +840,10 @@
 		printk("Aieee... bforget(): shared buffer\n");
 		return;
 	}
+	if (buffer_protected(buf)) {
+		printk("Aieee... bforget(): protected buffer\n");
+		return;
+	}
 	mark_buffer_clean(buf);
 	buf->b_count = 0;
 	remove_from_queues(buf);
@@ -1315,7 +1321,8 @@
 	do {
 		if (!tmp)
 			return 0;
-		if (tmp->b_count || buffer_dirty(tmp) || buffer_locked(tmp) || tmp->b_wait)
+		if (tmp->b_count || buffer_protected(tmp) ||
+		    buffer_dirty(tmp) || buffer_locked(tmp) || tmp->b_wait)
 			return 0;
 		if (priority && buffer_touched(tmp))
 			return 0;
@@ -1465,7 +1472,8 @@
 		bh = free_list[isize];
 		if(!bh) continue;
 		for (i=0 ; !i || bh != free_list[isize]; bh = bh->b_next_free, i++) {
-			if (bh->b_count || !bh->b_this_page)
+			if (bh->b_count || buffer_protected(bh) ||
+			    !bh->b_this_page)
 				 continue;
 			if (!age_of((unsigned long) bh->b_data) &&
 			    try_to_free(bh, &bh, 6))
@@ -1494,7 +1502,8 @@
 			/* We may have stalled while waiting for I/O
 			   to complete. */
 			if(bh->b_list != nlist) goto repeat1;
-			if (bh->b_count || !bh->b_this_page)
+			if (bh->b_count || buffer_protected(bh) ||
+			    !bh->b_this_page)
 				 continue;
 			if(size && bh->b_size != size) continue;
 			if (buffer_locked(bh))
@@ -1530,6 +1539,7 @@
 {
 	struct buffer_head * bh;
 	int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0;
+	int protected = 0;
 	int shared;
 	int nlist, isize;
 
@@ -1538,13 +1548,15 @@
 	printk("Buffer blocks:   %6d\n",nr_buffers);
 
 	for(nlist = 0; nlist < NR_LIST; nlist++) {
-	  shared = found = locked = dirty = used = lastused = 0;
+	  shared = found = locked = dirty = used = lastused = protected = 0;
 	  bh = lru_list[nlist];
 	  if(!bh) continue;
 	  do {
 		found++;
 		if (buffer_locked(bh))
 			locked++;
+		if (buffer_protected(bh))
+			protected++;
 		if (buffer_dirty(bh))
 			dirty++;
 		if(mem_map[MAP_NR(((unsigned long) bh->b_data))].count !=1) shared++;
@@ -1552,10 +1564,11 @@
 			used++, lastused = found;
 		bh = bh->b_next_free;
 	      } while (bh != lru_list[nlist]);
-	printk("Buffer[%d] mem: %d buffers, %d used (last=%d), %d locked, %d dirty %d shrd\n",
-		nlist, found, used, lastused, locked, dirty, shared);
+	printk("Buffer[%d] mem: %d buffers, %d used (last=%d), %d locked, "
+	       "%d protected, %d dirty %d shrd\n",
+		nlist, found, used, lastused, locked, protected, dirty, shared);
 	};
-	printk("Size    [LAV]     Free  Clean  Unshar     Lck    Lck1   Dirty  Shared\n");
+	printk("Size    [LAV]     Free  Clean  Unshar     Lck    Lck1   Dirty  Shared \n");
 	for(isize = 0; isize<NR_SIZES; isize++){
 		printk("%5d [%5d]: %7d ", bufferindex_size[isize],
 		       buffers_lav[isize], nr_free[isize]);
@@ -1587,7 +1600,8 @@
 		if (!tmp)
 			 return 0;
 		
-		if (tmp->b_count || buffer_dirty(tmp) || buffer_locked(tmp))
+		if (tmp->b_count || buffer_protected(tmp) ||
+		    buffer_dirty(tmp) || buffer_locked(tmp))
 			 return 0;
 		tmp = tmp->b_this_page;
 	} while (tmp != bh);
@@ -1792,8 +1806,11 @@
 
 static void wakeup_bdflush(int wait)
 {
-	if(!bdflush_running){
-		printk("Warning - bdflush not running\n");
+	extern int	rd_loading;
+	
+	if (!bdflush_running){
+		if (!rd_loading)
+			printk("Warning - bdflush not running\n");
 		sync_buffers(0,0);
 		return;
 	};
diff -u --recursive --new-file v1.3.47/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v1.3.47/linux/fs/hpfs/hpfs_fs.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/hpfs/hpfs_fs.c	Sun Dec 17 11:17:20 1995
@@ -232,7 +232,7 @@
 /* forwards */
 
 static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
-		      int *lowercase, int *conv);
+		      int *lowercase, int *conv, int *nocheck);
 static int check_warn(int not_ok,
 		      const char *p1, const char *p2, const char *p3);
 static int zerop(void *addr, unsigned len);
@@ -344,6 +344,7 @@
 	int lowercase;
 	int conv;
 	int dubious;
+	int nocheck;
 
 	MOD_INC_USE_COUNT;
 
@@ -351,7 +352,8 @@
 	 * Get the mount options
 	 */
 
-	if (!parse_opts(options, &uid, &gid, &umask, &lowercase, &conv)) {
+	if (!parse_opts(options, &uid, &gid, &umask, &lowercase, &conv,
+				 &nocheck)) {
 		printk("HPFS: syntax error in mount options.  Not mounted.\n");
 		s->s_dev = 0;
 		MOD_DEC_USE_COUNT;
@@ -414,7 +416,7 @@
 	 * so don't
 	 */
 
-	if (dubious)
+	if (dubious && !nocheck)
 		goto bail2;
 
 	dubious |= check_warn((spareblock->n_dnode_spares !=
@@ -544,7 +546,7 @@
  */
 
 static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
-		      int *lowercase, int *conv)
+		      int *lowercase, int *conv, int *nocheck)
 {
 	char *p, *rhs;
 
@@ -553,6 +555,7 @@
 	*umask = current->fs->umask;
 	*lowercase = 1;
 	*conv = CONV_BINARY;
+        *nocheck = 0;
 
 	if (!opts)
 		return 1;
@@ -599,6 +602,8 @@
 			else
 				return 0;
 		}
+		else if (!strcmp(p,"nocheck")) 
+			*nocheck=1;
 		else
 			return 1;
 	}
diff -u --recursive --new-file v1.3.47/linux/fs/inode.c linux/fs/inode.c
--- v1.3.47/linux/fs/inode.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/inode.c	Fri Dec 15 07:25:02 1995
@@ -150,7 +150,7 @@
 
 	wait_on_inode(inode);
 	if (IS_WRITABLE(inode)) {
-		if (inode->i_sb->dq_op)
+		if (inode->i_sb && inode->i_sb->dq_op)
 			inode->i_sb->dq_op->drop(inode);
 	}
 	remove_inode_hash(inode);
@@ -415,7 +415,7 @@
 
 	inode->i_count--;
 	if (IS_WRITABLE(inode)) {
-		if (inode->i_sb->dq_op)
+		if (inode->i_sb && inode->i_sb->dq_op)
 			inode->i_sb->dq_op->drop(inode);
 	}
 
@@ -540,6 +540,7 @@
 	inode->i_sb = sb;
 	inode->i_dev = sb->s_dev;
 	inode->i_ino = nr;
+	inode->i_flags = sb->s_flags;
 	put_last_free(inode);
 	insert_inode_hash(inode);
 	read_inode(inode);
diff -u --recursive --new-file v1.3.47/linux/fs/msdos/file.c linux/fs/msdos/file.c
--- v1.3.47/linux/fs/msdos/file.c	Sat Nov 11 17:41:33 1995
+++ linux/fs/msdos/file.c	Sun Dec 17 11:02:41 1995
@@ -283,8 +283,8 @@
 		printk("msdos_file_write: mode = %07o\n",inode->i_mode);
 		return -EINVAL;
 	}
-	/* Must not harm system files */
-	if (MSDOS_I(inode)->i_attrs & ATTR_SYS) return -EPERM;
+	/* system files are immutable */
+	if (IS_IMMUTABLE(inode)) return -EPERM;
 /*
  * ok, append may not work when many processes are writing at the same time
  * but so what. That way leads to madness anyway.
@@ -362,9 +362,8 @@
 {
 	int cluster;
 
-	/* Must not harm system files */
 	/* Why no return value?  Surely the disk could fail... */
-	if (MSDOS_I(inode)->i_attrs & ATTR_SYS) return /* -EPERM */;
+	if (IS_IMMUTABLE(inode)) return /* -EPERM */;
 	cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
 	(void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
 	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
diff -u --recursive --new-file v1.3.47/linux/fs/msdos/inode.c linux/fs/msdos/inode.c
--- v1.3.47/linux/fs/msdos/inode.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/msdos/inode.c	Sun Dec 17 11:02:41 1995
@@ -81,7 +81,9 @@
 
 	*check = 'n';
 	*conversion = 'b';
-	*dotsOK =0;
+	/* Please leave dotsOK as 1, and contact Albert Cahalan if */
+	/* it causes any problems for you. <albert@ccs.neu.edu>    */
+	*dotsOK =1;  /* see note above, and report problems */
 	*uid = current->uid;
 	*gid = current->gid;
 	*umask = current->fs->umask;
@@ -427,6 +429,8 @@
 		inode->i_nlink = 1;
 		inode->i_size = CF_LE_L(raw_entry->size);
 	}
+	if(raw_entry->attr & ATTR_SYS)
+		inode->i_flags |= S_IMMUTABLE;
 	MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->conversion,
 	    raw_entry->ext);
 	MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
diff -u --recursive --new-file v1.3.47/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v1.3.47/linux/fs/msdos/namei.c	Mon Nov 27 12:48:32 1995
+++ linux/fs/msdos/namei.c	Sun Dec 17 11:02:41 1995
@@ -452,7 +452,7 @@
 		res = -EPERM;
 		goto unlink_done;
 	}
-	if (MSDOS_I(inode)->i_attrs & ATTR_SYS){
+	if (IS_IMMUTABLE(inode)){
 		res = -EPERM;
 		goto unlink_done;
 	}
diff -u --recursive --new-file v1.3.47/linux/fs/namei.c linux/fs/namei.c
--- v1.3.47/linux/fs/namei.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/namei.c	Fri Dec 15 08:35:33 1995
@@ -371,7 +371,7 @@
 			error = -EROFS;
 		else {
 			dir->i_count++;		/* create eats the dir */
-			if (dir->i_sb->dq_op)
+			if (dir->i_sb && dir->i_sb->dq_op)
 				dir->i_sb->dq_op->initialize(dir, -1);
 			error = dir->i_op->create(dir, basename, namelen, mode, res_inode);
 			up(&dir->i_sem);
@@ -422,7 +422,7 @@
 			iput(inode);
 			return error;
 		}
-		if (inode->i_sb->dq_op)
+		if (inode->i_sb && inode->i_sb->dq_op)
 			inode->i_sb->dq_op->initialize(inode, -1);
 		newattrs.ia_size = 0;
 		newattrs.ia_valid = ATTR_SIZE;
@@ -440,7 +440,7 @@
 		put_write_access(inode);
 	} else
 		if (flag & FMODE_WRITE)
-			if (inode->i_sb->dq_op)
+			if (inode->i_sb && inode->i_sb->dq_op)
 				inode->i_sb->dq_op->initialize(inode, -1);
 	*res_inode = inode;
 	return 0;
@@ -473,7 +473,7 @@
 		return -EPERM;
 	}
 	dir->i_count++;
-	if (dir->i_sb->dq_op)
+	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
 	down(&dir->i_sem);
 	error = dir->i_op->mknod(dir,basename,namelen,mode,dev);
@@ -532,7 +532,7 @@
 		return -EPERM;
 	}
 	dir->i_count++;
-	if (dir->i_sb->dq_op)
+	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
 	down(&dir->i_sem);
 	error = dir->i_op->mkdir(dir, basename, namelen, mode & 0777 & ~current->fs->umask);
@@ -586,7 +586,7 @@
 		iput(dir);
 		return -EPERM;
 	}
-	if (dir->i_sb->dq_op)
+	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
 	return dir->i_op->rmdir(dir,basename,namelen);
 }
@@ -636,7 +636,7 @@
 		iput(dir);
 		return -EPERM;
 	}
-	if (dir->i_sb->dq_op)
+	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
 	return dir->i_op->unlink(dir,basename,namelen);
 }
@@ -680,7 +680,7 @@
 		return -EPERM;
 	}
 	dir->i_count++;
-	if (dir->i_sb->dq_op)
+	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
 	down(&dir->i_sem);
 	error = dir->i_op->symlink(dir,basename,namelen,oldname);
@@ -751,7 +751,7 @@
 		return -EPERM;
 	}
 	dir->i_count++;
-	if (dir->i_sb->dq_op)
+	if (dir->i_sb && dir->i_sb->dq_op)
 		dir->i_sb->dq_op->initialize(dir, -1);
 	down(&dir->i_sem);
 	error = dir->i_op->link(oldinode, dir, basename, namelen);
@@ -839,7 +839,7 @@
 		return -EPERM;
 	}
 	new_dir->i_count++;
-	if (new_dir->i_sb->dq_op)
+	if (new_dir->i_sb && new_dir->i_sb->dq_op)
 		new_dir->i_sb->dq_op->initialize(new_dir, -1);
 	down(&new_dir->i_sem);
 	error = old_dir->i_op->rename(old_dir, old_base, old_len, 
diff -u --recursive --new-file v1.3.47/linux/fs/open.c linux/fs/open.c
--- v1.3.47/linux/fs/open.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/open.c	Fri Dec 15 08:07:31 1995
@@ -367,6 +367,7 @@
 	struct inode * inode;
 	struct file * file;
 	struct iattr newattrs;
+	int error;
 
 	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 		return -EBADF;
@@ -400,7 +401,16 @@
 		newattrs.ia_valid |= ATTR_MODE;
 	}
 	inode->i_dirt = 1;
-	return notify_change(inode, &newattrs);
+	if (inode->i_sb->dq_op) {
+		inode->i_sb->dq_op->initialize(inode, -1);
+		if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
+			return -EDQUOT;
+		error = notify_change(inode, &newattrs);
+		if (error)
+			inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
+	} else
+		error = notify_change(inode, &newattrs);
+	return error;
 }
 
 asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
@@ -444,7 +454,15 @@
 		newattrs.ia_valid |= ATTR_MODE;
 	}
 	inode->i_dirt = 1;
-	error = notify_change(inode, &newattrs);
+	if (inode->i_sb->dq_op) {
+		inode->i_sb->dq_op->initialize(inode, -1);
+		if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
+			return -EDQUOT;
+		error = notify_change(inode, &newattrs);
+		if (error)
+			inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
+	} else
+		error = notify_change(inode, &newattrs);
 	iput(inode);
 	return(error);
 }
diff -u --recursive --new-file v1.3.47/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v1.3.47/linux/fs/umsdos/inode.c	Thu Nov  9 11:23:52 1995
+++ linux/fs/umsdos/inode.c	Sun Dec 17 11:02:41 1995
@@ -404,6 +404,7 @@
 	printk ("UMSDOS Beta 0.6 (compatibility level %d.%d, fast msdos)\n"
 		,UMSDOS_VERSION,UMSDOS_RELEASE);
 	if (sb != NULL){
+		MSDOS_SB(sb)->dotsOK = 0;  /* disable hidden==dotfile */
 		sb->s_op = &umsdos_sops;
 		PRINTK (("umsdos_read_super %p\n",sb->s_mounted));
 		umsdos_setup_dir_inode (sb->s_mounted);
diff -u --recursive --new-file v1.3.47/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- v1.3.47/linux/include/asm-alpha/pgtable.h	Mon Dec 11 15:42:04 1995
+++ linux/include/asm-alpha/pgtable.h	Fri Dec 15 07:31:30 1995
@@ -9,17 +9,62 @@
  * in <asm/page.h> (currently 8192).
  */
 
-#define invalidate_all() \
-__asm__ __volatile__( \
-	"lda $16,-2($31)\n\t" \
-	".long 51" \
-	: : :"$1", "$16", "$17", "$22","$23","$24","$25")
-
-#define invalidate() \
-__asm__ __volatile__( \
-	"lda $16,-1($31)\n\t" \
-	".long 51" \
-	: : :"$1", "$16", "$17", "$22","$23","$24","$25")
+extern void tbi(long type, ...);
+
+#define tbisi(x)	tbi(1,(x))
+#define tbisd(x)	tbi(2,(x))
+#define tbis(x)		tbi(3,(x))
+#define tbiap()		tbi(-1)
+#define tbia()		tbi(-2)
+
+/*
+ * Invalidate current user mapping.
+ */
+static inline void invalidate(void)
+{
+	tbiap();
+}
+
+/*
+ * Invalidate everything (kernel mapping may also have
+ * changed due to vmalloc/vfree)
+ */
+static inline void invalidate_all(void)
+{
+	tbia();
+}
+
+/*
+ * Invalidate a specified user mapping
+ */
+static inline void invalidate_mm(struct mm_struct *mm)
+{
+	tbiap();
+}
+
+/*
+ * Page-granular invalidate.
+ *
+ * do a tbisd (type = 2) normally, and a tbis (type = 3)
+ * if it is an executable mapping.  We want to avoid the
+ * itlb invalidate, because that potentially also does a
+ * icache invalidate. 
+ */
+static inline void invalidate_page(struct vm_area_struct *vma,
+	unsigned long addr)
+{
+	tbi(2 + ((vma->vm_flags & VM_EXEC) != 0), addr);
+}
+
+/*
+ * Invalidate a specified range of user mapping: on the
+ * alpha we invalidate the whole user tlb
+ */
+static inline void invalidate_range(struct mm_struct *mm,
+	unsigned long start, unsigned long end)
+{
+	tbiap();
+}
 
 /* Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
@@ -143,9 +188,9 @@
 
 extern unsigned long __zero_page(void);
 
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE __zero_page()
+#define BAD_PAGETABLE	__bad_pagetable()
+#define BAD_PAGE	__bad_page()
+#define ZERO_PAGE	0xfffffc000030A000
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR			(8*sizeof(unsigned long))
diff -u --recursive --new-file v1.3.47/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v1.3.47/linux/include/asm-alpha/processor.h	Sun Oct 29 11:38:49 1995
+++ linux/include/asm-alpha/processor.h	Fri Dec 15 12:48:37 1995
@@ -46,6 +46,9 @@
 	0, 0, 0, \
 }
 
+#define alloc_kernel_stack()    get_free_page(GFP_KERNEL)
+#define free_kernel_stack(page) free_page((page))
+
 #include <asm/ptrace.h>
 
 /*
diff -u --recursive --new-file v1.3.47/linux/include/asm-alpha/termios.h linux/include/asm-alpha/termios.h
--- v1.3.47/linux/include/asm-alpha/termios.h	Thu Jul 13 16:20:21 1995
+++ linux/include/asm-alpha/termios.h	Thu Dec 14 08:16:52 1995
@@ -102,6 +102,9 @@
 #define TIOCSERGETMULTI 0x545A /* Get multiport config  */
 #define TIOCSERSETMULTI 0x545B /* Set multiport config */
 
+#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
diff -u --recursive --new-file v1.3.47/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- v1.3.47/linux/include/asm-i386/bugs.h	Wed Nov  8 07:11:41 1995
+++ linux/include/asm-i386/bugs.h	Sun Dec 17 11:17:18 1995
@@ -110,8 +110,25 @@
 	printk("Ok.\n");
 }
 
+static void check_tlb(void)
+{
+	/*
+	 * The 386 chips don't support TLB finegrained invalidation.
+	 * They will fault when they hit a invlpg instruction.
+	 */
+	if (x86 == 3) {
+#if defined(CONFIG_M486) || defined(CONFIG_M586)
+		printk("CPU is a 386 and this kernel was compiled for 486 or better.\n");
+		printk("Giving up.\n");
+		for (;;) ;
+#endif
+		return;
+	}
+}
+
 static void check_bugs(void)
 {
+	check_tlb();
 	check_fpu();
 	check_hlt();
 	system_utsname.machine[1] = '0' + x86;
diff -u --recursive --new-file v1.3.47/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v1.3.47/linux/include/asm-i386/pgtable.h	Wed Dec 13 09:02:47 1995
+++ linux/include/asm-i386/pgtable.h	Fri Dec 15 07:33:13 1995
@@ -1,6 +1,8 @@
 #ifndef _I386_PGTABLE_H
 #define _I386_PGTABLE_H
 
+#include <linux/config.h>
+
 /*
  * Define USE_PENTIUM_MM if you want the 4MB page table optimizations.
  * This works only on a intel Pentium.
@@ -33,7 +35,7 @@
 #define __invalidate() \
 __asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
 
-#ifdef __i486__
+#ifdef CONFIG_M486
 #define __invalidate_one(addr) \
 __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
 #else
@@ -51,10 +53,10 @@
 		__invalidate();
 }
 
-static inline void invalidate_page(struct mm_struct *mm,
+static inline void invalidate_page(struct vm_area_struct *vma,
 	unsigned long addr)
 {
-	if (mm == current->mm)
+	if (vma->vm_mm == current->mm)
 		__invalidate_one(addr);
 }
 
@@ -87,7 +89,7 @@
 	invalidate();
 }
 
-static inline void invalidate_page(struct mm_struct *mm,
+static inline void invalidate_page(struct vm_area_struct *vma,
 	unsigned long addr)
 {
 	invalidate();
diff -u --recursive --new-file v1.3.47/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v1.3.47/linux/include/asm-i386/processor.h	Thu Sep  7 17:17:19 1995
+++ linux/include/asm-i386/processor.h	Fri Dec 15 12:48:37 1995
@@ -124,6 +124,9 @@
 	NULL, 0, 0, 0, 0 /* vm86_info */ \
 }
 
+#define alloc_kernel_stack()    get_free_page(GFP_KERNEL)
+#define free_kernel_stack(page) free_page((page))
+
 static inline void start_thread(struct pt_regs * regs, unsigned long eip, unsigned long esp)
 {
 	regs->cs = USER_CS;
diff -u --recursive --new-file v1.3.47/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h
--- v1.3.47/linux/include/asm-i386/termios.h	Thu Jul 13 16:20:21 1995
+++ linux/include/asm-i386/termios.h	Thu Dec 14 08:16:52 1995
@@ -55,6 +55,9 @@
 #define TIOCSERGETMULTI 0x545A /* Get multiport config  */
 #define TIOCSERSETMULTI 0x545B /* Set multiport config */
 
+#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/a.out.h linux/include/asm-mips/a.out.h
--- v1.3.47/linux/include/asm-mips/a.out.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/a.out.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,26 @@
+#ifndef __ASM_MIPS_A_OUT_H
+#define __ASM_MIPS_A_OUT_H
+
+struct exec
+{
+  unsigned long a_info;		/* Use macros N_MAGIC, etc for access */
+  unsigned a_text;		/* length of text, in bytes */
+  unsigned a_data;		/* length of data, in bytes */
+  unsigned a_bss;		/* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;		/* length of symbol table data in file, in bytes */
+  unsigned a_entry;		/* start address */
+  unsigned a_trsize;		/* length of relocation info for text, in bytes */
+  unsigned a_drsize;		/* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)	((a).a_trsize)
+#define N_DRSIZE(a)	((a).a_drsize)
+#define N_SYMSIZE(a)	((a).a_syms)
+
+#ifdef __KERNEL__
+
+#define STACK_TOP	TASK_SIZE
+
+#endif
+
+#endif /* __ASM_MIPS_A_OUT_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/asm.h linux/include/asm-mips/asm.h
--- v1.3.47/linux/include/asm-mips/asm.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/asm.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,248 @@
+/*
+ * include/asm-mips/asm.h
+ *
+ * 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) 1995 by Ralf Baechle
+ *
+ * Some usefull macros for MIPS assembler code
+ *
+ * Some of the routines below contain useless nops that will be optimized
+ * away by gas in -O mode. These nops are however required to fill delay
+ * slots in noreorder mode.
+ */
+#ifndef	__ASM_ASM_H
+#define	__ASM_ASM_H
+
+#include <linux/config.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
+
+#ifndef CAT
+#ifdef __STDC__
+#define __CAT(str1,str2) str1##str2
+#else
+#define __CAT(str1,str2) str1/**/str2
+#endif
+#define CAT(str1,str2) __CAT(str1,str2)
+#endif
+
+/*
+ * Macros to handle different pointer sizes for 32/64-bit code
+ */
+#if __mips == 3
+#define PTR	.quad
+#define PTRSIZE	8
+#define PTRLOG	3
+#define lp	ld
+#else
+#define PTR	.word
+#define PTRSIZE	4
+#define PTRLOG	2
+#define lp	lw
+#endif
+
+/*
+ * ELF specific declarations
+ */
+#ifdef __ELF__
+#define TYPE(symbol,_type)                              \
+			.type	symbol,@_type
+#define SIZE(symbol,_size)                              \
+			.size	symbol,_size
+#else
+#define TYPE(symbol,type)
+#define SIZE(symbol,size)
+#endif
+
+/*
+ * PIC specific declarations
+ * Not used for the kernel but here seems to be the right place.
+ */
+#ifdef __PIC__
+#define CPRESTORE(register)                             \
+			.cprestore register
+#define CPADD(register)                                 \
+			.cpadd	register
+#define CPLOAD(register)                                \
+			.cpload	register
+#else
+#define CPRESTORE(register)
+#define CPADD(register)
+#define CPLOAD(register)
+#endif
+
+/*
+ * LEAF - declare leaf routine
+ */
+#define	LEAF(symbol)                                    \
+			.globl	symbol;                 \
+			.align	2;                      \
+			TYPE(symbol,function);          \
+			.ent	symbol,0;               \
+symbol:			.frame	sp,0,ra
+
+/*
+ * NESTED - declare nested routine entry point
+ */
+#define	NESTED(symbol, framesize, rpc)                  \
+			.globl	symbol;                 \
+			.align	2;                      \
+			TYPE(symbol,function);          \
+			.ent	symbol,0;               \
+symbol:			.frame	sp, framesize, rpc
+
+/*
+ * END - mark end of function
+ */
+#define	END(function)                                   \
+			.end	function;		\
+			SIZE(function,.-function)
+
+/*
+ * EXPORT - export definition of symbol
+ */
+#define	EXPORT(symbol)                                  \
+			.globl	symbol;                 \
+symbol:
+
+/*
+ * ABS - export absolute symbol
+ */
+#define	ABS(symbol,value)                               \
+			.globl	symbol;                 \
+symbol			=	value
+
+#define	PANIC(msg)                                      \
+			la	a0,8f;                  \
+			jal	panic;                  \
+			nop;                            \
+9:			b	9b;                     \
+			nop;                            \
+			TEXT(msg)
+
+/*
+ * Print formated string
+ */
+#define PRINT(string)                                   \
+			la	a0,8f;                  \
+			jal	printk;                 \
+			nop;                            \
+			TEXT(string)
+
+#define	TEXT(msg)                                       \
+			.data;                          \
+8:			.asciiz	msg;                    \
+			.text
+
+/*
+ * Build text tables
+ */
+#define TTABLE(string)                                  \
+		.text;                                  \
+		.word	1f;                             \
+		.data;                                  \
+1:		.asciz	string;                         \
+		.text;
+
+/*
+ * Move to kernel mode and disable interrupts
+ * Set cp0 enable bit as sign that we're running on the kernel stack
+ * Use with .set noat!
+ * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
+ * means that another three instructions will be executed with interrupts
+ * disabled.
+ */
+#define CLI                                             \
+		mfc0	AT,CP0_STATUS;                  \
+		li	t0,ST0_CU0|0x1f;                \
+		or	AT,t0;                          \
+		xori	AT,0x1f;                        \
+		mtc0	AT,CP0_STATUS;			\
+
+/*
+ * Move to kernel mode and enable interrupts
+ * Set cp0 enable bit as sign that we're running on the kernel stack
+ * Use with .set noat!
+ * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
+ * means that another three instructions will be executed with interrupts
+ * disabled.  Arch/mips/kernel/r4xx0.S makes use of this fact.
+ */
+#define STI                                             \
+		mfc0	AT,CP0_STATUS;                  \
+		li	t0,ST0_CU0|0x1f;                \
+		or	AT,t0;                          \
+		xori	AT,0x1e;                        \
+		mtc0	AT,CP0_STATUS;			\
+
+/*
+ * Special nop to fill load delay slots
+ */
+#ifndef __R4000__
+#define NOP     nop
+#else
+#define NOP
+#endif
+
+/*
+ * Return from exception
+ */
+#if defined (CONFIG_CPU_R3000)
+#define ERET rfe
+#elif defined (CONFIG_CPU_R4X00) || defined (CONFIG_CPU_R4600)
+#define ERET                                            \
+		.set	mips3;                          \
+		eret;                                   \
+		.set	mips0
+#else
+#error "Implement ERET macro!"
+#endif
+
+/*
+ * R8000/R10000 (MIPS ISA IV) pref instruction.
+ * Use with .set noreorder only!
+ */
+#if defined (CONFIG_CPU_R8000) || defined(CONFIG_CPU_R10000)
+#define PREF(hint,addr)                                 \
+		pref	hint,addr
+#define PREFX(hint,addr)                                \
+		prefx	hint,addr
+#else
+#define PREF
+#define PREFX
+#endif
+
+/*
+ * R8000/R10000 (MIPS ISA IV) movn/movz instructions and
+ * equivalents for old CPUs. Use with .set noreorder only!
+ */
+#if defined (CONFIG_CPU_R8000) || defined (CONFIG_CPU_R10000)
+#define MOVN(rd,rs,rt)                                  \
+		movn	rd,rs,rt
+#define MOVZ(rd,rs,rt)                                  \
+		movz	rd,rs,rt
+#elif defined (CONFIG_CPU_R4000) || defined (CONFIG_CPU_R6000)
+#define MOVN(rd,rs,rt)                                  \
+		bnezl	rt,9f                           \
+		move	rd,rs                           \
+9:
+#define MOVZ(rd,rs,rt)                                  \
+		beqzl	rt,9f                           \
+		movz	rd,rt                           \
+9:
+#else /* R2000, R3000 */
+#define MOVN(rd,rs,rt)                                  \
+		beqz	rt,9f                           \
+		nop                                     \
+		move	rd,rs                           \
+9:
+#define MOVZ(rd,rs,rt)                                  \
+		bneqz	rt,9f                           \
+		nop                                     \
+		movz	rd,rt                           \
+9:
+#endif
+
+#endif /* __ASM_ASM_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h
--- v1.3.47/linux/include/asm-mips/bitops.h	Sun Oct 29 11:38:49 1995
+++ linux/include/asm-mips/bitops.h	Wed Dec 13 12:39:45 1995
@@ -10,8 +10,12 @@
 #ifndef __ASM_MIPS_BITOPS_H
 #define __ASM_MIPS_BITOPS_H
 
-#ifdef __R4000__
+#if __mips > 1
 
+/*
+ * These functions for MIPS ISA >= 2 are interrupt and SMP proof and
+ * interrupt friendly
+ */
 #include <asm/mipsregs.h>
 
 /*
@@ -62,14 +66,19 @@
 	return retval;
 }
 
-#else /* !defined(__R4000__) */
+#else /* __mips <= 1 */
 
+/*
+ * These functions are only used for MIPS ISA 1 CPUs.  Since I don't
+ * believe that someone ever will run Linux/SMP on such a beast I don't
+ * worry about making them SMP proof.
+ */
 #include <asm/system.h>
 
 #ifdef __KERNEL__
 /*
- * Only disable interrupt for kernelmode stuff to keep some
- * usermode stuff alive
+ * Only disable interrupt for kernel mode stuff to keep usermode stuff
+ * that dares to use kernel include files alive.
  */
 #define __flags unsigned long flags
 #define __cli() cli()
@@ -133,17 +142,11 @@
 #undef __save_flags(x)
 #undef __restore_flags(x)
 
-#endif /* !defined(__R4000__) */
+#endif /* __mips <= 1 */
 
 extern __inline__ int test_bit(int nr, const void *addr)
 {
-	int	mask;
-	unsigned long	*a;
-
-	a = addr;
-	addr += nr >> 5;
-	mask = 1 << (nr & 0x1f);
-	return ((mask & *a) != 0);
+	return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31));
 }
 
 extern __inline__ int find_first_zero_bit (void *addr, unsigned size)
@@ -227,19 +230,17 @@
 	__asm__ __volatile__ (
 		".set\tnoreorder\n\t"
 		".set\tnoat\n\t"
-		"li\t%2,1\n"
+		"move\t%0,$0\n"
 		"1:\tand\t$1,%2,%1\n\t"
-		"beq\t$0,$1,2f\n\t"
-		"sll\t%2,%2,1\n\t"
-		"bne\t$0,%2,1b\n\t"
-		"add\t%0,%0,1\n\t"
+		"beqz\t$1,2f\n\t"
+		"sll\t%1,1\n\t"
+		"bnez\t%1,1b\n\t"
+		"addiu\t%0,1\n\t"
 		".set\tat\n\t"
 		".set\treorder\n"
 		"2:\n\t"
-		: "=r" (__res), "=r" (word), "=r" (mask)
-		: "1" (~(word)),
-		  "2" (mask),
-		  "0" (0)
+		: "=r" (__res), "=r" (mask)
+		: "r" (word), "1" (mask)
 		: "$1");
 
 	return __res;
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h
--- v1.3.47/linux/include/asm-mips/bootinfo.h	Wed Jan 18 08:54:13 1995
+++ linux/include/asm-mips/bootinfo.h	Thu Dec 14 08:16:53 1995
@@ -11,20 +11,25 @@
  * License.  See the file README.legal in the main directory of this archive
  * for more details.
  */
-
 #ifndef __ASM_MIPS_BOOTINFO_H
 #define __ASM_MIPS_BOOTINFO_H
 
 /*
- * Valid values for machtype field
+ * Valid machtype values
  */
-#define MACH_UNKNOWN		0		/* whatever... */
-#define MACH_DESKSTATION_TYNE	1		/* Deskstation Tyne    */
-#define MACH_ACER_PICA_61	2		/* Acer PICA-61 (PICA1) */
-#define MACH_MIPS_MAGNUM_4000	3		/* Mips Magnum 4000 (aka RC4030) */
+#define MACH_UNKNOWN		0		/* whatever...               */
+#define MACH_DESKSTATION_RPC44  1               /* Deskstation rPC44         */
+#define MACH_DESKSTATION_TYNE	2		/* Deskstation Tyne          */
+#define MACH_ACER_PICA_61	3		/* Acer PICA-61 (PICA1)      */
+#define MACH_MIPS_MAGNUM_4000	4		/* Mips Magnum 4000 "RC4030" */
+#define MACH_OLIVETTI_M700      5               /* Olivetti M700 */
+#define MACH_LAST               5
+
+#define MACH_NAMES { "unknown", "Deskstation rPC44", "Deskstation Tyne", \
+	"Acer PICA 61", "Mips Magnum 4000", "Olivetti M700" }
 
 /*
- * Valid values for cputype field
+ * Valid cputype values
  */
 #define CPU_UNKNOWN		0
 #define CPU_R2000		1
@@ -47,15 +52,16 @@
 #define CPU_R6000A		18
 #define CPU_R8000		19
 #define CPU_R10000		20
+#define CPU_LAST                20
 
-#define CPU_NAMES { "UNKNOWN", "R2000", "R3000", "R3000A", "R3041", "R3051", \
+#define CPU_NAMES { "unknown", "R2000", "R3000", "R3000A", "R3041", "R3051", \
         "R3052", "R3081", "R3081E", "R4000PC", "R4000SC", "R4000MC",         \
         "R4200", "R4400PC", "R4400SC", "R4400MC", "R4600", "R6000",          \
         "R6000A", "R8000", "R10000" }
 
 #define CL_SIZE      (80)
 
-#ifndef __ASSEMBLY__
+#ifndef __LANGUAGE_ASSEMBLY__
 
 /*
  * Some machine parameters passed by MILO. Note that bootinfo
@@ -68,8 +74,15 @@
 	};
 
 struct bootinfo {
-	unsigned long machtype;			/* machine type */
-	unsigned long cputype;			/* system CPU & FPU */
+	/*
+	 * machine type
+	 */
+	unsigned long machtype;
+
+	/*
+	 * system CPU & FPU
+	 */
+	unsigned long cputype;
 
 	/*
 	 * Installed RAM
@@ -101,7 +114,7 @@
 	/*
 	 * Ramdisk Info
 	 */
-	unsigned long ramdisk_size;		/* ramdisk size in 1024 byte blocks */
+	unsigned long ramdisk_flags;		/* ramdisk flags */
 	unsigned long ramdisk_base;		/* address of the ram disk in mem */
 
 	/*
@@ -119,6 +132,83 @@
   
 };
 
+#if 0
+/*
+ * New style bootinfo
+ *
+ * Add new tags only at the end of the enum; *never* remove any tags
+ * or you'll break compatibility!
+ */
+enum bi_tag {	
+	/*
+	 * not a real tag
+	 */
+	dummy,
+
+	/*
+	 * machine type
+	 */
+	machtype,
+
+	/*
+	 * system CPU & FPU
+	 */
+	cputype,
+
+	/*
+	 * Installed RAM
+	 */
+	memlower,
+	memupper,
+
+	/*
+	 * Cache Sizes (0xffffffff = unknown)
+	 */
+	icache_size,
+	icache_linesize,
+	dcache_size,
+	dcache_linesize,
+	scache_size,
+	scache_linesize,
+
+	/*
+	 * TLB Info
+	 */
+	tlb_entries,
+
+	/*
+	 * DMA buffer size (Deskstation only)
+	 */
+	dma_cache_size,
+	dma_cache_base,
+
+	/*
+	 * Ramdisk Info
+	 */
+	ramdisk_size,		/* ramdisk size in 1024 byte blocks */
+	ramdisk_base,		/* address of the ram disk in mem */
+
+	/*
+	 * Boot flags for the kernel
+	 */
+	mount_root_rdonly,
+	drive_info,
+
+	/*
+	 * Video ram info (not in tty.h)
+	 */
+	vram_base,		/* video ram base address */
+      
+	command_line		/* kernel command line parameters */
+  
+};
+
+typedef struct {
+	bi_tag		tag;
+	unsigned long	size;
+} tag;
+#endif
+
 extern struct bootinfo boot_info;
 
 /*
@@ -127,9 +217,10 @@
  * are in the .data segment since the .bss segment is
  * cleared during startup.
  */
-#define BOOT_INFO { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"" }
+#define BOOT_INFO { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, {{0,}}, 0, "" }
+#define SCREEN_INFO {0, 0, {0, }, 52, 3, 80, 4626, 3, 9, 50}
 
-#else /* !__ASSEMBLY__ */
+#else /* !__LANGUAGE_ASSEMBLY__ */
 
 /*
  * Same structure, but as offsets for usage within assembler source.
@@ -151,9 +242,11 @@
 #define OFFSET_BOOTINFO_DMA_CACHE_BASE    48
 #define OFFSET_BOOTINFO_RAMDISK_SIZE      52
 #define OFFSET_BOOTINFO_RAMDISK_BASE      56
-#define OFFSET_BOOTINFO_VRAM_BASE         60
-#define OFFSET_BOOTINFO_COMMAND_LINE      64
+#define OFFSET_BOOTINFO_MOUNT_RD_ONLY     60
+#define OFFSET_BOOTINFO_DRIVE_INFO        64
+#define OFFSET_BOOTINFO_VRAM_BASE         96
+#define OFFSET_BOOTINFO_COMMAND_LINE      100
 
-#endif /* __ASSEMBLY__ */
+#endif /* __LANGUAGE_ASSEMBLY__ */
 
 #endif /* __ASM_MIPS_BOOTINFO_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/byteorder.h linux/include/asm-mips/byteorder.h
--- v1.3.47/linux/include/asm-mips/byteorder.h	Tue Aug 15 20:39:04 1995
+++ linux/include/asm-mips/byteorder.h	Wed Dec 13 12:39:45 1995
@@ -1,19 +1,22 @@
 #ifndef __ASM_MIPS_BYTEORDER_H
 #define __ASM_MIPS_BYTEORDER_H
 
+/*
+ * FIXME: Add big endian support
+ */
 #undef ntohl
 #undef ntohs
 #undef htonl
 #undef htons
 
-#ifdef MIPSEL
+#if defined (__MIPSEL__)
 #define __LITTLE_ENDIAN
 #define __LITTLE_ENDIAN_BITFIELD
-#elif MIPSEB
+#elif defined (__MIPSEB__)
 #define __BIG_ENDIAN
 #define __BIG_ENDIAN_BITFIELD
 #else
-#error "MIPS but neither MIPSEL nor MIPSEB?"
+#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
 #endif
 
 extern unsigned long int	ntohl(unsigned long int);
@@ -21,16 +24,18 @@
 extern unsigned long int	htonl(unsigned long int);
 extern unsigned short int	htons(unsigned short int);
 
-extern unsigned long int	__ntohl(unsigned long int);
-extern unsigned short int	__ntohs(unsigned short int);
-extern unsigned long int	__constant_ntohl(unsigned long int);
-extern unsigned short int	__constant_ntohs(unsigned short int);
+extern __inline__ unsigned long int	__ntohl(unsigned long int);
+extern __inline__ unsigned short int	__ntohs(unsigned short int);
+extern __inline__ unsigned long int	__constant_ntohl(unsigned long int);
+extern __inline__ unsigned short int	__constant_ntohs(unsigned short int);
 
 /*
  * The constant and non-constant versions here are the same.
  * Maybe I'll come up with an mips-optimized routine for the
  * non-constant ones (the constant ones don't need it: gcc
- * will optimize it to the correct constant)
+ * will optimize it to the correct constant).  Oh, and the
+ * big endian routines that are still missing will be fairly
+ * easy to write :-)
  */
 
 extern __inline__ unsigned long int
@@ -42,14 +47,11 @@
 		((x & 0xff000000U) >> 24));
 }
 
-extern __inline__ unsigned long int
-__constant_ntohl(unsigned long int x)
-{
-	return (((x & 0x000000ffU) << 24) |
-		((x & 0x0000ff00U) <<  8) |
-		((x & 0x00ff0000U) >>  8) |
-		((x & 0xff000000U) >> 24));
-}
+#define __constant_ntohl(x) \
+	((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
+			     (((unsigned long int)(x) & 0x0000ff00U) <<  8) | \
+			     (((unsigned long int)(x) & 0x00ff0000U) >>  8) | \
+			     (((unsigned long int)(x) & 0xff000000U) >> 24)))
 
 extern __inline__ unsigned short int
 __ntohs(unsigned short int x)
@@ -58,12 +60,9 @@
 		((x & 0xff00) >> 8));
 }
 
-extern __inline__ unsigned short int
-__constant_ntohs(unsigned short int x)
-{
-	return (((x & 0x00ff) << 8) |
-		((x & 0xff00) >> 8));
-}
+#define __constant_ntohs(x) \
+	((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
+			      (((unsigned short int)(x) & 0xff00) >> 8))) \
 
 #define __htonl(x) __ntohl(x)
 #define __htons(x) __ntohs(x)
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/cachectl.h linux/include/asm-mips/cachectl.h
--- v1.3.47/linux/include/asm-mips/cachectl.h	Fri Jan 13 20:28:54 1995
+++ linux/include/asm-mips/cachectl.h	Wed Dec 13 12:39:45 1995
@@ -3,8 +3,6 @@
  *
  * Written by Ralf Baechle,
  * Copyright (C) 1994 by Waldorf GMBH
- *
- * Defines for Risc/OS compatible cacheflush systemcall
  */
 #ifndef	__ASM_MIPS_CACHECTL
 #define	__ASM_MIPS_CACHECTL
@@ -20,13 +18,20 @@
 #define	DCACHE	(1<<1)		/* writeback and flush data cache */
 #define	BCACHE	(ICACHE|DCACHE)	/* flush both caches              */
 
-#define CACHELINES      512             /* number of cachelines    */
-
 #ifdef __KERNEL__
-#ifndef __ASSEMBLY__
+#define CACHELINES      512	/* number of cachelines (kludgy)  */
+
+/*
+ * Cache Operations - for use by assembler code
+ */
+#define Index_Invalidate_I      0x00
+#define Index_Writeback_Inv_D   0x01
+#define Index_Load_Tag_D        0x05
+
+#ifndef __LANGUAGE_ASSEMBLY__
 
 extern int sys_cacheflush(void *addr, int nbytes, int cache);
 
-#endif
-#endif
+#endif /* !__LANGUAGE_ASSEMBLY__ */
+#endif   /* __KERNEL__ */
 #endif	/* __ASM_MIPS_CACHECTL */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/checksum.h linux/include/asm-mips/checksum.h
--- v1.3.47/linux/include/asm-mips/checksum.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/checksum.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,179 @@
+/*
+ * include/asm-mips/checksum.h
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_CHECKSUM_H
+#define __ASM_MIPS_CHECKSUM_H
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+
+/*
+ * the same as csum_partial, but copies from user space (but on the alpha
+ * we have just one address space, so this is identical to the above)
+ */
+#define csum_partial_copy_fromuser csum_partial_copy
+  
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ *
+ *	By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
+ *	Arnt Gulbrandsen.
+ */
+static inline unsigned short ip_fast_csum(unsigned char * iph,
+					  unsigned int ihl)
+{
+	unsigned short int sum;
+	unsigned long	dummy1, dummy2;
+
+	/*
+	 * This is optimized for 32-bit MIPS processors.
+	 * I tried it in plain C but the generated code looks to bad to
+	 * use with old first generation MIPS CPUs.
+	 * Using 64-bit code could even further improve these routines.
+	 */
+	__asm__("
+	.set	noreorder
+	.set	noat
+	lw	%0,(%3)
+	subu	%1,4
+	blez	%1,2f
+	sll	%1,%4,2			# delay slot
+	lw	%2,4(%3)
+	addu	%1,%3			# delay slot
+	addu	%0,%2
+	sltu	$1,%0,%2
+	lw	%2,8(%3)
+	addu	%0,$1
+	addu	%0,%2
+	sltu	$1,%0,%2
+	lw	%2,12(%3)
+	addu	%0,$1
+	addu	%0,%2
+	sltu	$1,%0,%2
+	addu	%0,$1
+1:	lw	%2,16(%3)
+	addu	%1,4
+	addu	%0,%2
+	sltu	$1,%0,%2
+	bne	%1,%3,1b
+	addu	%0,$1			# delay slot
+	srl	$1,%0,16
+	addu	%0,$1
+	sltu	$1,%0,$1
+	addu	%0,$1
+	nor	%0,$0,%0
+	andi	%0,0xffff
+2:	.set	at
+	.set	reorder"
+	: "=r" (sum), "=r" (dummy1), "=r" (dummy2)
+	: "r" (iph), "r"(ihl)
+	: "$1");
+
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+						   unsigned long daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   unsigned int sum)
+{
+    __asm__("
+	.set	noat
+	addu	%0,%2
+	sltu	$1,%0,%2
+	addu	%0,$1
+	addu	%0,%3
+	sltu	$1,%0,%3
+	addu	%0,$1
+	addu	%0,%4
+	sltu	$1,%0,%4
+	addu	%0,$1
+	srl	$1,%0,16
+	addu	%0,$1
+	sltu	$1,%0,$1
+	addu	%0,$1
+	nor	%0,$0,%0
+	andi	%0,0xffff
+	.set	at"
+	: "=r" (sum)
+	: "0" (daddr), "r"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum)
+	: "$1");
+
+	return (unsigned short)sum;
+}
+
+/*
+ *	Fold a partial checksum without adding pseudo headers
+ */
+static inline unsigned short int csum_fold(unsigned int sum)
+{
+    __asm__("
+	.set	noat
+	srl	$1,%0,16
+	addu	%0,$1
+	sltu	$1,%0,$1
+	nor	%0,$0,%0
+	andi	%0,0xffff
+	.set	at"
+	: "=r"(sum)
+	: "0" (sum)
+	: "$1");
+
+ 	return sum;
+}
+ 
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+    unsigned short int sum;
+
+    __asm__("
+	.set	noat
+	srl	$1,%0,16
+	addu	%0,$1
+	sltu	$1,%0,$1
+	nor	%0,$0,%0
+	andi	%0,0xffff
+	.set	at"
+	: "=r"(sum)
+	: "r" (csum_partial(buff, len, 0))
+	: "$1");
+
+	return sum;
+}
+
+#endif /* __ASM_MIPS_CHECKSUM_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/delay.h linux/include/asm-mips/delay.h
--- v1.3.47/linux/include/asm-mips/delay.h	Fri Jan 13 20:42:03 1995
+++ linux/include/asm-mips/delay.h	Wed Dec 13 12:39:45 1995
@@ -27,15 +27,16 @@
 extern __inline__ void udelay(unsigned long usecs)
 {
 	usecs *= 0x000010c6;		/* 2**32 / 1000000 */
-	__asm__("mul\t%0,%0,%1"
+	__asm__("multu\t%0,%1\n\t"
+		"mfhi\t%0"
 		:"=r" (usecs)
 		:"0" (usecs),"r" (loops_per_sec));
 	__delay(usecs);
 }
 
 /*
- * 64-bit integers means we don't have to worry about overflow as
- * on some other architectures..
+ * The different variants for 32/64 bit are pure paranoia. The typical
+ * range of numbers that apprears for MIPS machines avoids overflows.
  */
 extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
 {
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/dma.h linux/include/asm-mips/dma.h
--- v1.3.47/linux/include/asm-mips/dma.h	Wed Aug  2 13:21:16 1995
+++ linux/include/asm-mips/dma.h	Wed Dec 13 12:39:45 1995
@@ -3,6 +3,10 @@
  * Written by Hennus Bergman, 1992.
  * High DMA channel support & info by Hannu Savolainen
  * and John Boyd, Nov. 1992.
+ *
+ * NOTE: all this is true *only* for ISA/EISA expansions on Mips boards
+ * and can only be used for expansion cards. Onboard DMA controller, such
+ * as the R4030 on Jazz boards behave totally different!
  */
 
 #ifndef __ASM_MIPS_DMA_H
@@ -69,10 +73,12 @@
 
 #define MAX_DMA_CHANNELS	8
 
-/* The maximum address that we can perform a DMA transfer to on this platform */
-#define MAX_DMA_ADDRESS      0x1000000
-
-/* The maximum address that we can perform a DMA transfer to on this platform */
+/*
+ * The maximum address that we can perform a DMA transfer to on this platform
+ * This discribes only the PC style part of the DMA logic like on Deskstations
+ * or Acer PICA but not the much more versatile DMA logic used for the
+ * local devices on Acer PICA or Mangnums.
+ */
 #define MAX_DMA_ADDRESS		0x1000000
 
 /* 8237 DMA controllers */
@@ -270,5 +276,10 @@
 extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);	/* release it again */
 
+/*
+ * DMA memory allocation - formerly in include/linux/mm.h
+ */
+#define __get_dma_pages(priority, order) __get_free_pages((priority),(order), \
+                                             0x80000000 + MAX_DMA_ADDRESS)
 
 #endif /* __ASM_MIPS_DMA_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h
--- v1.3.47/linux/include/asm-mips/elf.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/elf.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,17 @@
+#ifndef __ASM_MIPS_ELF_H
+#define __ASM_MIPS_ELF_H
+
+/*
+ * ELF register definitions
+ * This is "make it compile" stuff!
+ */
+#define ELF_NGREG	32
+#define ELF_NFPREG	32
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+#endif /* __ASM_MIPS_ELF_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/errno.h linux/include/asm-mips/errno.h
--- v1.3.47/linux/include/asm-mips/errno.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/errno.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,143 @@
+/*
+ * include/asm-mips/errno.h
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_ERRNO_H
+#define __ASM_MIPS_ERRNO_H
+
+/*
+ * These error numbers are intended to be MIPS ABI compatible
+ */
+#define	EPERM		 1	/* Operation not permitted */
+#define	ENOENT		 2	/* No such file or directory */
+#define	ESRCH		 3	/* No such process */
+#define	EINTR		 4	/* Interrupted system call */
+#define	EIO		 5	/* I/O error */
+#define	ENXIO		 6	/* No such device or address */
+#define	E2BIG		 7	/* Arg list too long */
+#define	ENOEXEC		 8	/* Exec format error */
+#define	EBADF		 9	/* Bad file number */
+#define	ECHILD		10	/* No child processes */
+#define	EAGAIN		11	/* Try again */
+#define	ENOMEM		12	/* Out of memory */
+#define	EACCES		13	/* Permission denied */
+#define	EFAULT		14	/* Bad address */
+#define	ENOTBLK		15	/* Block device required */
+#define	EBUSY		16	/* Device or resource busy */
+#define	EEXIST		17	/* File exists */
+#define	EXDEV		18	/* Cross-device link */
+#define	ENODEV		19	/* No such device */
+#define	ENOTDIR		20	/* Not a directory */
+#define	EISDIR		21	/* Is a directory */
+#define	EINVAL		22	/* Invalid argument */
+#define	ENFILE		23	/* File table overflow */
+#define	EMFILE		24	/* Too many open files */
+#define	ENOTTY		25	/* Not a typewriter */
+#define	ETXTBSY		26	/* Text file busy */
+#define	EFBIG		27	/* File too large */
+#define	ENOSPC		28	/* No space left on device */
+#define	ESPIPE		29	/* Illegal seek */
+#define	EROFS		30	/* Read-only file system */
+#define	EMLINK		31	/* Too many links */
+#define	EPIPE		32	/* Broken pipe */
+#define	EDOM		33	/* Math argument out of domain of func */
+#define	ERANGE		34	/* Math result not representable */
+#define	ENOMSG		35	/* No message of desired type */
+#define	EIDRM		36	/* Identifier removed */
+#define	ECHRNG		37	/* Channel number out of range */
+#define	EL2NSYNC	38	/* Level 2 not synchronized */
+#define	EL3HLT		39	/* Level 3 halted */
+#define	EL3RST		40	/* Level 3 reset */
+#define	ELNRNG		41	/* Link number out of range */
+#define	EUNATCH		42	/* Protocol driver not attached */
+#define	ENOCSI		43	/* No CSI structure available */
+#define	EL2HLT		44	/* Level 2 halted */
+#define	EDEADLK		45	/* Resource deadlock would occur */
+#define	ENOLCK		46	/* No record locks available */
+#define	EBADE		50	/* Invalid exchange */
+#define	EBADR		51	/* Invalid request descriptor */
+#define	EXFULL		52	/* Exchange full */
+#define	ENOANO		53	/* No anode */
+#define	EBADRQC		54	/* Invalid request code */
+#define	EBADSLT		55	/* Invalid slot */
+#define	EDEADLOCK	56	/* File locking deadlock error */
+#define	EBFONT		59	/* Bad font file format */
+#define	ENOSTR		60	/* Device not a stream */
+#define	ENODATA		61	/* No data available */
+#define	ETIME		62	/* Timer expired */
+#define	ENOSR		63	/* Out of streams resources */
+#define	ENONET		64	/* Machine is not on the network */
+#define	ENOPKG		65	/* Package not installed */
+#define	EREMOTE		66	/* Object is remote */
+#define	ENOLINK		67	/* Link has been severed */
+#define	EADV		68	/* Advertise error */
+#define	ESRMNT		69	/* Srmount error */
+#define	ECOMM		70	/* Communication error on send */
+#define	EPROTO		71	/* Protocol error */
+#define	EDOTDOT		73	/* RFS specific error */
+#define	EMULTIHOP	74	/* Multihop attempted */
+#define	EBADMSG		77	/* Not a data message */
+#define	ENAMETOOLONG	78	/* File name too long */
+#define	EOVERFLOW	79	/* Value too large for defined data type */
+#define	ENOTUNIQ	80	/* Name not unique on network */
+#define	EBADFD		81	/* File descriptor in bad state */
+#define	EREMCHG		82	/* Remote address changed */
+#define	ELIBACC		83	/* Can not access a needed shared library */
+#define	ELIBBAD		84	/* Accessing a corrupted shared library */
+#define	ELIBSCN		85	/* .lib section in a.out corrupted */
+#define	ELIBMAX		86	/* Attempting to link in too many shared libraries */
+#define	ELIBEXEC	87	/* Cannot exec a shared library directly */
+#define	EILSEQ		88	/* Illegal byte sequence */
+#define	ENOSYS		89	/* Function not implemented */
+#define	ELOOP		90	/* Too many symbolic links encountered */
+#define	ERESTART	91	/* Interrupted system call should be restarted */
+#define	ESTRPIPE	92	/* Streams pipe error */
+#define	ENOTEMPTY	93	/* Directory not empty */
+#define	EUSERS		94	/* Too many users */
+#define	ENOTSOCK	95	/* Socket operation on non-socket */
+#define	EDESTADDRREQ	96	/* Destination address required */
+#define	EMSGSIZE	97	/* Message too long */
+#define	EPROTOTYPE	98	/* Protocol wrong type for socket */
+#define	ENOPROTOOPT	99	/* Protocol not available */
+#define	EPROTONOSUPPORT	120	/* Protocol not supported */
+#define	ESOCKTNOSUPPORT	121	/* Socket type not supported */
+#define	EOPNOTSUPP	122	/* Operation not supported on transport endpoint */
+#define	EPFNOSUPPORT	123	/* Protocol family not supported */
+#define	EAFNOSUPPORT	124	/* Address family not supported by protocol */
+#define	EADDRINUSE	125	/* Address already in use */
+#define	EADDRNOTAVAIL	126	/* Cannot assign requested address */
+#define	ENETDOWN	127	/* Network is down */
+#define	ENETUNREACH	128	/* Network is unreachable */
+#define	ENETRESET	129	/* Network dropped connection because of reset */
+#define	ECONNABORTED	130	/* Software caused connection abort */
+#define	ECONNRESET	131	/* Connection reset by peer */
+#define	ENOBUFS		132	/* No buffer space available */
+#define	EISCONN		133	/* Transport endpoint is already connected */
+#define	ENOTCONN	134	/* Transport endpoint is not connected */
+#define	EUCLEAN		135	/* Structure needs cleaning */
+#define	ENOTNAM		137	/* Not a XENIX named type file */
+#define	ENAVAIL		138	/* No XENIX semaphores available */
+#define	EISNAM		139	/* Is a named type file */
+#define	EREMOTEIO	140	/* Remote I/O error */
+#define EINIT		141	/* Reserved */
+#define EREMDEV		142	/* Error 142 */
+#define	ESHUTDOWN	143	/* Cannot send after transport endpoint shutdown */
+#define	ETOOMANYREFS	144	/* Too many references: cannot splice */
+#define	ETIMEDOUT	145	/* Connection timed out */
+#define	ECONNREFUSED	146	/* Connection refused */
+#define	EHOSTDOWN	147	/* Host is down */
+#define	EHOSTUNREACH	148	/* No route to host */
+#define	EWOULDBLOCK	EAGAIN	/* Operation would block */
+#define	EALREADY	149	/* Operation already in progress */
+#define	EINPROGRESS	150	/* Operation now in progress */
+#define	ESTALE		151	/* Stale NFS file handle */
+#define ECANCELED	158	/* AIO operation canceled */
+#define	EDQUOT		1133	/* Quota exceeded */
+#define ENFSREMOTE	1134	/* ??? */
+
+#endif /* __ASM_MIPS_ERRNO_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/fcntl.h linux/include/asm-mips/fcntl.h
--- v1.3.47/linux/include/asm-mips/fcntl.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/fcntl.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,67 @@
+#ifndef __ASM_MIPS_FCNTL_H
+#define __ASM_MIPS_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	0x0003
+#define O_RDONLY	0x0000
+#define O_WRONLY	0x0001
+#define O_RDWR		0x0002
+#define O_APPEND	0x0008
+#define O_SYNC		0x0010
+#define O_NONBLOCK	0x0080
+#define O_CREAT         0x0100	/* not fcntl */
+#define O_TRUNC		0x0200	/* not fcntl */
+#define O_EXCL		0x0400	/* not fcntl */
+#define O_NOCTTY	0x0800	/* not fcntl */
+#define FASYNC		0x1000	/* fcntl, for BSD compatibility */
+
+#define O_NDELAY	O_NONBLOCK
+
+#define F_DUPFD		0	/* dup */
+#define F_GETFD		1	/* get f_flags */
+#define F_SETFD		2	/* set f_flags */
+#define F_GETFL		3	/* more flags (cloexec) */
+#define F_SETFL		4
+#define F_GETLK		14
+#define F_SETLK		6
+#define F_SETLKW	7
+
+#define F_SETOWN	24	/*  for sockets. */
+#define F_GETOWN	23	/*  for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK		0
+#define F_WRLCK		1
+#define F_UNLCK		2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH		1	/* shared lock */
+#define LOCK_EX		2	/* exclusive lock */
+#define LOCK_NB		4	/* or'd with one of the above to prevent		XXXXXXXXXXXXXXXXXX
+				   blocking */
+#define LOCK_UN		8	/* remove lock */
+
+#ifdef __KERNEL__
+#define F_POSIX		1
+#define F_FLOCK		2
+#endif /* __KERNEL__ */
+
+typedef struct flock {
+	short l_type;
+	short l_whence;
+	off_t l_start;
+	off_t l_len;
+	long  l_sysid;			/* XXXXXXXXXXXXXXXXXXXXXXXXX */
+	pid_t l_pid;
+	long  pad[4];			/* ZZZZZZZZZZZZZZZZZZZZZZZZZZ */
+} flock_t;
+
+#endif /* __ASM_MIPS_FCNTL_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h
--- v1.3.47/linux/include/asm-mips/floppy.h	Thu Nov  9 11:23:52 1995
+++ linux/include/asm-mips/floppy.h	Wed Dec 13 12:39:45 1995
@@ -17,7 +17,7 @@
 #include <asm/vector.h>
 
 #define fd_inb(port)			feature->fd_inb(port)
-#define fd_outb(port,value)		feature->fd_outb(port,value)
+#define fd_outb(value,port)		feature->fd_outb(value,port)
 
 #define fd_enable_dma()			feature->fd_enable_dma()
 #define fd_disable_dma()		feature->fd_disable_dma()
@@ -36,6 +36,7 @@
 				            "floppy")
 #define fd_free_irq()           free_irq(FLOPPY_IRQ);
 
+#define MAX_BUFFER_SECTORS 24
 #define virtual_dma_init()                                              \
         if (boot_info.machtype == MACH_ACER_PICA_61 ||                  \
             boot_info.machtype == MACH_MIPS_MAGNUM_4000 ||              \
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/fpregdef.h linux/include/asm-mips/fpregdef.h
--- v1.3.47/linux/include/asm-mips/fpregdef.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/fpregdef.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,52 @@
+/*
+ * Definitions for the FPU register names
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_FPREGDEF_H
+#define __ASM_MIPS_FPREGDEF_H
+
+/*
+ * These definitions only cover the R3000-ish 16/32 register model.
+ * But we're trying to be R3000 friendly anyway ...
+ */
+#define fv0	$f0      /* return value */
+#define fv0f	$f1
+#define fv1	$f2
+#define fv1f	$f3
+#define fa0	$f12     /* argument registers */
+#define fa0f	$f13
+#define fa1	$f14
+#define fa1f	$f15
+#define ft0	$f4      /* caller saved */
+#define ft0f	$f5
+#define ft1	$f6
+#define ft1f	$f7
+#define ft2	$f8
+#define ft2f	$f9
+#define ft3	$f10
+#define ft3f	$f11
+#define ft4	$f16
+#define ft4f	$f17
+#define ft5	$f18
+#define ft5f	$f19
+#define fs0	$f20     /* callee saved */
+#define fs0f	$f21
+#define fs1	$f22
+#define fs1f	$f23
+#define fs2	$f24
+#define fs2f	$f25
+#define fs3	$f26
+#define fs3f	$f27
+#define fs4	$f28
+#define fs4f	$f29
+#define fs5	$f30
+#define fs5f	$f31
+
+#define fcr31	$31      /* FPU status register */
+
+#endif /* !defined (__ASM_MIPS_FPREGDEF_H) */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/gdb-stub.h linux/include/asm-mips/gdb-stub.h
--- v1.3.47/linux/include/asm-mips/gdb-stub.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/gdb-stub.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,211 @@
+/*
+ *  include/asm-mips/gdb-stub.h
+ *
+ *  Copyright (C) 1995 Andreas Busse
+ */
+
+#ifndef __ASM_MIPS_GDB_STUB_H
+#define __ASM_MIPS_GDB_STUB_H
+
+
+/*
+ * important register numbers
+ */
+
+#define REG_EPC			37
+#define REG_FP			72
+#define REG_SP			29
+
+/*
+ * Stack layout for the GDB exception handler
+ * Derived from the stack layout described in asm-mips/stackframe.h
+ *
+ * The first PTRSIZE*5 bytes are argument save space for C subroutines.
+ */
+#define NUMREGS			90
+
+#define GDB_FR_REG0		(PTRSIZE*5)			/* 0 */
+#define GDB_FR_REG1		((GDB_FR_REG0) + 4)		/* 1 */
+#define GDB_FR_REG2		((GDB_FR_REG1) + 4)		/* 2 */
+#define GDB_FR_REG3		((GDB_FR_REG2) + 4)		/* 3 */
+#define GDB_FR_REG4		((GDB_FR_REG3) + 4)		/* 4 */
+#define GDB_FR_REG5		((GDB_FR_REG4) + 4)		/* 5 */
+#define GDB_FR_REG6		((GDB_FR_REG5) + 4)		/* 6 */
+#define GDB_FR_REG7		((GDB_FR_REG6) + 4)		/* 7 */
+#define GDB_FR_REG8		((GDB_FR_REG7) + 4)		/* 8 */
+#define GDB_FR_REG9	        ((GDB_FR_REG8) + 4)		/* 9 */
+#define GDB_FR_REG10		((GDB_FR_REG9) + 4)		/* 10 */
+#define GDB_FR_REG11		((GDB_FR_REG10) + 4)		/* 11 */
+#define GDB_FR_REG12		((GDB_FR_REG11) + 4)		/* 12 */
+#define GDB_FR_REG13		((GDB_FR_REG12) + 4)		/* 13 */
+#define GDB_FR_REG14		((GDB_FR_REG13) + 4)		/* 14 */
+#define GDB_FR_REG15		((GDB_FR_REG14) + 4)		/* 15 */
+#define GDB_FR_REG16		((GDB_FR_REG15) + 4)		/* 16 */
+#define GDB_FR_REG17		((GDB_FR_REG16) + 4)		/* 17 */
+#define GDB_FR_REG18		((GDB_FR_REG17) + 4)		/* 18 */
+#define GDB_FR_REG19		((GDB_FR_REG18) + 4)		/* 19 */
+#define GDB_FR_REG20		((GDB_FR_REG19) + 4)		/* 20 */
+#define GDB_FR_REG21		((GDB_FR_REG20) + 4)		/* 21 */
+#define GDB_FR_REG22		((GDB_FR_REG21) + 4)		/* 22 */
+#define GDB_FR_REG23		((GDB_FR_REG22) + 4)		/* 23 */
+#define GDB_FR_REG24		((GDB_FR_REG23) + 4)		/* 24 */
+#define GDB_FR_REG25		((GDB_FR_REG24) + 4)		/* 25 */
+#define GDB_FR_REG26		((GDB_FR_REG25) + 4)		/* 26 */
+#define GDB_FR_REG27		((GDB_FR_REG26) + 4)		/* 27 */
+#define GDB_FR_REG28		((GDB_FR_REG27) + 4)		/* 28 */
+#define GDB_FR_REG29		((GDB_FR_REG28) + 4)		/* 29 */
+#define GDB_FR_REG30		((GDB_FR_REG29) + 4)		/* 30 */
+#define GDB_FR_REG31		((GDB_FR_REG30) + 4)		/* 31 */
+	
+/*
+ * Saved special registers
+ */
+#define GDB_FR_STATUS		((GDB_FR_REG31) + 4)		/* 32 */
+#define GDB_FR_LO		((GDB_FR_STATUS) + 4)		/* 33 */
+#define GDB_FR_HI		((GDB_FR_LO) + 4)		/* 34 */
+#define GDB_FR_BADVADDR		((GDB_FR_HI) + 4)		/* 35 */
+#define GDB_FR_CAUSE		((GDB_FR_BADVADDR) + 4)		/* 36 */
+#define GDB_FR_EPC		((GDB_FR_CAUSE) + 4)		/* 37 */
+
+/*
+ * Saved floating point registers
+ */
+#define GDB_FR_FPR0		((GDB_FR_EPC) + 4)		/* 38 */
+#define GDB_FR_FPR1		((GDB_FR_FPR0) + 4)		/* 39 */
+#define GDB_FR_FPR2		((GDB_FR_FPR1) + 4)		/* 40 */
+#define GDB_FR_FPR3		((GDB_FR_FPR2) + 4)		/* 41 */
+#define GDB_FR_FPR4		((GDB_FR_FPR3) + 4)		/* 42 */
+#define GDB_FR_FPR5		((GDB_FR_FPR4) + 4)		/* 43 */
+#define GDB_FR_FPR6		((GDB_FR_FPR5) + 4)		/* 44 */
+#define GDB_FR_FPR7		((GDB_FR_FPR6) + 4)		/* 45 */
+#define GDB_FR_FPR8		((GDB_FR_FPR7) + 4)		/* 46 */
+#define GDB_FR_FPR9		((GDB_FR_FPR8) + 4)		/* 47 */
+#define GDB_FR_FPR10		((GDB_FR_FPR9) + 4)		/* 48 */
+#define GDB_FR_FPR11		((GDB_FR_FPR10) + 4)		/* 49 */
+#define GDB_FR_FPR12		((GDB_FR_FPR11) + 4)		/* 50 */
+#define GDB_FR_FPR13		((GDB_FR_FPR12) + 4)		/* 51 */
+#define GDB_FR_FPR14		((GDB_FR_FPR13) + 4)		/* 52 */
+#define GDB_FR_FPR15		((GDB_FR_FPR14) + 4)		/* 53 */
+#define GDB_FR_FPR16		((GDB_FR_FPR15) + 4)		/* 54 */
+#define GDB_FR_FPR17		((GDB_FR_FPR16) + 4)		/* 55 */
+#define GDB_FR_FPR18		((GDB_FR_FPR17) + 4)		/* 56 */
+#define GDB_FR_FPR19		((GDB_FR_FPR18) + 4)		/* 57 */
+#define GDB_FR_FPR20		((GDB_FR_FPR19) + 4)		/* 58 */
+#define GDB_FR_FPR21		((GDB_FR_FPR20) + 4)		/* 59 */
+#define GDB_FR_FPR22		((GDB_FR_FPR21) + 4)		/* 60 */
+#define GDB_FR_FPR23		((GDB_FR_FPR22) + 4)		/* 61 */
+#define GDB_FR_FPR24		((GDB_FR_FPR23) + 4)		/* 62 */
+#define GDB_FR_FPR25		((GDB_FR_FPR24) + 4)		/* 63 */
+#define GDB_FR_FPR26		((GDB_FR_FPR25) + 4)		/* 64 */
+#define GDB_FR_FPR27		((GDB_FR_FPR26) + 4)		/* 65 */
+#define GDB_FR_FPR28		((GDB_FR_FPR27) + 4)		/* 66 */
+#define GDB_FR_FPR29		((GDB_FR_FPR28) + 4)		/* 67 */
+#define GDB_FR_FPR30		((GDB_FR_FPR29) + 4)		/* 68 */
+#define GDB_FR_FPR31		((GDB_FR_FPR30) + 4)		/* 69 */
+
+#define GDB_FR_FSR		((GDB_FR_FPR31) + 4)		/* 70 */
+#define GDB_FR_FIR		((GDB_FR_FSR) + 4)		/* 71 */
+#define GDB_FR_FRP		((GDB_FR_FIR) + 4)		/* 72 */
+
+#define GDB_FR_DUMMY		((GDB_FR_FRP) + 4)		/* 73, unused ??? */
+
+/*
+ * Again, CP0 registers
+ */
+#define GDB_FR_CP0_INDEX	((GDB_FR_DUMMY) + 4)		/* 74 */
+#define GDB_FR_CP0_RANDOM	((GDB_FR_CP0_INDEX) + 4)	/* 75 */
+#define GDB_FR_CP0_ENTRYLO0	((GDB_FR_CP0_RANDOM) + 4)	/* 76 */
+#define GDB_FR_CP0_ENTRYLO1	((GDB_FR_CP0_ENTRYLO0) + 4)	/* 77 */
+#define GDB_FR_CP0_REG4		((GDB_FR_CP0_ENTRYLO1) + 4)	/* 78 */
+#define GDB_FR_CP0_PAGEMASK	((GDB_FR_CP0_REG4) + 4)		/* 79 */
+#define GDB_FR_CP0_WIRED	((GDB_FR_CP0_PAGEMASK) + 4)	/* 80 */
+#define GDB_FR_CP0_REG7		((GDB_FR_CP0_WIRED) + 4)	/* 81 */
+#define GDB_FR_CP0_REG8		((GDB_FR_CP0_REG7) + 4)		/* 82 */
+#define GDB_FR_CP0_REG9		((GDB_FR_CP0_REG8) + 4)		/* 83 */
+#define GDB_FR_CP0_ENTRYHI	((GDB_FR_CP0_REG9) + 4)		/* 84 */
+#define GDB_FR_CP0_REG11	((GDB_FR_CP0_ENTRYHI) + 4)	/* 85 */
+#define GDB_FR_CP0_REG12	((GDB_FR_CP0_REG11) + 4)	/* 86 */
+#define GDB_FR_CP0_REG13	((GDB_FR_CP0_REG12) + 4)	/* 87 */
+#define GDB_FR_CP0_REG14	((GDB_FR_CP0_REG13) + 4)	/* 88 */
+#define GDB_FR_CP0_PRID		((GDB_FR_CP0_REG14) + 4)	/* 89 */
+
+#define GDB_FR_SIZE		((((GDB_FR_CP0_PRID) + 4) + (PTRSIZE-1)) & ~(PTRSIZE-1))
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+/*
+ * This is the same as above, but for the high-level
+ * part of the GDB stub.
+ */
+
+struct gdb_regs {
+	/*
+	 * Pad bytes for argument save space on the stack
+	 * 20/40 Bytes for 32/64 bit code
+	 */
+	unsigned long pad0[5];
+
+	/*
+	 * saved main processor registers
+	 */
+	long	 reg0,  reg1,  reg2,  reg3,  reg4,  reg5,  reg6,  reg7;
+	long	 reg8,  reg9, reg10, reg11, reg12, reg13, reg14, reg15;
+	long	reg16, reg17, reg18, reg19, reg20, reg21, reg22, reg23;
+	long	reg24, reg25, reg26, reg27, reg28, reg29, reg30, reg31;
+
+	/*
+	 * Saved special registers
+	 */
+	long	cp0_status;
+	long	lo;
+	long	hi;
+	long	cp0_badvaddr;
+	long	cp0_cause;
+	long	cp0_epc;
+
+	/*
+	 * Saved floating point registers
+	 */
+	long	fpr0,  fpr1,  fpr2,  fpr3,  fpr4,  fpr5,  fpr6,  fpr7;
+	long	fpr8,  fpr9,  fpr10, fpr11, fpr12, fpr13, fpr14, fpr15;
+	long	fpr16, fpr17, fpr18, fpr19, fpr20, fpr21, fpr22, fpr23;
+	long	fpr24, fpr25, fpr26, fpr27, fpr28, fpr29, fpr30, fpr31;
+
+	long	cp1_fsr;
+	long	cp1_fir;
+
+	/*
+	 * Frame pointer
+	 */
+	long	frame_ptr;
+	long    dummy;		/* unused */
+	
+	/*
+	 * saved cp0 registers
+	 */
+	long	cp0_index;
+	long	cp0_random;
+	long	cp0_entrylo0;
+	long	cp0_entrylo1;
+	long	cp0_reg4;
+	long	cp0_pagemask;
+	long	cp0_wired;
+	long	cp0_reg7;
+	long	cp0_reg8;
+	long	cp0_reg9;
+	long	cp0_entryhi;
+	long	cp0_reg11;
+	long	cp0_reg12;
+	long	cp0_reg13;
+	long	cp0_reg14;
+	long	cp0_prid;
+};
+
+/*
+ * Prototypes
+ */
+
+void set_debug_traps(void);
+
+#endif /* __LANGUAGE_ASSEMBLY */
+#endif /* __ASM_MIPS_GDB_STUB_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/io.h linux/include/asm-mips/io.h
--- v1.3.47/linux/include/asm-mips/io.h	Sun Jan 15 23:05:43 1995
+++ linux/include/asm-mips/io.h	Wed Dec 13 12:39:45 1995
@@ -1,8 +1,8 @@
 #ifndef __ASM_MIPS_IO_H
 #define __ASM_MIPS_IO_H
 
-#include <asm/mipsregs.h>
 #include <asm/mipsconfig.h>
+#include <asm/segment.h>
 
 /*
  * This file contains the definitions for the MIPS counterpart of the
@@ -47,6 +47,51 @@
 #endif
 
 /*
+ * Change virtual addresses to physical addresses and vv.
+ * These are trivial on the 1:1 Linux/MIPS mapping
+ */
+extern inline unsigned long virt_to_phys(volatile void * address)
+{
+	return (unsigned long) address - KSEG0;
+}
+
+extern inline void * phys_to_virt(unsigned long address)
+{
+	return (void *) address + KSEG0;
+}
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ * FIXME: This assumption is wrong for the Deskstation Tyne
+ */
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ */
+#define readb(addr) (*(volatile unsigned char *) (addr))
+#define readw(addr) (*(volatile unsigned short *) (addr))
+#define readl(addr) (*(volatile unsigned int *) (addr))
+
+#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b))
+#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+
+#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
+
+/*
+ * Again, MIPS does not require mem IO specific function.
+ */
+
+#define eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),(void *)(b),(c),(d))
+
+/*
  * Talk about misusing macros..
  */
 
@@ -58,23 +103,26 @@
 
 #define __OUT(m,s) \
 __OUT1(s) __OUT2(m) : : "r" (value), "i" (0), "r" (PORT_BASE+port)); } \
-__OUT1(s##c) __OUT2(m) : : "r" (value), "i" (port), "r" (PORT_BASE)); } \
+__OUT1(s##c) __OUT2(m) : : "r" (value), "ir" (port), "r" (PORT_BASE)); } \
 __OUT1(s##_p) __OUT2(m) : : "r" (value), "i" (0), "r" (PORT_BASE+port)); \
 	SLOW_DOWN_IO; } \
-__OUT1(s##c_p) __OUT2(m) : : "r" (value), "i" (port), "r" (PORT_BASE)); \
+__OUT1(s##c_p) __OUT2(m) : : "r" (value), "ir" (port), "r" (PORT_BASE)); \
 	SLOW_DOWN_IO; }
 
-#define __IN1(s) \
-extern inline unsigned int __in##s(unsigned int port) { unsigned int _v;
+#define __IN1(t,s) \
+extern __inline__ t __in##s(unsigned int port) { t _v;
 
+/*
+ * Useless nops will be removed by the assembler
+ */
 #define __IN2(m) \
-__asm__ __volatile__ ("l" #m "u\t%0,%1(%2)\n\t"
+__asm__ __volatile__ ("l" #m "u\t%0,%1(%2)\n\tnop"
 
-#define __IN(m,s) \
-__IN1(s) __IN2(m) STR(FILL_LDS) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); return _v; } \
-__IN1(s##c) __IN2(m) STR(FILL_LDS) : "=r" (_v) : "i" (port), "r" (PORT_BASE)); return _v; } \
-__IN1(s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); SLOW_DOWN_IO; return _v; } \
-__IN1(s##c_p) __IN2(m) : "=r" (_v) : "i" (port), "r" (PORT_BASE)); SLOW_DOWN_IO; return _v; }
+#define __IN(t,m,s) \
+__IN1(t,s) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); return _v; } \
+__IN1(t,s##c) __IN2(m) : "=r" (_v) : "ir" (port), "r" (PORT_BASE)); return _v; } \
+__IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (PORT_BASE+port)); SLOW_DOWN_IO; return _v; } \
+__IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (PORT_BASE)); SLOW_DOWN_IO; return _v; }
 
 #define __INS1(s) \
 extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) {
@@ -84,10 +132,10 @@
 	".set\tnoreorder\n\t" \
 	".set\tnoat\n" \
 	"1:\tl" #m "u\t$1,%4(%5)\n\t" \
-	"subu\t%1,%1,1\n\t" \
+	"subu\t%1,1\n\t" \
 	"s" #m "\t$1,(%0)\n\t" \
 	"bne\t$0,%1,1b\n\t" \
-	"addiu\t%0,%0,%6\n\t" \
+	"addiu\t%0,%6\n\t" \
 	".set\tat\n\t" \
 	".set\treorder"
 
@@ -98,7 +146,7 @@
 	: "$1");} \
 __INS1(s##c) __INS2(m) \
 	: "=r" (addr), "=r" (count) \
-	: "0" (addr), "1" (count), "i" (port), "r" (PORT_BASE), "I" (i) \
+	: "0" (addr), "1" (count), "ir" (port), "r" (PORT_BASE), "I" (i) \
 	: "$1");}
 
 #define __OUTS1(s) \
@@ -123,12 +171,12 @@
 	: "$1");} \
 __OUTS1(s##c) __OUTS2(m) \
 	: "=r" (addr), "=r" (count) \
-	: "0" (addr), "1" (count), "i" (port), "r" (PORT_BASE), "I" (i) \
+	: "0" (addr), "1" (count), "ir" (port), "r" (PORT_BASE), "I" (i) \
 	: "$1");}
 
-__IN(b,b)
-__IN(h,w)
-__IN(w,l)
+__IN(unsigned char,b,b)
+__IN(unsigned short,h,w)
+__IN(unsigned int,w,l)
 
 __OUT(b,b)
 __OUT(h,w)
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/ioctl.h linux/include/asm-mips/ioctl.h
--- v1.3.47/linux/include/asm-mips/ioctl.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/ioctl.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,81 @@
+#ifndef __ASM_MIPS_IOCTL_H
+#define __ASM_MIPS_IOCTL_H
+
+/*
+ * The original linux ioctl numbering scheme was just a general
+ * "anything goes" setup, where more or less random numbers were
+ * assigned.  Sorry, I was clueless when I started out on this.
+ *
+ * On the alpha, we'll try to clean it up a bit, using a more sane
+ * ioctl numbering, and also trying to be compatible with OSF/1 in
+ * the process. I'd like to clean it up for the i386 as well, but
+ * it's so painful recognizing both the new and the old numbers..
+ *
+ * The same applies for for the MIPS ABI; in fact even the macros
+ * from Linux/Alpha fit almost perfectly.
+ */
+
+#define _IOC_NRBITS	8
+#define _IOC_TYPEBITS	8
+#define _IOC_SIZEBITS	13
+#define _IOC_DIRBITS	3
+
+#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT	0
+#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * We to additionally limit parameters to a maximum 255 bytes.
+ */
+#define _IOC_SLMASK	0xff
+
+/*
+ * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
+ * And this turns out useful to catch old ioctl numbers in header
+ * files for us.
+ */
+#define _IOC_NONE	1U
+#define _IOC_READ	2U
+#define _IOC_WRITE	4U
+
+/*
+ * The following are included for compatibility
+ */
+#define _IOC_VOID	0x20000000
+#define _IOC_OUT	0x40000000
+#define _IOC_IN		0x80000000
+#define _IOC_INOUT	(IOC_IN|IOC_OUT)
+
+#define _IOC(dir,type,nr,size) \
+	(((dir)  << _IOC_DIRSHIFT) | \
+	 ((type) << _IOC_TYPESHIFT) | \
+	 ((nr)   << _IOC_NRSHIFT) | \
+	 (((size) & _IOC_SLMASK) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode them.. */
+#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
+
+#endif /* __ASM_MIPS_IOCTL_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h
--- v1.3.47/linux/include/asm-mips/ioctls.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/ioctls.h	Wed Dec 13 12:39:45 1995
@@ -0,0 +1,299 @@
+#ifndef __ASM_MIPS_IOCTLS_H
+#define __ASM_MIPS_IOCTLS_H
+
+#include <asm/ioctl.h>
+
+#define TCGETA		0x5401
+#define TCSETA		0x5402
+#define TCSETAW		0x5403
+#define TCSETAF		0x5404
+
+#define TCSBRK		0x5405
+#define TCXONC		0x5406
+#define TCFLSH		0x5407
+
+#define TCGETS		0x540d
+#define TCSETS		0x540e
+#define TCSETSW		0x540f
+#define TCSETSF		0x5410
+
+#define TIOCEXCL	0x740d		/* set exclusive use of tty */
+#define TIOCNXCL	0x740e		/* reset exclusive use of tty */
+#define TIOCOUTQ	0x7472		/* output queue size */
+#define TIOCSTI		0x5472		/* simulate terminal input */
+#define TIOCMGET	0x741d		/* get all modem bits */
+#define TIOCMBIS	0x741b		/* bis modem bits */
+#define TIOCMBIC	0x741c		/* bic modem bits */
+#define TIOCMSET	0x741a		/* set all modem bits */
+#define TIOCPKT		0x5470		/* pty: set/clear packet mode */
+#define		TIOCPKT_DATA		0x00	/* data packet */
+#define		TIOCPKT_FLUSHREAD	0x01	/* flush packet */
+#define		TIOCPKT_FLUSHWRITE	0x02	/* flush packet */
+#define		TIOCPKT_STOP		0x04	/* stop output */
+#define		TIOCPKT_START		0x08	/* start output */
+#define		TIOCPKT_NOSTOP		0x10	/* no more ^S, ^Q */
+#define		TIOCPKT_DOSTOP		0x20	/* now do ^S ^Q */
+#if 0
+#define		TIOCPKT_IOCTL		0x40	/* state change of pty driver */
+#endif
+#define TIOCSWINSZ	_IOW('t', 103, struct winsize)	/* set window size */
+#define TIOCGWINSZ	_IOR('t', 104, struct winsize)	/* get window size */
+#define TIOCNOTTY	0x5471		/* void tty association */
+#define TIOCSETD	0x7401
+#define TIOCGETD	0x7400
+
+#define FIOCLEX		0x6601
+#define FIONCLEX	0x6602		/* these numbers need to be adjusted. */
+#define FIOASYNC	0x667d
+#define FIONBIO		0x667e
+
+						/* 116-117 compat */
+#define TIOCSPGRP	_IOW('t', 118, int)	/* set pgrp of tty */
+#define TIOCGPGRP	_IOR('t', 119, int)	/* get pgrp of tty */
+#define TIOCCONS	_IOW('t', 120, int)	/* become virtual console */
+
+#define FIONREAD	0x467f
+#define TIOCINQ		FIONREAD
+
+#if 0
+#define	TIOCSETA	_IOW('t', 20, struct termios) /* set termios struct */
+#define	TIOCSETAW	_IOW('t', 21, struct termios) /* drain output, set */
+#define	TIOCSETAF	_IOW('t', 22, struct termios) /* drn out, fls in, set */
+#define	TIOCGETD	_IOR('t', 26, int)	/* get line discipline */
+#define	TIOCSETD	_IOW('t', 27, int)	/* set line discipline */
+						/* 127-124 compat */
+#endif
+
+/* I hope the range from 0x5480 on is free ... */
+#define TIOCSCTTY	0x5480		/* become controlling tty */
+#define TIOCGSOFTCAR	0x5481
+#define TIOCSSOFTCAR	0x5482
+#define TIOCLINUX	0x5483
+#define TIOCGSERIAL	0x5484
+#define TIOCSSERIAL	0x5485
+
+#define TCSBRKP		0x5486	/* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT	0x5487  /* For debugging only */
+
+#define TIOCSERCONFIG	0x5488
+#define TIOCSERGWILD	0x5489
+#define TIOCSERSWILD	0x548a
+#define TIOCGLCKTRMIOS	0x548b
+#define TIOCSLCKTRMIOS	0x548c
+#define TIOCSERGSTRUCT	0x548d /* For debugging only */
+#define TIOCSERGETLSR   0x548e /* Get line status register */
+#define TIOCSERGETMULTI 0x548f /* Get multiport config  */
+#define TIOCSERSETMULTI 0x5490 /* Set multiport config */
+
+/* ----------------------------------------------------------------------- */
+
+/* c_cc characters */
+#define VINTR		 0		/* Interrupt character [ISIG].  */
+#define VQUIT		 1		/* Quit character [ISIG].  */
+#define VERASE		 2		/* Erase character [ICANON].  */
+#define VKILL		 3		/* Kill-line character [ICANON].  */
+#define VEOF		 4		/* End-of-file character [ICANON].  */
+#define VMIN		VEOF		/* Minimum number of bytes read at once [!ICANON].  */
+#define VEOL		 5		/* End-of-line character [ICANON].  */
+#define VTIME		VEOL		/* Time-out value (tenths of a second) [!ICANON].  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define VEOL2		 6		/* Second EOL character [ICANON].  */
+/* The next two are guesses ... */
+#define VSWTC		 7		/* ??? */
+#endif
+#define VSWTCH		VSWTC
+#define VSTART		 8		/* Start (X-ON) character [IXON, IXOFF].  */
+#define VSTOP		 9		/* Stop (X-OFF) character [IXON, IXOFF].  */
+#define VSUSP		10		/* Suspend character [ISIG].  */
+#if 0
+/*
+ * VDSUSP is not supported
+ */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define VDSUSP		11		/* Delayed suspend character [ISIG].  */
+#endif
+#endif
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define VREPRINT	12		/* Reprint-line character [ICANON].  */
+#endif
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define VDISCARD	13		/* Discard character [IEXTEN].  */
+#define VWERASE		14		/* Word-erase character [ICANON].  */
+#define VLNEXT		15		/* Literal-next character [IEXTEN].  */
+#endif
+/*
+ * 17 - 19 are reserved
+ */
+
+#ifdef __KERNEL__
+/*
+ *	intr=^C		quit=^|		erase=del	kill=^U
+ *	eof=^D		eol=time=\0	eol2=\0		swtc=\0
+ *	start=^Q	stop=^S		susp=^Z		vdsusp=
+ *	reprint=^R	discard=^U	werase=^W	lnext=^V
+ */
+#define INIT_C_CC "\003\034\177\025\004\0\0\0\021\023\032\0\022\017\027\026"
+#endif
+
+/* c_iflag bits */
+#define IGNBRK	0000001		/* Ignore break condition.  */
+#define BRKINT	0000002		/* Signal interrupt on break.  */
+#define IGNPAR	0000004		/* Ignore characters with parity errors.  */
+#define PARMRK	0000010		/* Mark parity and framing errors.  */
+#define INPCK	0000020		/* Enable input parity check.  */
+#define ISTRIP	0000040		/* Strip 8th bit off characters.  */
+#define INLCR	0000100		/* Map NL to CR on input.  */
+#define IGNCR	0000200		/* Ignore CR.  */
+#define ICRNL	0000400		/* Map CR to NL on input.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define IUCLC	0001000		/* Map upper case to lower case on input.  */
+#endif
+#define IXON	0002000		/* Enable start/stop output control.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define IXANY	0004000		/* Any character will restart after stop.  */
+#endif
+#define IXOFF	0010000		/* Enable start/stop input control.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define IMAXBEL	0020000		/* Ring bell when input queue is full.  */
+#endif
+
+/* c_oflag bits */
+#define OPOST	0000001		/* Perform output processing.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define OLCUC	0000002		/* Map lower case to upper case on output.  */
+#define ONLCR	0000004		/* Map NL to CR-NL on output.  */
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+/*
+#define PAGEOUT ???
+#define WRAP    ???
+ */
+#endif
+
+/* c_cflag bit meaning */
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060		/* Number of bits per byte (mask).  */
+#define   CS5	0000000		/* 5 bits per byte.  */
+#define   CS6	0000020		/* 6 bits per byte.  */
+#define   CS7	0000040		/* 7 bits per byte.  */
+#define   CS8	0000060		/* 8 bits per byte.  */
+#define CSTOPB	0000100		/* Two stop bits instead of one.  */
+#define CREAD	0000200		/* Enable receiver.  */
+#define PARENB	0000400		/* Parity enable.  */
+#define PARODD	0001000		/* Odd parity instead of even.  */
+#define HUPCL	0002000		/* Hang up on last close.  */
+#define CLOCAL	0004000		/* Ignore modem status lines.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define CBAUDEX 0010000
+#define  B57600  0010001
+#define  B115200 0010002
+#define  B230400 0010003
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CRTSCTS	  020000000000		/* flow control */
+#endif
+
+/* c_lflag bits */
+#define ISIG	0000001		/* Enable signals.  */
+#define ICANON	0000002		/* Do erase and kill processing.  */
+#define XCASE	0000004
+#define ECHO	0000010		/* Enable echo.  */
+#define ECHOE	0000020		/* Visual erase for ERASE.  */
+#define ECHOK	0000040		/* Echo NL after KILL.  */
+#define ECHONL	0000100		/* Echo NL even if ECHO is off.  */
+#define NOFLSH	0000200		/* Disable flush after interrupt.  */
+#define IEXTEN	0000400		/* Enable DISCARD and LNEXT.  */
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define ECHOCTL	0001000		/* Echo control characters as ^X.  */
+#define ECHOPRT	0002000		/* Hardcopy visual erase.  */
+#define ECHOKE	0004000		/* Visual erase for KILL.  */
+#endif
+#define FLUSHO	0020000
+#if defined (__USE_BSD) || defined (__KERNEL__)
+#define PENDIN	0040000		/* Retype pending input (state).  */
+#endif
+#define TOSTOP	0100000		/* Send SIGTTOU for background output.  */
+#define ITOSTOP	TOSTOP
+
+/* modem lines */
+#define TIOCM_LE	0x001		/* line enable */
+#define TIOCM_DTR	0x002		/* data terminal ready */
+#define TIOCM_RTS	0x004		/* request to send */
+#define TIOCM_ST	0x010		/* secondary transmit */
+#define TIOCM_SR	0x020		/* secondary receive */
+#define TIOCM_CTS	0x040		/* clear to send */
+#define TIOCM_CAR	0x100		/* carrier detect */
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RNG	0x200		/* ring */
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_DSR	0x400		/* data set ready */
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0	/* Suspend output.  */
+#define	TCOON		1	/* Restart suspended output.  */
+#define	TCIOFF		2	/* Send a STOP character.  */
+#define	TCION		3	/* Send a START character.  */
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0	/* Discard data received but not yet read.  */
+#define	TCOFLUSH	1	/* Discard data written but not yet sent.  */
+#define	TCIOFLUSH	2	/* Discard all pending data.  */
+
+/* tcsetattr uses these */
+#define	TCSANOW		TCSETS	/* Change immediately.  */
+#define	TCSADRAIN	TCSETSW	/* Change when pending output is written.  */
+#define	TCSAFLUSH	TCSETSF	/* Flush pending input before changing.  */
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+
+#endif /* __ASM_MIPS_IOCTLS_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/irq.h linux/include/asm-mips/irq.h
--- v1.3.47/linux/include/asm-mips/irq.h	Fri Jan 13 20:39:49 1995
+++ linux/include/asm-mips/irq.h	Wed Dec 13 12:39:46 1995
@@ -12,6 +12,11 @@
 #ifndef __ASM_MIPS_IRQ_H
 #define __ASM_MIPS_IRQ_H
 
+/*
+ * Actually this is a lie but we hide the local device's interrupts ...
+ */
+#define NR_IRQS 16
+
 extern void disable_irq(unsigned int);
 extern void enable_irq(unsigned int);
 
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/jazz.h linux/include/asm-mips/jazz.h
--- v1.3.47/linux/include/asm-mips/jazz.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/jazz.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,310 @@
+/*
+ * Hardware info about Mips JAZZ and similar systems
+ *
+ * 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) 1995 by Andreas Busse and Ralf Baechle
+ *
+ * This file is a mess. It really needs some reorganisation!
+ */
+
+#ifndef __ASM_MIPS_JAZZ_H 
+#define __ASM_MIPS_JAZZ_H 
+
+/*
+ * The addresses below are virtual address. The mappings are
+ * created on startup via wired entries in the tlb. The Mips
+ * Magnum R3000 and R4000 machines are similar in many aspects,
+ * but many hardware register are accessible at 0xb9000000 in
+ * instead of 0xe0000000.
+ */
+
+#define JAZZ_LOCAL_IO_SPACE     0xe0000000
+
+/*
+ * Revision numbers in PICA_ASIC_REVISION
+ *
+ * 0xf0000000 - Rev1
+ * 0xf0000001 - Rev2
+ * 0xf0000002 - Rev3
+ */
+#define PICA_ASIC_REVISION      0xe0000008
+
+/*
+ * The segments of the seven segment LED are mapped
+ * to the control bits as follows:
+ *
+ *         (7)
+ *      ---------
+ *      |       |
+ *  (2) |       | (6)
+ *      |  (1)  |
+ *      ---------
+ *      |       |
+ *  (3) |       | (5)
+ *      |  (4)  |
+ *      --------- . (0)
+ */
+#define PICA_LED                0xe000f000
+
+/*
+ * Some characters for the LED control registers
+ * The original Mips machines seem to have a LED display
+ * with integrated decoder while the Acer machines can
+ * control each of the seven segments and the dot independend.
+ * It's only a toy, anyway...
+ */
+#define LED_DOT                 0x01
+#define LED_SPACE               0x00
+#define LED_0                   0xfc
+#define LED_1                   0x60
+#define LED_2                   0xda
+#define LED_3                   0xf2
+#define LED_4                   0x66
+#define LED_5                   0xb6
+#define LED_6                   0xbe
+#define LED_7                   0xe0
+#define LED_8                   0xfe
+#define LED_9                   0xf6
+#define LED_A                   0xee
+#define LED_b                   0x3e
+#define LED_C                   0x9c
+#define LED_d                   0x7a
+#define LED_E                   0x9e
+#define LED_F                   0x8e
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern __inline__ void pica_set_led(unsigned int bits)
+{
+	volatile unsigned int *led_register = (unsigned int *) PICA_LED;
+
+	*led_register = bits;
+}
+
+#endif
+
+/*
+ * i8042 keyboard controller for JAZZ and PICA chipsets.
+ * This address is just a guess and seems to differ from
+ * other mips machines such as RC3xxx...
+ */
+#define JAZZ_KEYBOARD_ADDRESS   0xe0005000
+#define JAZZ_KEYBOARD_DATA      0xe0005000
+#define JAZZ_KEYBOARD_COMMAND   0xe0005001
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+typedef struct {
+	unsigned char data;
+	unsigned char command;
+} jazz_keyboard_hardware;
+
+typedef struct {
+	unsigned char pad0[3];
+	unsigned char data;
+	unsigned char pad1[3];
+	unsigned char command;
+} mips_keyboard_hardware;
+
+/*
+ * For now. Needs to be changed for RC3xxx support. See below.
+ */
+#define keyboard_hardware       jazz_keyboard_hardware
+
+#endif
+
+/*
+ * i8042 keyboard controller for most other Mips machines.
+ */
+#define MIPS_KEYBOARD_ADDRESS   0xb9005000
+#define MIPS_KEYBOARD_DATA      0xb9005003
+#define MIPS_KEYBOARD_COMMAND   0xb9005007
+
+/*
+ * Serial and parallel ports (WD 16C552) on the Mips JAZZ
+ */
+#define JAZZ_SERIAL1_BASE       (unsigned int)0xe0006000
+#define JAZZ_SERIAL2_BASE       (unsigned int)0xe0007000
+#define JAZZ_PARALLEL_BASE      (unsigned int)0xe0008000
+
+/*
+ * Dummy Device Address. Used in jazzdma.c
+ */
+#define JAZZ_DUMMY_DEVICE       0xe000d000
+     
+/*
+ * JAZZ timer registers and interrupt no.
+ * Note that the hardware timer interrupt is actually on
+ * cpu level 6, but to keep compatibility with PC stuff
+ * it is remapped to vector 0. See arch/mips/kernel/entry.S.
+ */
+#define JAZZ_TIMER_INTERVAL     0xe0000228
+#define JAZZ_TIMER_REGISTER     0xe0000230
+
+/*
+ * DRAM configuration register
+ */
+#ifndef __LANGUAGE_ASSEMBLY__
+#ifdef __MIPSEL__
+typedef struct {
+	unsigned int bank2 : 3;
+	unsigned int bank1 : 3;
+	unsigned int mem_bus_width : 1;
+	unsigned int reserved2 : 1;
+	unsigned int page_mode : 1;
+	unsigned int reserved1 : 23;
+} dram_configuration;
+#else /* defined (__MIPSEB__) */
+typedef struct {
+	unsigned int reserved1 : 23;
+	unsigned int page_mode : 1;
+	unsigned int reserved2 : 1;
+	unsigned int mem_bus_width : 1;
+	unsigned int bank1 : 3;
+	unsigned int bank2 : 3;
+} dram_configuration;
+#endif
+#endif /* __LANGUAGE_ASSEMBLY__ */
+
+#define PICA_DRAM_CONFIG        0xe00fffe0
+
+/*
+ * JAZZ interrupt control registers
+ */
+#define JAZZ_IO_IRQ_SOURCE      0xe0100000
+#define JAZZ_IO_IRQ_ENABLE      0xe0100002
+
+/*
+ * JAZZ interrupt enable bits
+ */
+#define JAZZ_IE_PARALLEL            (1 << 0)
+#define JAZZ_IE_FLOPPY              (1 << 1)
+#define JAZZ_IE_SOUND               (1 << 2)
+#define JAZZ_IE_VIDEO               (1 << 3)
+#define JAZZ_IE_ETHERNET            (1 << 4)
+#define JAZZ_IE_SCSI                (1 << 5)
+#define JAZZ_IE_KEYBOARD            (1 << 6)
+#define JAZZ_IE_MOUSE               (1 << 7)
+#define JAZZ_IE_SERIAL1             (1 << 8)
+#define JAZZ_IE_SERIAL2             (1 << 9)
+
+/*
+ * JAZZ Interrupt Level definitions
+ */
+#define JAZZ_TIMER_IRQ          0
+#define JAZZ_KEYBOARD_IRQ       1
+#define JAZZ_ETHERNET_IRQ       2 /* 15 */
+#define JAZZ_SERIAL1_IRQ        3
+#define JAZZ_SERIAL2_IRQ        4
+#define JAZZ_PARALLEL_IRQ       5
+#define JAZZ_FLOPPY_IRQ         6 /* needs to be consistent with floppy driver! */
+
+
+/*
+ * JAZZ DMA Channels
+ * Note: Channels 4...7 are not used with respect to the Acer PICA-61
+ * chipset which does not provide these DMA channels.
+ */
+#define JAZZ_SCSI_DMA           0              /* SCSI */
+#define JAZZ_FLOPPY_DMA         1              /* FLOPPY */
+#define JAZZ_AUDIOL_DMA         2              /* AUDIO L */
+#define JAZZ_AUDIOR_DMA         3              /* AUDIO R */
+
+/*
+ * JAZZ R4030 MCT_ADR chip (DMA controller)
+ * Note: Virtual Addresses !
+ */
+#define JAZZ_R4030_CONFIG	0xE0000000	/* R4030 config register */
+#define JAZZ_R4030_REVISION     0xE0000008	/* same as PICA_ASIC_REVISION */
+#define JAZZ_R4030_INV_ADDR	0xE0000010	/* Invalid Address register */
+
+#define JAZZ_R4030_TRSTBL_BASE  0xE0000018	/* Translation Table Base */
+#define JAZZ_R4030_TRSTBL_LIM   0xE0000020	/* Translation Table Limit */
+#define JAZZ_R4030_TRSTBL_INV   0xE0000028	/* Translation Table Invalidate */
+
+#define JAZZ_R4030_CACHE_MTNC   0xE0000030	/* Cache Maintenance */
+#define JAZZ_R4030_R_FAIL_ADDR  0xE0000038	/* Remote Failed Address */
+#define JAZZ_R4030_M_FAIL_ADDR  0xE0000040	/* Memory Failed Adresss */
+
+#define JAZZ_R4030_CACHE_PTAG   0xE0000048	/* I/O Cache Physical Tag */
+#define JAZZ_R4030_CACHE_LTAG   0xE0000050	/* I/O Cache Logical Tag */
+#define JAZZ_R4030_CACHE_BMASK  0xE0000058	/* I/O Cache Byte Mask */
+#define JAZZ_R4030_CACHE_BWIN   0xE0000060	/* I/O Cache Buffer Window */
+
+/*
+ * Remote Speed Registers. 
+ *
+ *  0: free,      1: Ethernet,  2: SCSI,      3: Floppy,
+ *  4: RTC,       5: Kb./Mouse  6: serial 1,  7: serial 2,
+ *  8: parallel,  9: NVRAM,    10: CPU,      11: PROM,
+ * 12: reserved, 13: free,     14: 7seg LED, 15: ???
+ */
+#define JAZZ_R4030_REM_SPEED	0xE0000070	/* 16 Remote Speed Registers */
+						/* 0xE0000070,78,80... 0xE00000E8 */
+#define JAZZ_R4030_IRQ_ENABLE   0xE00000E8	/* Internal Interrupt Enable */
+
+#define JAZZ_R4030_IRQ_SOURCE   0xE0000200	/* Interrupt Source Reg */
+#define JAZZ_R4030_I386_ERROR   0xE0000208	/* i386/EISA Bus Error */
+
+
+/*
+ * Access the R4030 DMA and I/O Controller
+ */
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern inline unsigned short r4030_read_reg16(unsigned addr) {
+	unsigned short ret = *((volatile unsigned short *)addr);
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		".set\treorder");
+	return ret;
+}
+
+extern inline unsigned int r4030_read_reg32(unsigned addr) {
+	unsigned int ret = *((volatile unsigned int *)addr);
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		".set\treorder");
+	return ret;
+}
+
+extern inline void r4030_write_reg16(unsigned addr, unsigned val) {
+	*((volatile unsigned short *)addr) = val;
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		".set\treorder");
+}
+
+extern inline unsigned int r4030_write_reg32(unsigned addr, unsigned val) {
+	*((volatile unsigned int *)addr) = val;
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		".set\treorder");
+}
+
+#endif /* !LANGUAGE_ASSEMBLY__ */
+
+#define JAZZ_FDC_BASE 0xe0003000
+
+#define JAZZ_RTC_BASE 0xe0004000
+
+#endif /* __ASM_MIPS_JAZZ_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h
--- v1.3.47/linux/include/asm-mips/jazzdma.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/jazzdma.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,96 @@
+/*
+ * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support
+ */
+
+#ifndef __ASM_JAZZDMA_H
+#define __ASM_JAZZDMA_H
+
+/*
+ * Prototypes and macros
+ */
+
+unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end);
+unsigned long vdma_alloc(unsigned long paddr, unsigned long size);
+int vdma_free(unsigned long laddr);
+int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size);
+unsigned long vdma_phys2log(unsigned long paddr);
+unsigned long vdma_log2phys(unsigned long laddr);
+void vdma_stats(void);		/* for debugging only */
+
+void vdma_enable(int channel);
+void vdma_disable(int channel);
+void vdma_set_mode(int channel, int mode);
+void vdma_set_addr(int channel, long addr);
+void vdma_set_count(int channel, int count);
+int vdma_get_residue(int channel);
+
+/*
+ * some definitions used by the driver functions
+ */
+#define VDMA_PAGESIZE		4096
+#define VDMA_PGTBL_ENTRIES	4096
+#define VDMA_PGTBL_SIZE		(sizeof(VDMA_PGTBL_ENTRY) * VDMA_PGTBL_ENTRIES)
+#define VDMA_PAGE_EMPTY		0
+
+/*
+ * Macros to get page no. and offset of a given address
+ * Note that VDMA_PAGE() works for physical addresses only
+ */
+#define VDMA_PAGE(a)            ((unsigned int)(a) >> 12)
+#define VDMA_OFFSET(a)          ((unsigned int)(a) & (VDMA_PAGESIZE-1))
+
+/*
+ * error code returned by vdma_alloc()
+ * (See also arch/mips/kernel/jazzdma.c)
+ */
+#define VDMA_ERROR              0xffffffff
+
+/*
+ * VDMA pagetable entry description
+ */
+typedef volatile struct VDMA_PGTBL_ENTRY
+{
+	unsigned int frame;		/* physical frame no. */
+	unsigned int owner;		/* owner of this entry (0=free) */
+} VDMA_PGTBL_ENTRY;
+
+
+/*
+ * DMA channel control registers
+ * in the R4030 MCT_ADR chip
+ */
+#define JAZZ_R4030_CHNL_MODE	0xE0000100	/* 8 DMA Channel Mode Registers, */
+						/* 0xE0000100,120,140... */
+#define JAZZ_R4030_CHNL_ENABLE  0xE0000108	/* 8 DMA Channel Enable Regs, */
+						/* 0xE0000108,128,148... */
+#define JAZZ_R4030_CHNL_COUNT   0xE0000110	/* 8 DMA Channel Byte Cnt Regs, */
+						/* 0xE0000110,130,150... */
+#define JAZZ_R4030_CHNL_ADDR	0xE0000118	/* 8 DMA Channel Address Regs, */
+						/* 0xE0000118,138,158... */
+
+/* channel enable register bits */
+
+#define R4030_CHNL_ENABLE        (1<<0)
+#define R4030_CHNL_WRITE         (1<<1)
+#define R4030_TC_INTR            (1<<8)
+#define R4030_MEM_INTR           (1<<9)
+#define R4030_ADDR_INTR          (1<<10)
+
+/* channel mode register bits */
+
+#define R4030_MODE_ATIME_40      (0) /* device access time on remote bus */
+#define R4030_MODE_ATIME_80      (1)
+#define R4030_MODE_ATIME_120     (2)
+#define R4030_MODE_ATIME_160     (3)
+#define R4030_MODE_ATIME_200     (4)
+#define R4030_MODE_ATIME_240     (5)
+#define R4030_MODE_ATIME_280     (6)
+#define R4030_MODE_ATIME_320     (7)
+#define R4030_MODE_WIDTH_8       (1<<3)	/* device data bus width */
+#define R4030_MODE_WIDTH_16      (2<<3)
+#define R4030_MODE_WIDTH_32      (3<<3)
+#define R4030_MODE_INTR_EN       (1<<5)
+#define R4030_MODE_BURST         (1<<6)	/* Rev. 2 only */
+#define R4030_MODE_FAST_ACK      (1<<7)	/* Rev. 2 only */
+
+#endif /* __ASM_JAZZDMA_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/mc146818rtc.h linux/include/asm-mips/mc146818rtc.h
--- v1.3.47/linux/include/asm-mips/mc146818rtc.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/mc146818rtc.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,28 @@
+/*
+ * Machine dependend access functions for RTC registers.
+ */
+#ifndef __ASM_MIPS_MC146818RTC_H
+#define __ASM_MIPS_MC146818RTC_H
+
+#include <asm/io.h>
+#include <asm/vector.h>
+
+#ifndef RTC_PORT
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_ALWAYS_BCD	1
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+feature->rtc_read_data(); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+feature->rtc_write_data(val); \
+})
+
+#endif /* __ASM_MIPS_MC146818RTC_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/mipsconfig.h linux/include/asm-mips/mipsconfig.h
--- v1.3.47/linux/include/asm-mips/mipsconfig.h	Tue Jan 17 00:57:01 1995
+++ linux/include/asm-mips/mipsconfig.h	Wed Dec 13 12:39:46 1995
@@ -1,29 +1,26 @@
 /*
- * linux/include/asm-mips/mipsconfig.h
+ * include/asm-mips/mipsconfig.h
  *
  * 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, 1995 by Waldorf Electronics
- * written by Ralf Baechle
- *
+ * Copyright (C) 1994, 1995 by Ralf Baechle
  */
-#ifndef __ASM_MIPS_MIPS_CONFIG_H
-#define __ASM_MIPS_MIPS_CONFIG_H
+#ifndef __ASM_MIPS_MIPSCONFIG_H
+#define __ASM_MIPS_MIPSCONFIG_H
 
 /*
  * This is the virtual address to which all ports are being mapped.
  * Must be a value that can be load with a lui instruction.
  */
-#define PORT_BASE		0xe0000000
-
-/* #define NUMBER_OF_TLB_ENTRIES	48  */ /* see bootinfo.h -- Andy */
-#define NUMBER_OF_TLB_ENTRIES	48
+#ifndef PORT_BASE
+#define PORT_BASE		0xe2000000
+#endif
 
 /*
- * Pagetables are 4MB mapped at 0xe3000000
- * Must be a value that can be load with a lui instruction.
+ * Pagetables are 4MB mapped at 0xe4000000
+ * Must be a value that can be loaded with a single instruction.
  */
 #define TLBMAP			0xe4000000
 
@@ -31,14 +28,31 @@
  * The virtual address where we'll map the pagetables
  * For a base address of 0xe3000000 this is 0xe338c000
  * For a base address of 0xe4000000 this is 0xe4390000
- * FIXME: Gas miscomputes the following expression!
+ * FIXME: Gas computes the following expression with signed
+ *        shift and therefore false
 #define TLB_ROOT		(TLBMAP + (TLBMAP >> (12-2)))
  */
 #define TLB_ROOT		0xe4390000
 
 /*
- * This ASID is reserved for the swapper
+ * Use this to activate extra TLB error checking
+ */
+#define CONF_DEBUG_TLB
+
+/*
+ * Use this to activate extra TLB profiling code
+ * (currently not implemented)
+ */
+#undef CONF_PROFILE_TLB
+
+/*
+ * Disable all caching.  Usefull to find trouble with caches in drivers.
+ */
+#undef CONF_DISABLE_KSEG0_CACHING
+
+/*
+ * Set this to one to enable additional vdma debug code.
  */
-#define SWAPPER_ASID		0
+#define CONF_DEBUG_VDMA 0
 
-#endif /* __ASM_MIPS_MIPS_CONFIG_H */
+#endif /* __ASM_MIPS_MIPSCONFIG_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h
--- v1.3.47/linux/include/asm-mips/mipsregs.h	Tue Jan 17 00:57:01 1995
+++ linux/include/asm-mips/mipsregs.h	Wed Dec 13 12:39:46 1995
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 by Ralf Baechle
+ * Copyright (C) 1994, 1995 by Ralf Baechle
  */
 
 #ifndef __ASM_MIPS_MIPSREGS_H
@@ -26,9 +26,7 @@
 /*
  * On the R2000/3000 load instructions are not interlocked -
  * we therefore sometimes need to fill load delay slots with a nop
- * which are useless for >=R4000.
- *
- * FIXME: Don't know about R6000
+ * which would be useless for ISA >= 2.
  */
 #if !defined (__R4000__)
 #define FILL_LDS nop
@@ -59,6 +57,9 @@
 #define CP0_WATCHLO $18
 #define CP0_WATCHHI $19
 #define CP0_XCONTEXT $20
+#define CP0_FRAMEMASK $21
+#define CP0_DIAGNOSTIC $22
+#define CP0_PERFORMANCE $25
 #define CP0_ECC $26
 #define CP0_CACHEERR $27
 #define CP0_TAGLO $28
@@ -66,6 +67,12 @@
 #define CP0_ERROREPC $30
 
 /*
+ * Coprocessor 1 (FPU) register names
+ */
+#define CP1_REVISION   $0
+#define CP1_STATUS     $31
+
+/*
  * Values for PageMask register
  */
 #define PM_4K   0x00000000
@@ -88,33 +95,84 @@
 #define PL_16M  24
 
 /*
- * Compute a vpn/pfn entry for EntryHi register
- */
-#define VPN(addr,pagesizeshift) ((addr) & ~((1 << (pagesizeshift))-1))
-#define PFN(addr,pagesizeshift) (((addr) & ((1 << (pagesizeshift))-1)) << 6)
-
-/*
  * Macros to access the system control coprocessor
  */
-#define read_32bit_cp0_register(source)                                        \
-({ int __res;                                                                  \
-        __asm__ __volatile__(                                                  \
-        "mfc0\t%0,"STR(source)                                                 \
-        : "=r" (__res));                                                       \
+#define read_32bit_cp0_register(source)                         \
+({ int __res;                                                   \
+        __asm__ __volatile__(                                   \
+        "mfc0\t%0,"STR(source)                                  \
+        : "=r" (__res));                                        \
         __res;})
 
-#define read_64bit_cp0_register(source)                                        \
-({ int __res;                                                                  \
-        __asm__ __volatile__(                                                  \
-        "dmfc0\t%0,"STR(source)                                                \
-        : "=r" (__res));                                                       \
+#define read_64bit_cp0_register(source)                         \
+({ int __res;                                                   \
+        __asm__ __volatile__(                                   \
+        ".set\tmips3\n\t"                                       \
+        "dmfc0\t%0,"STR(source)"\n\t"                           \
+        ".set\tmips0"                                           \
+        : "=r" (__res));                                        \
         __res;})
 
-#define write_32bit_cp0_register(register,value)                               \
-        __asm__ __volatile__(                                                  \
-        "mtc0\t%0,"STR(register)                                               \
+#define write_32bit_cp0_register(register,value)                \
+        __asm__ __volatile__(                                   \
+        "mtc0\t%0,"STR(register)                                \
         : : "r" (value));
 
+#define write_64bit_cp0_register(register,value)                \
+        __asm__ __volatile__(                                   \
+        ".set\tmips3\n\t"                                       \
+        "dmtc0\t%0,"STR(register)"\n\t"                         \
+        ".set\tmips0"                                           \
+        : : "r" (value))
+/*
+ * R4x00 interrupt enable / cause bits
+ */
+#define IE_SW0          (1<< 8)
+#define IE_SW1          (1<< 9)
+#define IE_IRQ0         (1<<10)
+#define IE_IRQ1         (1<<11)
+#define IE_IRQ2         (1<<12)
+#define IE_IRQ3         (1<<13)
+#define IE_IRQ4         (1<<14)
+#define IE_IRQ5         (1<<15)
+
+/*
+ * R4x00 interrupt cause bits
+ */
+#define C_SW0           (1<< 8)
+#define C_SW1           (1<< 9)
+#define C_IRQ0          (1<<10)
+#define C_IRQ1          (1<<11)
+#define C_IRQ2          (1<<12)
+#define C_IRQ3          (1<<13)
+#define C_IRQ4          (1<<14)
+#define C_IRQ5          (1<<15)
+
+#ifndef __LANGUAGE_ASSEMBLY__
+/*
+ * Manipulate the status register.
+ * Mostly used to access the interrupt bits.
+ */
+#define BUILD_SET_CP0(name,register)                            \
+extern __inline__ unsigned int                                  \
+set_cp0_##name(unsigned int change, unsigned int new)           \
+{                                                               \
+	unsigned int res;                                       \
+                                                                \
+	res = read_32bit_cp0_register(register);                \
+	res &= ~change;                                         \
+	res |= (new & change);                                  \
+	if(change)                                              \
+		write_32bit_cp0_register(register, res);        \
+                                                                \
+	return res;                                             \
+}
+
+BUILD_SET_CP0(status,CP0_STATUS)
+BUILD_SET_CP0(cause,CP0_CAUSE)
+
+#endif /* defined (__LANGUAGE_ASSEMBLY__) */
+
 /*
  * Inline code for use of the ll and sc instructions
  *
@@ -122,54 +180,89 @@
  * Since these operations are only being used for atomic operations
  * the easiest workaround for the R[23]00 is to disable interrupts.
  */
-#define load_linked(addr)                                                      \
-({                                                                             \
-	unsigned int __res;                                                    \
-                                                                               \
-	__asm__ __volatile__(                                                  \
-	"ll\t%0,(%1)"                                                          \
-	: "=r" (__res)                                                         \
-	: "r" ((unsigned int) (addr)));                                        \
-                                                                               \
-	__res;                                                                 \
+#define load_linked(addr)                                       \
+({                                                              \
+	unsigned int __res;                                     \
+                                                                \
+	__asm__ __volatile__(                                   \
+	"ll\t%0,(%1)"                                           \
+	: "=r" (__res)                                          \
+	: "r" ((unsigned int) (addr)));                         \
+                                                                \
+	__res;                                                  \
 })
 
-#define store_conditional(addr,value)                                          \
-({                                                                             \
-	int	__res;                                                         \
-                                                                               \
-	__asm__ __volatile__(                                                  \
-	"sc\t%0,(%2)"                                                          \
-	: "=r" (__res)                                                         \
-	: "0" (value), "r" (addr));                                            \
-                                                                               \
-	__res;                                                                 \
+#define store_conditional(addr,value)                           \
+({                                                              \
+	int	__res;                                          \
+                                                                \
+	__asm__ __volatile__(                                   \
+	"sc\t%0,(%2)"                                           \
+	: "=r" (__res)                                          \
+	: "0" (value), "r" (addr));                             \
+                                                                \
+	__res;                                                  \
 })
 
 /*
  * Bitfields in the cp0 status register
  *
- * Refer to MIPS R4600 manual, page 5-4 for explanation
+ * Refer to the MIPS R4xx0 manuals, chapter 5 for explanation.
+ * FIXME: This doesn't cover all R4xx0 processors.
+ */
+#define ST0_IE			(1   <<  0)
+#define ST0_EXL			(1   <<  1)
+#define ST0_ERL			(1   <<  2)
+#define ST0_KSU			(3   <<  3)
+#  define KSU_USER		(2  <<   3)
+#  define KSU_SUPERVISOR	(1  <<   3)
+#  define KSU_KERNEL		(0  <<   3)
+#define ST0_UX			(1   <<  5)
+#define ST0_SX			(1   <<  6)
+#define ST0_KX 			(1   <<  7)
+#define ST0_IM			(255 <<  8)
+#define ST0_DE			(1   << 16)
+#define ST0_CE			(1   << 17)
+#define ST0_CH			(1   << 18)
+#define ST0_SR			(1   << 20)
+#define ST0_BEV			(1   << 22)
+#define ST0_RE			(1   << 25)
+#define ST0_FR			(1   << 26)
+#define ST0_CU			(15  << 28)
+#define ST0_CU0			(1   << 28)
+#define ST0_CU1			(1   << 29)
+#define ST0_CU2			(1   << 30)
+#define ST0_CU3			(1   << 31)
+#define ST0_XX			(1   << 31)	/* R8000/R10000 naming */
+
+/*
+ * Bitfields and bit numbers in the coprocessor 0 cause register.
+ *
+ * Refer to to your MIPS R4xx0 manual, chapter 5 for explanation.
  */
-#define ST0_IE  (1   <<  0)
-#define ST0_EXL (1   <<  1)
-#define ST0_ERL (1   <<  2)
-#define ST0_KSU (3   <<  3)
-#define ST0_UX  (1   <<  5)
-#define ST0_SX  (1   <<  6)
-#define ST0_KX  (1   <<  7)
-#define ST0_IM  (255 <<  8)
-#define ST0_DE  (1   << 16)
-#define ST0_CE  (1   << 17)
-#define ST0_CH  (1   << 18)
-#define ST0_SR  (1   << 20)
-#define ST0_BEV (1   << 22)
-#define ST0_RE  (1   << 25)
-#define ST0_FR  (1   << 26)
-#define ST0_CU  (15  << 28)
-#define ST0_CU0 (1   << 28)
-#define ST0_CU1 (1   << 29)
-#define ST0_CU2 (1   << 30)
-#define ST0_CU3 (1   << 31)
+#define  CAUSEB_EXCCODE		2
+#define  CAUSEF_EXCCODE		(31  <<  2)
+#define  CAUSEB_IP		8
+#define  CAUSEF_IP		(255 <<  8)
+#define  CAUSEB_IP0		8
+#define  CAUSEF_IP0		(1   <<  8)
+#define  CAUSEB_IP1		9
+#define  CAUSEF_IP1		(1   <<  9)
+#define  CAUSEB_IP2		10
+#define  CAUSEF_IP2		(1   << 10)
+#define  CAUSEB_IP3		11
+#define  CAUSEF_IP3		(1   << 11)
+#define  CAUSEB_IP4		12
+#define  CAUSEF_IP4		(1   << 12)
+#define  CAUSEB_IP5		13
+#define  CAUSEF_IP5		(1   << 13)
+#define  CAUSEB_IP6		14
+#define  CAUSEF_IP6		(1   << 14)
+#define  CAUSEB_IP7		15
+#define  CAUSEF_IP7		(1   << 15)
+#define  CAUSEB_CE		28
+#define  CAUSEF_CE		(3   << 28)
+#define  CAUSEB_BD		31
+#define  CAUSEF_BD		(1   << 31)
 
 #endif /* __ASM_MIPS_MIPSREGS_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/mman.h linux/include/asm-mips/mman.h
--- v1.3.47/linux/include/asm-mips/mman.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/mman.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,62 @@
+/*
+ * Linux/MIPS memory manager definitions
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_MMAN_H
+#define __ASM_MIPS_MMAN_H
+
+/*
+ * Protections are chosen from these bits, OR'd together.  The
+ * implementation does not necessarily support PROT_EXEC or PROT_WRITE
+ * without PROT_READ.  The only guarantees are that no writing will be
+ * allowed without PROT_WRITE and no access will be allowed for PROT_NONE.
+ */
+#define PROT_NONE	0x0		/* page can not be accessed */
+#define PROT_READ	0x1		/* page can be read */
+#define PROT_WRITE	0x2		/* page can be written */
+#define PROT_EXEC	0x4		/* page can be executed */
+
+/*
+ * Flags for mmap
+ */
+#define MAP_SHARED	0x001		/* Share changes */
+#define MAP_PRIVATE	0x002		/* Changes are private */
+#define MAP_TYPE	0x00f		/* Mask for type of mapping */
+#define MAP_FIXED	0x010		/* Interpret addr exactly */
+
+/* not used by linux, but here to make sure we don't clash with ABI defines */
+#define MAP_RENAME	0x020		/* Assign page to file */
+#define MAP_AUTOGROW	0x040		/* File may grow by writing */
+#define MAP_LOCAL	0x080		/* Copy on fork/sproc */
+#define MAP_AUTORSRV	0x100		/* Logical swap reserved on demand */
+
+/* These are linux-specific */
+#define MAP_ANONYMOUS	0x0800		/* don't use a file */
+#define MAP_GROWSDOWN	0x1000		/* stack-like segment */
+#define MAP_DENYWRITE	0x2000		/* ETXTBSY */
+#define MAP_EXECUTABLE	0x4000		/* mark it as a executable */
+#define MAP_LOCKED	0x8000		/* pages are locked */
+
+/*
+ * Flags for msync
+ */
+#define MS_SYNC		0		/* synchronous memory sync */
+#define MS_ASYNC	1		/* sync memory asynchronously */
+#define MS_INVALIDATE	2		/* invalidate mappings & caches */
+
+/*
+ * Flags for mlockall
+ */
+#define MCL_CURRENT	1		/* lock all current mappings */
+#define MCL_FUTURE	2		/* lock all future mappings */
+
+/* compatibility flags */
+#define MAP_ANON       MAP_ANONYMOUS
+#define MAP_FILE       0
+
+#endif /* __ASM_MIPS_MMAN_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/page.h linux/include/asm-mips/page.h
--- v1.3.47/linux/include/asm-mips/page.h	Wed Nov  8 07:11:41 1995
+++ linux/include/asm-mips/page.h	Wed Dec 13 12:39:46 1995
@@ -1,36 +1,33 @@
 #ifndef __ASM_MIPS_PAGE_H
 #define __ASM_MIPS_PAGE_H
 
-#define STRICT_MM_TYPECHECKS
-
-#ifndef __ASSEMBLY__
-
-#include <linux/linkage.h>
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT	12
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_MASK	(~(PAGE_SIZE-1))
 
-#define invalidate()	tlbflush();
-extern asmlinkage void tlbflush(void);
+#ifdef __KERNEL__
 
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+#define STRICT_MM_TYPECHECKS
 
-typedef unsigned short mem_map_t;
+#ifndef __LANGUAGE_ASSEMBLY__
 
 #ifdef STRICT_MM_TYPECHECKS
 /*
  * These are used to make use of C type-checking..
  */
 typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 
 #define pte_val(x)	((x).pte)
+#define pmd_val(x)	((x).pmd)
 #define pgd_val(x)	((x).pgd)
 #define pgprot_val(x)	((x).pgprot)
 
 #define __pte(x)	((pte_t) { (x) } )
+#define __pme(x)	((pme_t) { (x) } )
 #define __pgd(x)	((pgd_t) { (x) } )
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
@@ -39,202 +36,67 @@
  * .. while these make it easier on the compiler
  */
 typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
 typedef unsigned long pgd_t;
 typedef unsigned long pgprot_t;
 
 #define pte_val(x)	(x)
+#define pmd_val(x)	(x)
 #define pgd_val(x)	(x)
 #define pgprot_val(x)	(x)
 
 #define __pte(x)	(x)
+#define __pmd(x)	(x)
 #define __pgd(x)	(x)
 #define __pgprot(x)	(x)
 
 #endif /* !defined (STRICT_MM_TYPECHECKS) */
-#endif /* __ASSEMBLY__ */
-
-/*
- * Note that we shift the lower 32bits of each EntryLo[01] entry
- * 6 bits to the left. That way we can convert the PFN into the
- * physical address by a single 'and' operation and gain 6 additional
- * bits for storing information which isn't present in a normal
- * MIPS page table.
- */
-#define _PAGE_PRESENT               (1<<0)  /* implemented in software */
-#define _PAGE_COW                   (1<<1)  /* implemented in software */
-#define _PAGE_DIRTY                 (1<<2)  /* implemented in software */
-#define _PAGE_USER                  (1<<3)
-#define _PAGE_UNUSED1               (1<<4)
-#define _PAGE_UNUSED2               (1<<5)
-#define _PAGE_GLOBAL                (1<<6)
-#define _PAGE_ACCESSED              (1<<7)   /* The MIPS valid bit      */
-#define _PAGE_RW                    (1<<8)   /* The MIPS dirty bit      */
-#define _CACHE_CACHABLE_NO_WA       (0<<9)
-#define _CACHE_CACHABLE_WA          (1<<9)
-#define _CACHE_UNCACHED             (2<<9)
-#define _CACHE_CACHABLE_NONCOHERENT (3<<9)
-#define _CACHE_CACHABLE_CE          (4<<9)
-#define _CACHE_CACHABLE_COW         (5<<9)
-#define _CACHE_CACHABLE_CUW         (6<<9)
-#define _CACHE_MASK                 (7<<9)
-
-#define _PAGE_TABLE     (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY | \
-                         _CACHE_CACHABLE_NO_WA)
-
-#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _CACHE_MASK)
-
-#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _CACHE_CACHABLE_NO_WA)
-#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW | _CACHE_CACHABLE_NO_WA)
-#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _CACHE_CACHABLE_NO_WA)
-#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
-
-/*
- * MIPS can't do page protection for execute, and considers that the same like
- * read. Also, write permissions imply read permissions. This is the closest
- * we can get by reasonable means..
- */
-#define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY
-#define __P010	PAGE_COPY
-#define __P011	PAGE_COPY
-#define __P100	PAGE_READONLY
-#define __P101	PAGE_READONLY
-#define __P110	PAGE_COPY
-#define __P111	PAGE_COPY
-
-#define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED
-#define __S100	PAGE_READONLY
-#define __S101	PAGE_READONLY
-#define __S110	PAGE_SHARED
-#define __S111	PAGE_SHARED
-
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT			12
-#define PGDIR_SHIFT			22
-#define PAGE_SIZE			(1UL << PAGE_SHIFT)
-#define PGDIR_SIZE			(1UL << PGDIR_SHIFT)
-
-#ifdef __KERNEL__
-
-#define PAGE_OFFSET	KERNELBASE
-#define MAP_NR(addr)	(((addr) - PAGE_OFFSET) >> PAGE_SHIFT)
-#define MAP_PAGE_RESERVED (1<<15)
-
-#if !defined (__ASSEMBLY__)
-
-/* page table for 0-4MB for everybody */
-extern unsigned long pg0[1024];
 
 /*
- * BAD_PAGETABLE is used when we need a bogus page-table, while
- * BAD_PAGE is used for a bogus page.
- *
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
+ * We need a special version of copy_page that can handle virtual caches.
+ * While we're at tweaking with caches we can use that to make it even
+ * faster.  The R10000 accelerated caching mode will further accelerate it.
  */
-extern pte_t __bad_page(void);
-extern pte_t * __bad_pagetable(void);
-
-extern unsigned long __zero_page(void);
+extern void __copy_page(unsigned long from, unsigned long to);
+#define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to)
 
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE __zero_page()
-
-/* number of bits that fit into a memory pointer */
-#define BITS_PER_PTR			(8*sizeof(unsigned long))
-
-/* to mask away the intra-page address bits */
-#define PAGE_MASK			(~(PAGE_SIZE-1))
-
-/* to mask away the intra-page address bits */
-#define PGDIR_MASK			(~(PGDIR_SIZE-1))
+#endif /* __LANGUAGE_ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)		(((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-/* to align the pointer to a pointer address */
-#define PTR_MASK			(~(sizeof(void*)-1))
-
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-/* 64-bit machines, beware!  SRB. */
-#define SIZEOF_PTR_LOG2			2
-
-/* to find an entry in a page-table-directory */
-#define PAGE_DIR_OFFSET(tsk,address) \
-((((unsigned long)(address)) >> PGDIR_SHIFT) + (pgd_t *) (tsk)->tss.pg_dir)
-
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-
-/* the no. of pointers that fit on a page */
-#define PTRS_PER_PAGE			(PAGE_SIZE/sizeof(void*))
-
-/* to set the page-dir */
-#define SET_PAGE_DIR(tsk,pgdir) \
-do { \
-	(tsk)->tss.pg_dir = (unsigned long) (pgdir); \
-	if ((tsk) == current) \
-		invalidate(); \
-} while (0)
-
-extern unsigned long high_memory;
-
-extern inline int pte_none(pte_t pte)		{ return !pte_val(pte); }
-extern inline int pte_present(pte_t pte)	{ return pte_val(pte) & _PAGE_PRESENT; }
-extern inline void pte_clear(pte_t *ptep)	{ pte_val(*ptep) = 0; }
-
-extern inline int pgd_none(pgd_t pgd)		{ return !pgd_val(pgd); }
-extern inline int pgd_bad(pgd_t pgd)		{ return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; }
-extern inline int pgd_present(pgd_t pgd)	{ return pgd_val(pgd) & _PAGE_PRESENT; }
-extern inline void pgd_clear(pgd_t * pgdp)	{ pgd_val(*pgdp) = 0; }
+#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
+/* This handles the memory map */
+#if __mips == 3
 /*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
+ * We handle pages at XKPHYS + 0x1800000000000000 (cachable, noncoherent)
+ * Pagetables are at  XKPHYS + 0x1000000000000000 (uncached)
  */
-extern inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
-extern inline int pte_exec(pte_t pte)		{ return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
-extern inline int pte_cow(pte_t pte)		{ return pte_val(pte) & _PAGE_COW; }
-
-extern inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_RW; return pte; }
-extern inline pte_t pte_rdprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_uncow(pte_t pte)	{ pte_val(pte) &= ~_PAGE_COW; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_RW; return pte; }
-extern inline pte_t pte_mkread(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkcow(pte_t pte)	{ pte_val(pte) |= _PAGE_COW; return pte; }
-
+#define PAGE_OFFSET	0x9800000000000000UL
+#define PT_OFFSET	0x9000000000000000UL
+#define MAP_MASK        0x07ffffffffffffffUL
+#else
 /*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
+ * We handle pages at KSEG0 (cachable, noncoherent)
+ * Pagetables are at  KSEG1 (uncached)
  */
-extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; }
+#define PAGE_OFFSET	0x80000000
+#define PT_OFFSET	0xa0000000
+#define MAP_MASK        0x1fffffff
+#endif
+
+#define MAP_NR(addr)	((((unsigned long)(addr)) & MAP_MASK) >> PAGE_SHIFT)
 
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+#ifndef __LANGUAGE_ASSEMBLY__
 
-extern inline unsigned long pte_page(pte_t pte)	{ return pte_val(pte) & PAGE_MASK; }
-extern inline unsigned long pgd_page(pgd_t pgd)	{ return pgd_val(pgd) & PAGE_MASK; }
+extern unsigned long page_colour_mask;
 
-extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep)
-{ pgd_val(*pgdp) = _PAGE_TABLE | (unsigned long) ptep; }
+extern inline unsigned long
+page_colour(unsigned long page)
+{
+	return page & page_colour_mask;
+}
 
-#endif /* !defined (__ASSEMBLY__) */
+#endif /* defined (__LANGUAGE_ASSEMBLY__) */
 #endif /* defined (__KERNEL__) */
 
 #endif /* __ASM_MIPS_PAGE_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h
--- v1.3.47/linux/include/asm-mips/pgtable.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/pgtable.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,570 @@
+#ifndef __ASM_MIPS_PGTABLE_H
+#define __ASM_MIPS_PGTABLE_H
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <asm/cachectl.h>
+
+/*
+ * The Linux memory management assumes a three-level page table setup. In
+ * 32 bit mode we use that, but "fold" the mid level into the top-level page
+ * table, so that we physically have the same two-level page table as the
+ * i386 mmu expects. The 64 bit version uses a three level setup.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the MIPS page table tree.  Note the frequent conversion between addresses
+ * in KSEG0 and KSEG1.
+ *
+ * This is required due to the cache aliasing problem of the R4xx0 series.
+ * Sometimes doing uncached accesses also to improve the cache performance
+ * slightly.  The R10000 caching mode "uncached accelerated" will help even
+ * further.
+ */
+
+/*
+ * TLB invalidation:
+ *
+ *  - invalidate() invalidates the current mm struct TLBs
+ *  - invalidate_all() invalidates all processes TLBs
+ *  - invalidate_mm(mm) invalidates the specified mm context TLB's
+ *  - invalidate_page(mm, vmaddr) invalidates one page
+ *  - invalidate_range(mm, start, end) invalidates a range of pages
+ *
+ * FIXME: MIPS has full control of all TLB activity in the CPU.  Though
+ * we just stick with complete flushing of TLBs for now.
+ */
+extern asmlinkage void tlbflush(void);
+#define invalidate()	({sys_cacheflush(0, ~0, BCACHE);tlbflush();})
+
+#define invalidate_all() invalidate()
+#define invalidate_mm(mm_struct) \
+do { if ((mm_struct) == current->mm) invalidate(); } while (0)
+#define invalidate_page(mm_struct,addr) \
+do { if ((mm_struct) == current->mm) invalidate(); } while (0)
+#define invalidate_range(mm_struct,start,end) \
+do { if ((mm_struct) == current->mm) invalidate(); } while (0)
+
+/*
+ * We need a special version of copy_page that can handle virtual caches.
+ * While we're at tweaking with caches we can use that to make it faster.
+ * The R10000's accelerated caching mode will further accelerate it.
+ */
+extern void __copy_page(unsigned long from, unsigned long to);
+#define copy_page(from,to) __copy_page((unsigned long)from, (unsigned long)to)
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+
+/* PMD_SHIFT determines the size of the area a second-level page table can map */
+#define PMD_SHIFT	22
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT	22
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: we use two-level, so
+ * we don't really have any PMD directory physically.
+ */
+#define PTRS_PER_PTE	1024
+#define PTRS_PER_PMD	1
+#define PTRS_PER_PGD	1024
+
+#define VMALLOC_START     KSEG2
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+/*
+ * Note that we shift the lower 32bits of each EntryLo[01] entry
+ * 6 bits to the left. That way we can convert the PFN into the
+ * physical address by a single 'and' operation and gain 6 additional
+ * bits for storing information which isn't present in a normal
+ * MIPS page table.
+ * Since the Mips has choosen some quite missleading names for the
+ * valid and dirty bits they're defined here but only their synonyms
+ * will be used.
+ */
+#define _PAGE_PRESENT               (1<<0)  /* implemented in software */
+#define _PAGE_COW                   (1<<1)  /* implemented in software */
+#define _PAGE_READ                  (1<<2)  /* implemented in software */
+#define _PAGE_WRITE                 (1<<3)  /* implemented in software */
+#define _PAGE_ACCESSED              (1<<4)  /* implemented in software */
+#define _PAGE_MODIFIED              (1<<5)  /* implemented in software */
+#define _PAGE_GLOBAL                (1<<6)
+#define _PAGE_VALID                 (1<<7)
+#define _PAGE_SILENT_READ           (1<<7)  /* synonym                 */
+#define _PAGE_DIRTY                 (1<<8)  /* The MIPS dirty bit      */
+#define _PAGE_SILENT_WRITE          (1<<8)
+#define _CACHE_CACHABLE_NO_WA       (0<<9)  /* R4600 only              */
+#define _CACHE_CACHABLE_WA          (1<<9)  /* R4600 only              */
+#define _CACHE_UNCACHED             (2<<9)  /* R4[0246]00              */
+#define _CACHE_CACHABLE_NONCOHERENT (3<<9)  /* R4[0246]00              */
+#define _CACHE_CACHABLE_CE          (4<<9)  /* R4[04]00 only           */
+#define _CACHE_CACHABLE_COW         (5<<9)  /* R4[04]00 only           */
+#define _CACHE_CACHABLE_CUW         (6<<9)  /* R4[04]00 only           */
+#define _CACHE_CACHABLE_ACCELERATED (7<<9)  /* R10000 only             */
+#define _CACHE_MASK                 (7<<9)
+
+#define __READABLE	(_PAGE_READ|_PAGE_SILENT_READ|_PAGE_ACCESSED)
+#define __WRITEABLE	(_PAGE_WRITE|_PAGE_SILENT_WRITE|_PAGE_MODIFIED)
+
+#define _PAGE_TABLE	(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
+			_PAGE_DIRTY | _CACHE_UNCACHED)
+#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _CACHE_MASK)
+
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | __READABLE | _CACHE_UNCACHED)
+#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_WRITE | \
+			_PAGE_ACCESSED | _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_COPY       __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_COW | \
+			_CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | __READABLE | \
+			_CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
+			_CACHE_CACHABLE_NONCOHERENT)
+
+/*
+ * MIPS can't do page protection for execute, and considers that the same like
+ * read. Also, write permissions imply read permissions. This is the closest
+ * we can get by reasonable means..
+ */
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY
+#define __P100	PAGE_READONLY
+#define __P101	PAGE_READONLY
+#define __P110	PAGE_COPY
+#define __P111	PAGE_COPY
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED
+#define __S100	PAGE_READONLY
+#define __S101	PAGE_READONLY
+#define __S110	PAGE_SHARED
+#define __S111	PAGE_SHARED
+
+#if !defined (__LANGUAGE_ASSEMBLY__)
+
+/* page table for 0-4MB for everybody */
+extern unsigned long pg0[1024];
+
+/*
+ * BAD_PAGETABLE is used when we need a bogus page-table, while
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t __bad_page(void);
+extern pte_t * __bad_pagetable(void);
+
+extern unsigned long __zero_page(void);
+
+#define BAD_PAGETABLE __bad_pagetable()
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE __zero_page()
+
+/* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR			(8*sizeof(unsigned long))
+
+/* to align the pointer to a pointer address */
+#define PTR_MASK			(~(sizeof(void*)-1))
+
+/*
+ * sizeof(void*)==1<<SIZEOF_PTR_LOG2
+ */
+#if __mips == 3
+#define SIZEOF_PTR_LOG2			3
+#else
+#define SIZEOF_PTR_LOG2			2
+#endif
+
+/* to find an entry in a page-table */
+#define PAGE_PTR(address) \
+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+
+/* to set the page-dir */
+#define SET_PAGE_DIR(tsk,pgdir) \
+do { \
+	(tsk)->tss.pg_dir = ((unsigned long) (pgdir)) - PT_OFFSET; \
+	if ((tsk) == current) \
+	{ \
+		void load_pgd(unsigned long pg_dir); \
+ \
+		load_pgd((tsk)->tss.pg_dir); \
+	} \
+} while (0)
+
+extern unsigned long high_memory;
+extern pmd_t invalid_pte_table[PAGE_SIZE/sizeof(pmd_t)];
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern inline unsigned long pte_page(pte_t pte)
+{ return PAGE_OFFSET + (pte_val(pte) & PAGE_MASK); }
+
+extern inline unsigned long pmd_page(pmd_t pmd)
+{ return PAGE_OFFSET + (pmd_val(pmd) & PAGE_MASK); }
+
+extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
+{ pmd_val(*pmdp) = _PAGE_TABLE | ((unsigned long) ptep - PT_OFFSET); }
+
+extern inline int pte_none(pte_t pte)		{ return !pte_val(pte); }
+extern inline int pte_present(pte_t pte)	{ return pte_val(pte) & _PAGE_PRESENT; }
+extern inline int pte_inuse(pte_t *ptep)	{ return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
+extern inline void pte_clear(pte_t *ptep)	{ pte_val(*ptep) = 0; }
+extern inline void pte_reuse(pte_t * ptep)
+{
+	if (!mem_map[MAP_NR(ptep)].reserved)
+		mem_map[MAP_NR(ptep)].count++;
+}
+
+/*
+ * Empty pgd/pmd entries point to the invalid_pte_table.
+ */
+extern inline int pmd_none(pmd_t pmd)		{ return (pmd_val(pmd) & PAGE_MASK) == ((unsigned long) invalid_pte_table - PAGE_OFFSET); }
+
+extern inline int pmd_bad(pmd_t pmd)
+{
+	return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE ||
+	        pmd_page(pmd) > high_memory ||
+	        pmd_page(pmd) < PAGE_OFFSET;
+}
+extern inline int pmd_present(pmd_t pmd)	{ return pmd_val(pmd) & _PAGE_PRESENT; }
+extern inline int pmd_inuse(pmd_t *pmdp)	{ return 0; }
+extern inline void pmd_clear(pmd_t * pmdp)	{ pmd_val(*pmdp) = ((unsigned long) invalid_pte_table - PAGE_OFFSET); }
+extern inline void pmd_reuse(pmd_t * pmdp)	{ }
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+extern inline int pgd_none(pgd_t pgd)		{ return 0; }
+extern inline int pgd_bad(pgd_t pgd)		{ return 0; }
+extern inline int pgd_present(pgd_t pgd)	{ return 1; }
+extern inline int pgd_inuse(pgd_t * pgdp)	{ return mem_map[MAP_NR(pgdp)].reserved; }
+extern inline void pgd_clear(pgd_t * pgdp)	{ }
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+extern inline int pte_read(pte_t pte)		{ return pte_val(pte) & _PAGE_READ; }
+extern inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_WRITE; }
+extern inline int pte_exec(pte_t pte)		{ return pte_val(pte) & _PAGE_READ; }
+extern inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_MODIFIED; }
+extern inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
+extern inline int pte_cow(pte_t pte)		{ return pte_val(pte) & _PAGE_COW; }
+
+extern inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+	return pte;
+}
+extern inline pte_t pte_rdprotect(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
+}
+extern inline pte_t pte_exprotect(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ); return pte;
+}
+extern inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); return pte; }
+extern inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ|_PAGE_SILENT_WRITE); return pte; }
+extern inline pte_t pte_uncow(pte_t pte)	{ pte_val(pte) &= ~_PAGE_COW; return pte; }
+extern inline pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_WRITE;
+	if (pte_val(pte) & _PAGE_MODIFIED)
+		pte_val(pte) |= _PAGE_SILENT_WRITE;
+	return pte;
+}
+extern inline pte_t pte_mkread(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_READ;
+	if (pte_val(pte) & _PAGE_ACCESSED)
+		pte_val(pte) |= _PAGE_SILENT_READ;
+	return pte;
+}
+extern inline pte_t pte_mkexec(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_READ;
+	if (pte_val(pte) & _PAGE_ACCESSED)
+		pte_val(pte) |= _PAGE_SILENT_READ;
+	return pte;
+}
+extern inline pte_t pte_mkdirty(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_MODIFIED;
+	if (pte_val(pte) & _PAGE_WRITE)
+		pte_val(pte) |= _PAGE_SILENT_WRITE;
+	return pte;
+}
+extern inline pte_t pte_mkyoung(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_ACCESSED;
+	if (pte_val(pte) & _PAGE_READ)
+	{
+		pte_val(pte) |= _PAGE_SILENT_READ;
+		if ((pte_val(pte) & (_PAGE_WRITE|_PAGE_MODIFIED)) == (_PAGE_WRITE|_PAGE_MODIFIED))
+			pte_val(pte) |= _PAGE_SILENT_WRITE;
+	}
+	return pte;
+}
+extern inline pte_t pte_mkcow(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_COW;
+	return pte;
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
+{ pte_t pte; pte_val(pte) = (page - PAGE_OFFSET) | pgprot_val(pgprot); return pte; }
+
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+
+/* to find an entry in a page-table-directory */
+extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+{
+	return mm->pgd + (address >> PGDIR_SHIFT);
+}
+
+/* Find an entry in the second-level page table.. */
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+	return (pmd_t *) dir;
+}
+
+/* Find an entry in the third-level page table.. */ 
+extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
+{
+	return (pte_t *) (pmd_page(*dir) + (PT_OFFSET - PAGE_OFFSET)) +
+	       ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+}
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any, and marks the page tables reserved.
+ */
+extern inline void pte_free_kernel(pte_t * pte)
+{
+	unsigned long page = (unsigned long) pte;
+
+	mem_map[MAP_NR(pte)].reserved = 0;
+	if(!page)
+		return;
+	page -= (PT_OFFSET - PAGE_OFFSET);
+	free_page(page);
+}
+
+extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+{
+	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	if (pmd_none(*pmd)) {
+		unsigned long page = __get_free_page(GFP_KERNEL);
+		if (pmd_none(*pmd)) {
+			if (page) {
+				mem_map[MAP_NR(page)].reserved = 1;
+				memset((void *) page, 0, PAGE_SIZE);
+				sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
+				sync_mem();
+				page += (PT_OFFSET - PAGE_OFFSET);
+				pmd_set(pmd, (pte_t *)page);
+				return ((pte_t *)page) + address;
+			}
+			pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+			return NULL;
+		}
+		free_page(page);
+	}
+	if (pmd_bad(*pmd)) {
+		printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
+		pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+		return NULL;
+	}
+	return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free_kernel(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
+{
+	return (pmd_t *) pgd;
+}
+
+extern inline void pte_free(pte_t * pte)
+{
+	unsigned long page = (unsigned long) pte;
+
+	if(!page)
+		return;
+	page -= (PT_OFFSET - PAGE_OFFSET);
+	free_page(page);
+}
+
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+{
+	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	if (pmd_none(*pmd)) {
+		unsigned long page = __get_free_page(GFP_KERNEL);
+		if (pmd_none(*pmd)) {
+			if (page) {
+				memset((void *) page, 0, PAGE_SIZE);
+				sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
+				sync_mem();
+				page += (PT_OFFSET - PAGE_OFFSET);
+				pmd_set(pmd, (pte_t *)page);
+				return ((pte_t *)page) + address;
+			}
+			pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+			return NULL;
+		}
+		free_page(page);
+	}
+	if (pmd_bad(*pmd)) {
+		printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+		pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+		return NULL;
+	}
+	return (pte_t *) (pmd_page(*pmd) + (PT_OFFSET - PAGE_OFFSET)) + address;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+	return (pmd_t *) pgd;
+}
+
+extern inline void pgd_free(pgd_t * pgd)
+{
+	unsigned long page = (unsigned long) pgd;
+
+	if(!page)
+		return;
+	page -= (PT_OFFSET - PAGE_OFFSET);
+	free_page(page);
+}
+
+/*
+ * Initialize new page directory with pointers to invalid ptes
+ */
+extern inline void pgd_init(unsigned long page)
+{
+	unsigned long dummy1, dummy2;
+
+	page += (PT_OFFSET - PAGE_OFFSET);
+#if __mips >= 3
+	/*
+	 * Ich will Spass - ich geb Gas ich geb Gas...
+	 */
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"dsll32\t$1,%2,0\n\t"
+		"dsrl32\t%2,$1,0\n\t"
+		"or\t%2,$1\n"
+		"1:\tsd\t%2,(%0)\n\t"
+		"subu\t%1,1\n\t"
+		"bnez\t%1,1b\n\t"
+		"addiu\t%0,8\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (dummy1),
+		 "=r" (dummy2)
+		:"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
+		       _PAGE_TABLE),
+		 "0" (page),
+		 "1" (PAGE_SIZE/(sizeof(pmd_t)*2))
+		:"$1");
+#else
+	__asm__ __volatile__(
+		".set\tnoreorder\n"
+		"1:\tsw\t%2,(%0)\n\t"
+		"subu\t%1,1\n\t"
+		"bnez\t%1,1b\n\t"
+		"addiu\t%0,4\n\t"
+		".set\treorder"
+		:"=r" (dummy1),
+		 "=r" (dummy2)
+		:"r" (((unsigned long) invalid_pte_table - PAGE_OFFSET) |
+		       _PAGE_TABLE),
+		 "0" (page),
+		 "1" (PAGE_SIZE/sizeof(pmd_t)));
+#endif
+}
+
+extern inline pgd_t * pgd_alloc(void)
+{
+	unsigned long page;
+
+	if(!(page = __get_free_page(GFP_KERNEL)))
+		return NULL;
+
+	sys_cacheflush((void *)page, PAGE_SIZE, DCACHE);
+	sync_mem();
+	pgd_init(page);
+
+	return (pgd_t *) (page + (PT_OFFSET - PAGE_OFFSET));
+}
+
+extern pgd_t swapper_pg_dir[1024];
+
+/*
+ * MIPS doesn't need any external MMU info: the kernel page tables contain
+ * all the necessary information.  We use this hook though to load the
+ * TLB as early as possible with uptodate information avoiding unecessary
+ * exceptions.
+ */
+extern void update_mmu_cache(struct vm_area_struct * vma,
+	unsigned long address, pte_t pte);
+
+#if __mips >= 3
+
+#define SWP_TYPE(entry) (((entry) >> 32) & 0xff)
+#define SWP_OFFSET(entry) ((entry) >> 40)
+#define SWP_ENTRY(type,offset) pte_val(mk_swap_pte((type),(offset)))
+
+#else
+
+#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
+#define SWP_OFFSET(entry) ((entry) >> 8)
+#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+
+#endif
+
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+
+#endif /* __ASM_MIPS_PGTABLE_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/pica.h linux/include/asm-mips/pica.h
--- v1.3.47/linux/include/asm-mips/pica.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/pica.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,181 @@
+/*
+ * Hardware info about Acer PICA 61 and similar
+ *
+ * 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) 1995 by Andreas Busse and Ralf Baechle
+ */
+#ifndef __ASM_MIPS_PICA_H 
+#define __ASM_MIPS_PICA_H 
+
+/*
+ * The addresses below are virtual address. The mappings are
+ * created on startup via wired entries in the tlb. The Mips
+ * Magnum R3000 and R4000 machines are similar in many aspects,
+ * but many hardware register are accessible at 0xb9000000 in
+ * instead of 0xe0000000.
+ */
+
+/*
+ * Revision numbers in PICA_ASIC_REVISION
+ *
+ * 0xf0000000 - Rev1
+ * 0xf0000001 - Rev2
+ * 0xf0000002 - Rev3
+ */
+#define PICA_ASIC_REVISION      0xe0000008
+
+/*
+ * The segments of the seven segment LED are mapped
+ * to the control bits as follows:
+ *
+ *         (7)
+ *      ---------
+ *      |       |
+ *  (2) |       | (6)
+ *      |  (1)  |
+ *      ---------
+ *      |       |
+ *  (3) |       | (5)
+ *      |  (4)  |
+ *      --------- . (0)
+ */
+#define PICA_LED                0xe000f000
+
+/*
+ * Some characters for the LED control registers
+ * The original Mips machines seem to have a LED display
+ * with integrated decoder while the Acer machines can
+ * control each of the seven segments and the dot independend.
+ * It only a toy, anyway...
+ */
+#define LED_DOT                 0x01
+#define LED_SPACE               0x00
+#define LED_0                   0xfc
+#define LED_1                   0x60
+#define LED_2                   0xda
+#define LED_3                   0xf2
+#define LED_4                   0x66
+#define LED_5                   0xb6
+#define LED_6                   0xbe
+#define LED_7                   0xe0
+#define LED_8                   0xfe
+#define LED_9                   0xf6
+#define LED_A                   0xee
+#define LED_b                   0x3e
+#define LED_C                   0x9c
+#define LED_d                   0x7a
+#define LED_E                   0x9e
+#define LED_F                   0x8e
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+extern __inline__ void pica_set_led(unsigned int bits)
+{
+	volatile unsigned int *led_register = (unsigned int *) PICA_LED;
+
+	*led_register = bits;
+}
+
+#endif
+
+/*
+ * i8042 keyboard controller for PICA chipset.
+ * This address is just a guess and seems to differ
+ * from the other mips machines...
+ */
+#define PICA_KEYBOARD_ADDRESS   0xe0005000
+#define PICA_KEYBOARD_DATA      0xe0005000
+#define PICA_KEYBOARD_COMMAND   0xe0005001
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+typedef struct {
+	unsigned char data;
+	unsigned char command;
+} pica_keyboard_hardware;
+
+typedef struct {
+	unsigned char pad0[3];
+	unsigned char data;
+	unsigned char pad1[3];
+	unsigned char command;
+} mips_keyboard_hardware;
+
+/*
+ * For now
+ */
+#define keyboard_hardware       pica_keyboard_hardware
+
+#endif
+
+/*
+ * i8042 keyboard controller for most other Mips machines.
+ */
+#define MIPS_KEYBOARD_ADDRESS   0xb9005000
+#define MIPS_KEYBOARD_DATA      0xb9005003
+#define MIPS_KEYBOARD_COMMAND   0xb9005007
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+#endif
+
+/*
+ * PICA timer registers and interrupt no.
+ * Note that the hardware timer interrupt is actually on
+ * cpu level 6, but to keep compatibility with PC stuff
+ * it is remapped to vector 0. See arch/mips/kernel/entry.S.
+ */
+#define PICA_TIMER_INTERVAL     0xe0000228
+#define PICA_TIMER_REGISTER     0xe0000230
+
+/*
+ * DRAM configuration register
+ */
+#ifndef __LANGUAGE_ASSEMBLY__
+#ifdef __MIPSEL__
+typedef struct {
+	unsigned int bank2 : 3;
+	unsigned int bank1 : 3;
+	unsigned int mem_bus_width : 1;
+	unsigned int reserved2 : 1;
+	unsigned int page_mode : 1;
+	unsigned int reserved1 : 23;
+} dram_configuration;
+#else /* defined (__MIPSEB__) */
+typedef struct {
+	unsigned int reserved1 : 23;
+	unsigned int page_mode : 1;
+	unsigned int reserved2 : 1;
+	unsigned int mem_bus_width : 1;
+	unsigned int bank1 : 3;
+	unsigned int bank2 : 3;
+} dram_configuration;
+#endif
+#endif /* __LANGUAGE_ASSEMBLY__ */
+
+#define PICA_DRAM_CONFIG        0xe00fffe0
+
+/*
+ * PICA interrupt control registers
+ */
+#define PICA_IO_IRQ_SOURCE      0xe0100000
+#define PICA_IO_IRQ_ENABLE      0xe0100002
+
+/*
+ * Pica interrupt enable bits
+ */
+#define PIE_PARALLEL            (1<<0)
+#define PIE_FLOPPY              (1<<1)
+#define PIE_SOUND               (1<<2)
+#define PIE_VIDEO               (1<<3)
+#define PIE_ETHERNET            (1<<4)
+#define PIE_SCSI                (1<<5)
+#define PIE_KEYBOARD            (1<<6)
+#define PIE_MOUSE               (1<<7)
+#define PIE_SERIAL1             (1<<8)
+#define PIE_SERIAL2             (1<<9)
+
+#endif /* __ASM_MIPS_PICA_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- v1.3.47/linux/include/asm-mips/processor.h	Thu Feb  9 18:22:17 1995
+++ linux/include/asm-mips/processor.h	Wed Dec 13 12:39:46 1995
@@ -8,7 +8,10 @@
 #ifndef __ASM_MIPS_PROCESSOR_H
 #define __ASM_MIPS_PROCESSOR_H
 
-#if !defined (__ASSEMBLY__)
+#if !defined (__LANGUAGE_ASSEMBLY__)
+#include <asm/cachectl.h>
+#include <asm/mipsregs.h>
+#include <asm/reg.h>
 #include <asm/system.h>
 
 /*
@@ -19,46 +22,6 @@
 extern unsigned long intr_count;
 extern unsigned long event;
 
-#if defined (__R4000__)
-
-#define start_bh_atomic()        \
-__asm__ __volatile__(            \
-	".set\tnoreorder\n\t"    \
-	".set\tnoat\n\t"         \
-	"ll\t$1,(%0)\n"          \
-	"1:\taddiu\t$1,$1,1\n\t" \
-	"sc\t$1,(%0)\n\t"        \
-	"beqzl\t$1,1b\n\t"       \
-	"ll\t$1,(%0)\n\t"        \
-	".set\tat\n\t"           \
-	".set\treorder"          \
-	: /* no outputs */       \
-	: "r" (&intr_count));
-
-#define end_bh_atomic()          \
-__asm__ __volatile__(            \
-	".set\tnoreorder\n\t"    \
-	".set\tnoat\n\t"         \
-	"ll\t$1,(%0)\n"          \
-	"1:\tsubu\t$1,$1,1\n\t"  \
-	"sc\t$1,(%0)\n\t"        \
-	"beqzl\t$1,1b\n\t"       \
-	"ll\t$1,(%0)\n\t"        \
-	".set\tat\n\t"           \
-	".set\treorder"          \
-	: /* no outputs */       \
-	: "r" (&intr_count));
-
-#else /* !defined (__R4000__) */
-
-#define start_bh_atomic() \
-{int flags; save_flags(flags); cli(); intr_count++; restore_flags(flags)}
-
-#define end_bh_atomic() \
-{int flags; save_flags(flags); cli(); intr_count--; restore_flags(flags)}
-
-#endif
-
 /*
  * Bus types (default is ISA, but people can check others with these..)
  * MCA_bus hardcoded to 0 for now.
@@ -107,7 +70,7 @@
 };
 
 #define INIT_FPU { \
-	0, \
+	{{0,},} \
 }
 
 /*
@@ -128,17 +91,18 @@
 	 */
 	union mips_fpu_union fpu;
 	/*
-	 * Other stuff associated with the process
+	 * Other stuff associated with the thread
 	 */
 	unsigned long cp0_badvaddr;
 	unsigned long error_code;
 	unsigned long trap_no;
 	unsigned long ksp;		/* Top of kernel stack   */
-	unsigned long fs;		/* "Segment" pointer     */
 	unsigned long pg_dir;		/* L1 page table pointer */
+#define MF_FIXADE 1
+	unsigned long mflags;
 };
 
-#endif /* !defined (__ASSEMBLY__) */
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
 
 /*
  * If you change the #defines remember to change thread_struct above too!
@@ -164,10 +128,13 @@
 #define TOFF_ERROR_CODE		(TOFF_CP0_BADVADDR+4)
 #define TOFF_TRAP_NO		(TOFF_ERROR_CODE+4)
 #define TOFF_KSP		(TOFF_TRAP_NO+4)
-#define TOFF_FS			(TOFF_KSP+4)
-#define TOFF_PG_DIR		(TOFF_FS+4)
+#define TOFF_PG_DIR		(TOFF_KSP+4)
+#define TOFF_MFLAGS		(TOFF_PG_DIR+4)
 
-#if !defined (__ASSEMBLY__)
+#if !defined (__LANGUAGE_ASSEMBLY__)
+
+#define INIT_MMAP { &init_mm, KSEG0, KSEG1, PAGE_SHARED, \
+                    VM_READ | VM_WRITE | VM_EXEC }
 
 #define INIT_TSS  { \
         /* \
@@ -186,8 +153,39 @@
 	/* \
 	 * Other stuff associated with the process\
 	 */ \
-	0, 0, 0, (((unsigned long)init_kernel_stack)+4096-8), \
-	KERNEL_DS, (unsigned long) swapper_pg_dir \
+	0, 0, 0, sizeof(init_kernel_stack) + (unsigned long)init_kernel_stack - 8, \
+	(unsigned long) swapper_pg_dir - PT_OFFSET, 0 \
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+extern inline unsigned long thread_saved_pc(struct thread_struct *t)
+{
+	return ((unsigned long *)t->reg29)[EF_CP0_EPC];
+}
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ */
+static __inline__
+void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
+{
+	/*
+	 * Pure paranoia; probably not needed.
+	 */
+	sys_cacheflush(0, ~0, BCACHE);
+	sync_mem();
+	regs->cp0_epc = pc;
+	/*
+	 * New thread looses kernel priviledges.
+	 */
+	regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER;
+	/*
+	 * Reserve argument save space for registers a0 - a3.
+	regs->reg29 = sp - 4 * sizeof(unsigned long);
+	 */
+	regs->reg29 = sp;
 }
 
 #ifdef __KERNEL__
@@ -210,12 +208,21 @@
 
 #else /* !defined (__R4000__) */
 
-#error "#define USES_USER_TIME(regs)!"
+#define USES_USER_TIME(regs) (!((regs)->cp0_status & 0x4))
 
 #endif /* !defined (__R4000__) */
 
 #endif /* __KERNEL__ */
 
-#endif /* !defined (__ASSEMBLY__) */
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
+
+/*
+ * ELF support
+ *
+ * Using EM_MIPS is actually wrong - this one is reserved for big endian
+ * machines only
+ */
+#define INCOMPATIBLE_MACHINE(m) ((m) != EM_MIPS && (m) != EM_MIPS_RS4_BE)
+#define ELF_EM_CPU EM_MIPS
 
 #endif /* __ASM_MIPS_PROCESSOR_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/ptrace.h linux/include/asm-mips/ptrace.h
--- v1.3.47/linux/include/asm-mips/ptrace.h	Wed Jan 18 08:54:13 1995
+++ linux/include/asm-mips/ptrace.h	Wed Dec 13 12:39:46 1995
@@ -1,34 +1,29 @@
 /*
  * linux/include/asm-mips/ptrace.h
  *
- * machine dependent structs and defines to help the user use
+ * 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, 1995 by Waldorf GMBH
+ * written by Ralf Baechle
+ *
+ * Machine dependent structs and defines to help the user use
  * the ptrace system call.
  */
 #ifndef __ASM_MIPS_PTRACE_H
 #define __ASM_MIPS_PTRACE_H
 
 /*
- * use ptrace (3 or 6, pid, PT_EXCL, data); to read or write
- * the processes registers.
- *
- * This defines/structures correspond to the register layout on stack -
- * if the order here is changed, it needs to be updated in
- * arch/mips/fork.c:copy_process, asm/mips/signal.c:do_signal,
- * asm-mips/ptrace.c, include/asm-mips/ptrace.h.
- */
-
-#include <asm/stackframe.h>
-
-/*
- * This struct defines the way the registers are stored on the 
- * stack during a system call/exception. As usual the registers
- * k0/k1 aren't being saved.
+ * This struct defines the way the registers are stored on the stack during a
+ * system call/exception. As usual the registers k0/k1 aren't being saved.
  */
 struct pt_regs {
 	/*
 	 * Pad bytes for argument save space on the stack
+	 * 20/40 Bytes for 32/64 bit code
 	 */
-	unsigned long pad0[FR_REG1/sizeof(unsigned long)];
+	unsigned long pad0[5];
 
 	/*
 	 * saved main processor registers
@@ -56,19 +51,26 @@
 	 */
 	unsigned long interrupt;
 	long orig_reg2;
+	long pad1;
 };
 
+#ifdef __KERNEL__
+
 /*
  * Does the process account for user or for system time?
  */
 #if defined (__R4000__)
 
-#define user_mode(regs) (!((regs)->cp0_status & 0x18))
+#define user_mode(regs) ((regs)->cp0_status & 0x10)
 
 #else /* !defined (__R4000__) */
 
-#error "#define user_mode(regs) for R3000!"
+#define user_mode(regs) (!((regs)->cp0_status & 0x8))
 
 #endif /* !defined (__R4000__) */
+
+#define instruction_pointer(regs) ((regs)->cp0_epc)
+extern void show_regs(struct pt_regs *);
+#endif
 
 #endif /* __ASM_MIPS_PTRACE_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/reg.h linux/include/asm-mips/reg.h
--- v1.3.47/linux/include/asm-mips/reg.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/reg.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,78 @@
+/*
+ * Makefile for MIPS Linux main source directory
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_REG_H
+#define __ASM_MIPS_REG_H
+
+/*
+ * This defines/structures correspond to the register layout on stack -
+ * if the order here is changed, it needs to be updated in
+ * include/asm-mips/stackframe.h
+ */
+#define EF_REG1       5
+#define EF_REG2       6
+#define EF_REG3       7
+#define EF_REG4       8
+#define EF_REG5       9
+#define EF_REG6       10
+#define EF_REG7       11
+#define EF_REG8       12
+#define EF_REG9       13
+#define EF_REG10      14
+#define EF_REG11      15
+#define EF_REG12      16
+#define EF_REG13      17
+#define EF_REG14      18
+#define EF_REG15      19
+#define EF_REG16      20
+#define EF_REG17      21
+#define EF_REG18      22
+#define EF_REG19      23
+#define EF_REG20      24
+#define EF_REG21      25
+#define EF_REG22      26
+#define EF_REG23      27
+#define EF_REG24      28
+#define EF_REG25      29
+/*
+ * k0/k1 unsaved
+ */
+#define EF_REG28      30
+#define EF_REG29      31
+#define EF_REG30      32
+#define EF_REG31      33
+
+/*
+ * Saved special registers
+ */
+#define EF_LO         34
+#define EF_HI         35
+
+/*
+ * saved cp0 registers
+ */
+#define EF_CP0_STATUS 36
+#define EF_CP0_EPC    37
+#define EF_CP0_CAUSE  38
+
+/*
+ * Some goodies
+ */
+#define EF_INTERRUPT  39
+#define EF_ORIG_REG2  40
+
+#define EF_SIZE		(41*4)
+
+/*
+ * Map register number into core file offset.
+ */
+#define CORE_REG(reg, ubase) \
+	(((unsigned long *)((unsigned long)(ubase)))[reg])
+
+#endif /* __ASM_MIPS_REG_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/regdef.h linux/include/asm-mips/regdef.h
--- v1.3.47/linux/include/asm-mips/regdef.h	Fri Jan 13 20:38:36 1995
+++ linux/include/asm-mips/regdef.h	Wed Dec 13 12:39:46 1995
@@ -5,17 +5,17 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 by Ralf Baechle
+ * Copyright (C) 1994, 1995 by Ralf Baechle
  */
 
-#ifndef __ASM_MIPS_REGSDEFS_H
-#define __ASM_MIPS_REGSDEFS_H
+#ifndef __ASM_MIPS_REGDEF_H
+#define __ASM_MIPS_REGDEF_H
 
 /*
- * Symbolic register names
+ * Symbolic register names for 32 bit ABI
  */
 #define zero    $0      /* wired zero */
-#define AT      $1      /* assembler temp (uprcase, because ".set at") */
+#define AT      $1      /* assembler temp  - uppercase because of ".set at" */
 #define v0      $2      /* return value */
 #define v1      $3
 #define a0      $4      /* argument registers */
@@ -40,11 +40,13 @@
 #define s7      $23
 #define t8      $24     /* caller saved */
 #define t9      $25
+#define jp      $25     /* PIC jump register */
 #define k0      $26     /* kernel scratch */
 #define k1      $27
 #define gp      $28     /* global pointer */
 #define sp      $29     /* stack pointer */
 #define fp      $30     /* frame pointer */
+#define s8	$30	/* same like fp! */
 #define ra      $31     /* return address */
 
-#endif /* __ASM_MIPS_REGSDEFS_H */
+#endif /* __ASM_MIPS_REGDEF_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/resource.h linux/include/asm-mips/resource.h
--- v1.3.47/linux/include/asm-mips/resource.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/resource.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,48 @@
+/*
+ * Process resource limits
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_RESOURCE_H
+#define __ASM_MIPS_RESOURCE_H
+
+/*
+ * Resource limits
+ */
+#define RLIMIT_CPU	0		/* CPU time in ms */
+#define RLIMIT_FSIZE	1		/* Maximum filesize */
+#define RLIMIT_DATA	2		/* max data size */
+#define RLIMIT_STACK	3		/* max stack size */
+#define RLIMIT_CORE	4		/* max core file size */
+#define RLIMIT_NOFILE	5		/* max number of open files */
+#define RLIMIT_VMEM	6		/* mapped memory */
+#define RLIMIT_AS	RLIMIT_VMEM
+#define RLIMIT_RSS	7		/* max resident set size */
+#define RLIMIT_NPROC	8		/* max number of processes */
+#define RLIMIT_MEMLOCK	9		/* max locked-in-memory address space*/
+
+#define RLIM_NLIMITS	10
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS					\
+{							\
+	{LONG_MAX, LONG_MAX},				\
+	{LONG_MAX, LONG_MAX},				\
+	{LONG_MAX, LONG_MAX},				\
+	{_STK_LIM, _STK_LIM},				\
+	{       0, LONG_MAX},				\
+	{NR_OPEN, NR_OPEN},				\
+	{LONG_MAX, LONG_MAX},				\
+	{LONG_MAX, LONG_MAX},				\
+	{MAX_TASKS_PER_USER, MAX_TASKS_PER_USER},	\
+	{ LONG_MAX, LONG_MAX },				\
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_MIPS_RESOURCE_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/segment.h linux/include/asm-mips/segment.h
--- v1.3.47/linux/include/asm-mips/segment.h	Wed Jan 25 08:54:23 1995
+++ linux/include/asm-mips/segment.h	Wed Dec 13 12:39:46 1995
@@ -7,81 +7,119 @@
  *
  * Copyright (C) 1994, 1995 by Ralf Baechle
  *
+ * Note that the quad functions are only being used for the 64 bit kernel and
+ * therefore it isn't really important that they will be misscompiled for
+ * 32-bit kernels.
  */
 #ifndef __ASM_MIPS_SEGMENT_H
 #define __ASM_MIPS_SEGMENT_H
 
+#ifndef __LANGUAGE_ASSEMBLY__
 /*
- * Memory segments (32bit kernel mode addresses)
+ * For memcpy()
  */
-#define KUSEG                   0x00000000
-#define KSEG0                   0x80000000
-#define KSEG1                   0xa0000000
-#define KSEG2                   0xc0000000
-#define KSEG3                   0xe0000000
+#include <linux/string.h>
 
 /*
- * returns the kernel segment base of a given address
+ * This is a gcc optimization barrier, which essentially
+ * inserts a sequence point in the gcc RTL tree that gcc
+ * can't move code around. This is needed when we enter
+ * or exit a critical region (in this case around user-level
+ * accesses that may sleep, and we can't let gcc optimize
+ * global state around them).
  */
-#define KSEGX(a)                (a & 0xe0000000)
-
-#ifndef __ASSEMBLY__
+#define __gcc_barrier() __asm__ __volatile__("": : :"memory")
 
 /*
- * Beware: the xxx_fs_word functions work on 16bit words!
+ * Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
  */
-#define get_fs_byte(addr) get_user_byte((char *)(addr))
-static inline unsigned char get_user_byte(const char *addr)
-{
-	return *addr;
-}
-
-#define get_fs_word(addr) get_user_word((short *)(addr))
-static inline unsigned short get_user_word(const short *addr)
-{
-	return *addr;
-}
-
-#define get_fs_long(addr) get_user_long((int *)(addr))
-static inline unsigned long get_user_long(const int *addr)
-{
-	return *addr;
-}
+#define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr)))
+#define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr))))
 
-#define get_fs_dlong(addr) get_user_dlong((long long *)(addr))
-static inline unsigned long get_user_dlong(const long long *addr)
-{
-	return *addr;
-}
-
-#define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr))
-static inline void put_user_byte(char val,char *addr)
-{
-	*addr = val;
-}
-
-#define put_fs_word(x,addr) put_user_word((x),(short *)(addr))
-static inline void put_user_word(short val,short * addr)
-{
-	*addr = val;
-}
-
-#define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
-static inline void put_user_long(unsigned long val,int * addr)
-{
-	*addr = val;
-}
+/*
+ * This is a silly but good way to make sure that
+ * the __put_user function is indeed always optimized,
+ * and that we use the correct sizes..
+ */
+extern int bad_user_access_length(void);
 
-#define put_fs_dlong(x,addr) put_user_dlong((x),(int *)(addr))
-static inline void put_user_dlong(unsigned long val,long long * addr)
+/* I should make this use unaligned transfers etc.. */
+static inline void __put_user(unsigned long x, void * y, int size)
 {
-	*addr = val;
+	__gcc_barrier();
+	switch (size) {
+		case 1:
+			*(char *) y = x;
+			break;
+		case 2:
+			*(short *) y = x;
+			break;
+		case 4:
+			*(int *) y = x;
+			break;
+		case 8:
+			*(long *) y = x;
+			break;
+		default:
+			bad_user_access_length();
+	}
+	__gcc_barrier();
+}
+
+/* I should make this use unaligned transfers etc.. */
+static inline unsigned long __get_user(const void * y, int size)
+{
+	unsigned long result;
+
+	__gcc_barrier();
+	switch (size) {
+		case 1:
+			result = *(unsigned char *) y;
+			break;
+		case 2:
+			result = *(unsigned short *) y;
+			break;
+		case 4:
+			result = *(unsigned int *) y;
+			break;
+		case 8:
+			result = *(unsigned long *) y;
+			break;
+		default:
+			result = bad_user_access_length();
+			break;
+	}
+	__gcc_barrier();
+
+	return result;
+}
+
+#define get_fs_byte(addr) get_user((unsigned char *)(addr))
+#define get_fs_word(addr) get_user((unsigned short *)(addr))
+#define get_fs_long(addr) get_user((unsigned int *)(addr))
+#define get_fs_quad(addr) get_user((unsigned long *)(addr))
+
+#define put_fs_byte(x,addr) put_user((x),(char *)(addr))
+#define put_fs_word(x,addr) put_user((x),(short *)(addr))
+#define put_fs_long(x,addr) put_user((x),(int *)(addr))
+#define put_fs_quad(x,addr) put_user((x),(long *)(addr))
+
+static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
+{
+	__gcc_barrier();
+	memcpy(to, from, n);
+	__gcc_barrier();
+}
+
+static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
+{
+	__gcc_barrier();
+	memcpy(to, from, n);
+	__gcc_barrier();
 }
 
-#define memcpy_fromfs(to, from, n) memcpy((to),(from),(n))
-
-#define memcpy_tofs(to, from, n) memcpy((to),(from),(n))
-
 /*
  * For segmented architectures, these are used to specify which segment
  * to use for the above functions.
@@ -94,18 +132,57 @@
 
 static inline unsigned long get_fs(void)
 {
-	return 0;
+	return USER_DS;
 }
 
 static inline unsigned long get_ds(void)
 {
-	return 0;
+	return KERNEL_DS;
 }
 
 static inline void set_fs(unsigned long val)
 {
 }
 
-#endif /* !__ASSEMBLY__ */
+#endif /* !__LANGUAGE_ASSEMBLY__ */
+
+/*
+ * Memory segments (32bit kernel mode addresses)
+ */
+#define KUSEG                   0x00000000
+#define KSEG0                   0x80000000
+#define KSEG1                   0xa0000000
+#define KSEG2                   0xc0000000
+#define KSEG3                   0xe0000000
+
+/*
+ * Returns the kernel segment base of a given address
+ */
+#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
+
+/*
+ * Returns the physical address of a KSEG0/KSEG1 address
+ */
+#define PHYSADDR(a)		(((unsigned long)(a)) & 0x1fffffff)
+
+/*
+ * Map an address to a certain kernel segment
+ */
+#define KSEG0ADDR(a)		((((unsigned long)(a)) & 0x1fffffff) | KSEG0)
+#define KSEG1ADDR(a)		((((unsigned long)(a)) & 0x1fffffff) | KSEG1)
+#define KSEG2ADDR(a)		((((unsigned long)(a)) & 0x1fffffff) | KSEG2)
+#define KSEG3ADDR(a)		((((unsigned long)(a)) & 0x1fffffff) | KSEG3)
+
+/*
+ * Memory segments (64bit kernel mode addresses)
+ */
+#define XKUSEG                  0x0000 0000 0000 0000
+#define XKSSEG                  0x4000 0000 0000 0000
+#define XKPHYS                  0x8000 0000 0000 0000
+#define XKSEG                   0xc000 0000 0000 0000
+#define CKSEG0                  0xffff ffff 8000 0000
+#define CKSEG1                  0xffff ffff a000 0000
+#define CKSSEG                  0xffff ffff c000 0000
+#define CKSEG3                  0xffff ffff e000 0000
 
 #endif /* __ASM_MIPS_SEGMENT_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/shmparam.h linux/include/asm-mips/shmparam.h
--- v1.3.47/linux/include/asm-mips/shmparam.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/shmparam.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,47 @@
+#ifndef __ASM_MIPS_SHMPARAM_H
+#define __ASM_MIPS_SHMPARAM_H
+
+/* address range for shared memory attaches if no address passed to shmat() */
+#define SHM_RANGE_START	0x50000000
+#define SHM_RANGE_END	0x60000000
+
+/*
+ * Format of a swap-entry for shared memory pages currently out in
+ * swap space (see also mm/swap.c).
+ *
+ * SWP_TYPE = SHM_SWP_TYPE
+ * SWP_OFFSET is used as follows:
+ *
+ *  bits 0..6 : id of shared memory segment page belongs to (SHM_ID)
+ *  bits 7..21: index of page within shared memory segment (SHM_IDX)
+ *		(actually fewer bits get used since SHMMAX is so low)
+ */
+
+/*
+ * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
+ * there is a static array of size SHMMNI.
+ */
+#define _SHM_ID_BITS	7
+#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1)
+
+#define SHM_IDX_SHIFT	(_SHM_ID_BITS)
+#define _SHM_IDX_BITS	15
+#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
+
+/*
+ * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and
+ * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
+ */
+
+#define SHMMAX 0x1000000		/* max shared seg size (bytes) */
+#define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
+#define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
+#define SHMALL				/* max shm system wide (pages) */ \
+	(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
+/*
+ * This constant is very large but the ABI in it's wisdom says ...
+ */
+#define	SHMLBA 0x40000			/* attach addr a multiple of this */
+#define SHMSEG SHMMNI			/* max shared segs per process */
+
+#endif /* __ASM_MIPS_SHMPARAM_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/sigcontext.h linux/include/asm-mips/sigcontext.h
--- v1.3.47/linux/include/asm-mips/sigcontext.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/sigcontext.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,21 @@
+#ifndef __ASM_MIPS_SIGCONTEXT_H
+#define __ASM_MIPS_SIGCONTEXT_H
+
+/*
+ * This struct isn't in the ABI, so we continue to use the old
+ * pre 1.3 definition.  Needs to be changed for 64 bit kernels,
+ * but it's 4am ...
+ */
+struct sigcontext_struct {
+	unsigned long	       sc_at, sc_v0, sc_v1, sc_a0, sc_a1, sc_a2, sc_a3;
+	unsigned long	sc_t0, sc_t1, sc_t2, sc_t3, sc_t4, sc_t5, sc_t6, sc_t7;
+	unsigned long	sc_s0, sc_s1, sc_s2, sc_s3, sc_s4, sc_s5, sc_s6, sc_s7;
+	unsigned long	sc_t8, sc_t9,               sc_gp, sc_sp, sc_fp, sc_ra;
+
+	unsigned long	sc_epc;
+	unsigned long	sc_cause;
+
+	unsigned long	sc_oldmask;
+};
+
+#endif /* __ASM_MIPS_SIGCONTEXT_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/signal.h linux/include/asm-mips/signal.h
--- v1.3.47/linux/include/asm-mips/signal.h	Wed Jan 18 08:54:13 1995
+++ linux/include/asm-mips/signal.h	Wed Dec 13 12:39:46 1995
@@ -1,16 +1,126 @@
 #ifndef __ASM_MIPS_SIGNAL_H
 #define __ASM_MIPS_SIGNAL_H
 
-struct sigcontext_struct {
-	unsigned long	       sc_at, sc_v0, sc_v1, sc_a0, sc_a1, sc_a2, sc_a3;
-	unsigned long	sc_t0, sc_t1, sc_t2, sc_t3, sc_t4, sc_t5, sc_t6, sc_t7;
-	unsigned long	sc_s0, sc_s1, sc_s2, sc_s3, sc_s4, sc_s5, sc_s6, sc_s7;
-	unsigned long	sc_t8, sc_t9,               sc_gp, sc_sp, sc_fp, sc_ra;
+/*
+ * For now ...
+ */
+#include <linux/types.h>
+typedef __u64	sigset_t;
 
-	unsigned long	sc_epc;
-	unsigned long	sc_cause;
+#if 0
+/*
+ * This is what we should really use but the kernel can't handle
+ * a non-scalar type yet.  Since we use 64 signals only anyway we
+ * just use __u64 and pad another 64 bits in the kernel for now ...
+ */
+typedef struct {
+	unsigned int	sigbits[4];
+} sigset_t;
+#endif
 
-	unsigned long	oldmask;
+#define _NSIG		65
+#define NSIG		_NSIG
+
+/*
+ * For 1.3.0 Linux/MIPS changed the signal numbers to be compatible the ABI.
+ */
+#define SIGHUP		 1	/* Hangup (POSIX).  */
+#define SIGINT		 2	/* Interrupt (ANSI).  */
+#define SIGQUIT		 3	/* Quit (POSIX).  */
+#define SIGILL		 4	/* Illegal instruction (ANSI).  */
+#define SIGTRAP		 5	/* Trace trap (POSIX).  */
+#define SIGIOT		 6	/* IOT trap (4.2 BSD).  */
+#define SIGABRT		 SIGIOT	/* Abort (ANSI).  */
+#define SIGEMT		 7
+#define SIGFPE		 8	/* Floating-point exception (ANSI).  */
+#define SIGKILL		 9	/* Kill, unblockable (POSIX).  */
+#define SIGBUS		10	/* BUS error (4.2 BSD).  */
+#define SIGSEGV		11	/* Segmentation violation (ANSI).  */
+#define SIGSYS		12
+#define SIGPIPE		13	/* Broken pipe (POSIX).  */
+#define SIGALRM		14	/* Alarm clock (POSIX).  */
+#define SIGTERM		15	/* Termination (ANSI).  */
+#define SIGUSR1		16	/* User-defined signal 1 (POSIX).  */
+#define SIGUSR2		17	/* User-defined signal 2 (POSIX).  */
+#define SIGCHLD		18	/* Child status has changed (POSIX).  */
+#define SIGCLD		SIGCHLD	/* Same as SIGCHLD (System V).  */
+#define SIGPWR		19	/* Power failure restart (System V).  */
+#define SIGWINCH	20	/* Window size change (4.3 BSD, Sun).  */
+#define SIGURG		21	/* Urgent condition on socket (4.2 BSD).  */
+#define SIGIO		22	/* I/O now possible (4.2 BSD).  */
+#define SIGPOLL		SIGIO	/* Pollable event occured (System V).  */
+#define SIGSTOP		23	/* Stop, unblockable (POSIX).  */
+#define SIGTSTP		24	/* Keyboard stop (POSIX).  */
+#define SIGCONT		25	/* Continue (POSIX).  */
+#define SIGTTIN		26	/* Background read from tty (POSIX).  */
+#define SIGTTOU		27	/* Background write to tty (POSIX).  */
+#define SIGVTALRM	28	/* Virtual alarm clock (4.2 BSD).  */
+#define SIGPROF		29	/* Profiling alarm clock (4.2 BSD).  */
+#define SIGXCPU		30	/* CPU limit exceeded (4.2 BSD).  */
+#define SIGXFSZ		31	/* File size limit exceeded (4.2 BSD).  */
+
+/*
+ * sa_flags values: SA_STACK is not currently supported, but will allow the
+ * usage of signal stacks by using the (now obsolete) sa_restorer field in
+ * the sigaction structure as a stack pointer. This is now possible due to
+ * the changes in signal handling. LBT 010493.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ */
+#define SA_STACK	0x1
+#define SA_ONSTACK	SA_STACK
+#define SA_RESTART	0x4
+#define SA_NOCLDSTOP	0x20000
+/* Non ABI signals */
+#define SA_INTERRUPT	0x01000000
+#define SA_NOMASK	0x02000000
+#define SA_ONESHOT	0x04000000
+
+#ifdef __KERNEL__
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ */
+#define SA_PROBE SA_ONESHOT
+#define SA_SAMPLE_RANDOM SA_RESTART
+#endif
+
+#define SIG_BLOCK          1	/* for blocking signals */
+#define SIG_UNBLOCK        2	/* for unblocking signals */
+#define SIG_SETMASK        3	/* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+/* Fake signal functions */
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+
+struct sigaction {
+	unsigned int	sa_flags;
+	__sighandler_t	sa_handler;
+	sigset_t	sa_mask;
+	/*
+	 * To keep the ABI structure size we have to fill a little gap ...
+	 */
+	unsigned int	sa_mask_pad[2];
+
+	/* Abi says here follows reserved int[2] */
+	void		(*sa_restorer)(void);
+#if __mips < 3
+	/*
+	 * For 32 bit code we have to pad struct sigaction to get
+	 * constant size for the ABI
+	 */
+	int		pad0[1];	/* reserved */
+#endif
 };
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+#endif
 
 #endif /* __ASM_MIPS_SIGNAL_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h
--- v1.3.47/linux/include/asm-mips/socket.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/socket.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,58 @@
+#ifndef __ASM_MIPS_SOCKET_H
+#define __ASM_MIPS_SOCKET_H
+
+#include <linux/types.h>
+#include <asm/ioctl.h>
+
+/* Socket-level I/O control calls. */
+#define FIOGETOWN	_IOR('f', 123, int)
+#define FIOSETOWN 	_IOW('f', 124, int)
+
+#define SIOCATMARK	_IOR('s', 7, int)
+#define SIOCSPGRP	_IOW('s', 8, pid_t)
+#define SIOCGPGRP	_IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP	0x8906			/* Get stamp - linux-specific */
+
+/*
+ * For setsockoptions(2)
+ *
+ * This defines are ABI conformant as far as Linux supports these ...
+ */
+#define SOL_SOCKET	0xffff
+
+#define SO_DEBUG	0x0001
+#define SO_REUSEADDR	0x0004
+#define SO_KEEPALIVE	0x0008
+#define SO_DONTROUTE	0x0010
+#define SO_BROADCAST	0x0020
+#define SO_LINGER	0x0080
+#define SO_OOBINLINE	0x0100
+/* To add: #define SO_REUSEPORT 0x0200 */
+
+#define SO_TYPE		0x1008
+#define SO_ERROR	0x1007
+#define SO_SNDBUF	0x1001
+#define SO_RCVBUF	0x1002
+
+/* linux-specific, might as well be the same as on i386 */
+#define SO_NO_CHECK	11
+#define SO_PRIORITY	12
+#define SO_BSDCOMPAT	14
+
+/*
+ * Wierd.  There are two ABIs; in the old one SOCK_STREAM and SOCK_DGRAM
+ * have swapped values.  I choose to be compatible with the new one.
+ */
+#define SOCK_DGRAM	1		/* datagram (conn.less) socket	*/
+#define SOCK_STREAM	2		/* stream (connection) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+
+#endif /* __ASM_MIPS_SOCKET_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/stackframe.h linux/include/asm-mips/stackframe.h
--- v1.3.47/linux/include/asm-mips/stackframe.h	Fri Jan 13 20:37:30 1995
+++ linux/include/asm-mips/stackframe.h	Wed Dec 13 12:39:46 1995
@@ -11,18 +11,12 @@
 /*
  * Stack layout for all exceptions:
  *
- * ptrace needs to have all regs on the stack.
- * if the order here is changed, it needs to be 
- * updated in asm/mips/fork.c:copy_process, asm/mips/signal.c:do_signal,
- * asm-mips/ptrace.c, include/asm-mips/ptrace.h
- * and asm-mips/ptrace
+ * ptrace needs to have all regs on the stack. If the order here is changed,
+ * it needs to be updated in include/asm-mips/ptrace.h
+ *
+ * The first PTRSIZE*5 bytes are argument save space for C subroutines.
  */
-
-/*
- * Offsets into the Interrupt stackframe.
- * The first 20 bytes are reserved for the usual MIPS calling sequence
- */
-#define FR_REG1		20
+#define FR_REG1		(PTRSIZE*5)
 #define FR_REG2		((FR_REG1) + 4)
 #define FR_REG3		((FR_REG2) + 4)
 #define FR_REG4		((FR_REG3) + 4)
@@ -74,121 +68,122 @@
  */
 #define FR_INTERRUPT	((FR_CAUSE) + 4)
 #define FR_ORIG_REG2	((FR_INTERRUPT) + 4)
+#define FR_PAD1		((FR_ORIG_REG2) + 4)
 
 /*
- * Size of stack frame
+ * Size of stack frame, word/double word alignment
  */
-#define FR_SIZE		((FR_ORIG_REG2) + 4)
+#define FR_SIZE		((((FR_PAD1) + 4) + (PTRSIZE-1)) & ~(PTRSIZE-1))
 
-#define SAVE_ALL                                \
-		mfc0	k0,CP0_STATUS;          \
-		andi	k0,0x18;                /* extract KSU bits */ \
-		beqz	k0,1f;                  \
-		move	k1,sp;                  \
-		/*                              \
-		 * Called from user mode, new stack \
-		 */                             \
-		lui	k1,%hi(_kernelsp);      \
-		lw	k1,%lo(_kernelsp)(k1);  \
-1:		move	k0,sp;                  \
-		subu	sp,k1,FR_SIZE;          \
-		sw	k0,FR_REG29(sp);        \
-		sw	$2,FR_REG2(sp);         \
-		sw	$2,FR_ORIG_REG2(sp);    \
-		mfc0	v0,CP0_STATUS;          \
-		sw	v0,FR_STATUS(sp);       \
-		mfc0	v0,CP0_CAUSE;           \
-		sw	v0,FR_CAUSE(sp);        \
-		mfc0	v0,CP0_EPC;             \
-		sw	v0,FR_EPC(sp);          \
-		mfhi	v0;                     \
-		sw	v0,FR_HI(sp);           \
-		mflo	v0;                     \
-		sw	v0,FR_LO(sp);           \
-		sw	$1,FR_REG1(sp);         \
-		sw	$3,FR_REG3(sp);         \
-		sw	$4,FR_REG4(sp);         \
-		sw	$5,FR_REG5(sp);         \
-		sw	$6,FR_REG6(sp);         \
-		sw	$7,FR_REG7(sp);         \
-		sw	$8,FR_REG8(sp);         \
-		sw	$9,FR_REG9(sp);         \
-		sw	$10,FR_REG10(sp);       \
-		sw	$11,FR_REG11(sp);       \
-		sw	$12,FR_REG12(sp);       \
-		sw	$13,FR_REG13(sp);       \
-		sw	$14,FR_REG14(sp);       \
-		sw	$15,FR_REG15(sp);       \
-		sw	$16,FR_REG16(sp);       \
-		sw	$17,FR_REG17(sp);       \
-		sw	$18,FR_REG18(sp);       \
-		sw	$19,FR_REG19(sp);       \
-		sw	$20,FR_REG20(sp);       \
-		sw	$21,FR_REG21(sp);       \
-		sw	$22,FR_REG22(sp);       \
-		sw	$23,FR_REG23(sp);       \
-		sw	$24,FR_REG24(sp);       \
-		sw	$25,FR_REG25(sp);       \
-		sw	$28,FR_REG28(sp);       \
-		sw	$30,FR_REG30(sp);       \
-		sw	$31,FR_REG31(sp)
+#ifdef __R4000__
 
-#define RESTORE_ALL                             \
-		lw	v1,FR_EPC(sp);          \
-		lw	v0,FR_HI(sp);           \
-		mtc0	v1,CP0_EPC;             \
-		lw	v1,FR_LO(sp);           \
-		mthi	v0;                     \
-		lw	v0,FR_STATUS(sp);       \
-		mtlo	v1;                     \
-		mtc0	v0,CP0_STATUS;          \
-		lw	$31,FR_REG31(sp);       \
-		lw	$30,FR_REG30(sp);       \
-		lw	$28,FR_REG28(sp);       \
-		lw	$25,FR_REG25(sp);       \
-		lw	$24,FR_REG24(sp);       \
-		lw	$23,FR_REG23(sp);       \
-		lw	$22,FR_REG22(sp);       \
-		lw	$21,FR_REG21(sp);       \
-		lw	$20,FR_REG20(sp);       \
-		lw	$19,FR_REG19(sp);       \
-		lw	$18,FR_REG18(sp);       \
-		lw	$17,FR_REG17(sp);       \
-		lw	$16,FR_REG16(sp);       \
-		lw	$15,FR_REG15(sp);       \
-		lw	$14,FR_REG14(sp);       \
-		lw	$13,FR_REG13(sp);       \
-		lw	$12,FR_REG12(sp);       \
-		lw	$11,FR_REG11(sp);       \
-		lw	$10,FR_REG10(sp);       \
-		lw	$9,FR_REG9(sp);         \
-		lw	$8,FR_REG8(sp);         \
-		lw	$7,FR_REG7(sp);         \
-		lw	$6,FR_REG6(sp);         \
-		lw	$5,FR_REG5(sp);         \
-		lw	$4,FR_REG4(sp);         \
-		lw	$3,FR_REG3(sp);         \
-		lw	$2,FR_REG2(sp);         \
-		lw	$1,FR_REG1(sp);         \
-		lw	sp,FR_REG29(sp); /* Deallocate stack */ \
-		eret
+#define SAVE_ALL                                        \
+		mfc0	k0,CP0_STATUS;                  \
+		sll	k0,3;     /* extract cu0 bit */ \
+		bltz	k0,8f;                          \
+		move	k1,sp;                          \
+		/*                                      \
+		 * Called from user mode, new stack     \
+		 */                                     \
+		lui	k1,%hi(kernelsp);               \
+		lw	k1,%lo(kernelsp)(k1);           \
+8:		move	k0,sp;                          \
+		subu	sp,k1,FR_SIZE;                  \
+		sw	k0,FR_REG29(sp);                \
+		sw	$2,FR_REG2(sp);                 \
+		sw	$2,FR_ORIG_REG2(sp);            \
+		mfc0	v0,CP0_STATUS;                  \
+		sw	v0,FR_STATUS(sp);               \
+		mfc0	v0,CP0_CAUSE;                   \
+		sw	v0,FR_CAUSE(sp);                \
+		mfc0	v0,CP0_EPC;                     \
+		sw	v0,FR_EPC(sp);                  \
+		mfhi	v0;                             \
+		sw	v0,FR_HI(sp);                   \
+		mflo	v0;                             \
+		sw	v0,FR_LO(sp);                   \
+		sw	$1,FR_REG1(sp);                 \
+		sw	$3,FR_REG3(sp);                 \
+		sw	$4,FR_REG4(sp);                 \
+		sw	$5,FR_REG5(sp);                 \
+		sw	$6,FR_REG6(sp);                 \
+		sw	$7,FR_REG7(sp);                 \
+		sw	$8,FR_REG8(sp);                 \
+		sw	$9,FR_REG9(sp);                 \
+		sw	$10,FR_REG10(sp);               \
+		sw	$11,FR_REG11(sp);               \
+		sw	$12,FR_REG12(sp);               \
+		sw	$13,FR_REG13(sp);               \
+		sw	$14,FR_REG14(sp);               \
+		sw	$15,FR_REG15(sp);               \
+		sw	$16,FR_REG16(sp);               \
+		sw	$17,FR_REG17(sp);               \
+		sw	$18,FR_REG18(sp);               \
+		sw	$19,FR_REG19(sp);               \
+		sw	$20,FR_REG20(sp);               \
+		sw	$21,FR_REG21(sp);               \
+		sw	$22,FR_REG22(sp);               \
+		sw	$23,FR_REG23(sp);               \
+		sw	$24,FR_REG24(sp);               \
+		sw	$25,FR_REG25(sp);               \
+		sw	$28,FR_REG28(sp);               \
+		sw	$30,FR_REG30(sp);               \
+		sw	$31,FR_REG31(sp)
 
 /*
- * Move to kernel mode and disable interrupts
+ * Note that we restore the IE flags from stack. This means
+ * that a modified IE mask will be nullified.
  */
-#define CLI                                     \
-		mfc0	k0,CP0_STATUS;          \
-		ori	k0,k0,0x1f;             \
-		xori	k0,k0,0x1f;             \
-		mtc0	k0,CP0_STATUS
+#define RESTORE_ALL                                     \
+		.set	mips3;                          \
+		mfc0	t0,CP0_STATUS;                  \
+		ori	t0,0x1f;                        \
+		xori	t0,0x1f;                        \
+		mtc0	t0,CP0_STATUS;                  \
+		\
+		lw	v0,FR_STATUS(sp);               \
+		lw	v1,FR_LO(sp);                   \
+		mtc0	v0,CP0_STATUS;                  \
+		mtlo	v1;                             \
+		lw	v0,FR_HI(sp);                   \
+		lw	v1,FR_EPC(sp);                  \
+		mthi	v0;                             \
+		mtc0	v1,CP0_EPC;                     \
+		lw	$31,FR_REG31(sp);               \
+		lw	$30,FR_REG30(sp);               \
+		lw	$28,FR_REG28(sp);               \
+		lw	$25,FR_REG25(sp);               \
+		lw	$24,FR_REG24(sp);               \
+		lw	$23,FR_REG23(sp);               \
+		lw	$22,FR_REG22(sp);               \
+		lw	$21,FR_REG21(sp);               \
+		lw	$20,FR_REG20(sp);               \
+		lw	$19,FR_REG19(sp);               \
+		lw	$18,FR_REG18(sp);               \
+		lw	$17,FR_REG17(sp);               \
+		lw	$16,FR_REG16(sp);               \
+		lw	$15,FR_REG15(sp);               \
+		lw	$14,FR_REG14(sp);               \
+		lw	$13,FR_REG13(sp);               \
+		lw	$12,FR_REG12(sp);               \
+		lw	$11,FR_REG11(sp);               \
+		lw	$10,FR_REG10(sp);               \
+		lw	$9,FR_REG9(sp);                 \
+		lw	$8,FR_REG8(sp);                 \
+		lw	$7,FR_REG7(sp);                 \
+		lw	$6,FR_REG6(sp);                 \
+		lw	$5,FR_REG5(sp);                 \
+		lw	$4,FR_REG4(sp);                 \
+		lw	$3,FR_REG3(sp);                 \
+		lw	$2,FR_REG2(sp);                 \
+		lw	$1,FR_REG1(sp);                 \
+		lw	sp,FR_REG29(sp); /* Deallocate stack */ \
+		.set	mips0
 
-/*
- * Move to kernel mode and enable interrupts
- */
-#define STI                                     \
-		mfc0	k0,CP0_STATUS;          \
-		ori	k0,k0,0x1f;             \
-		xori	k0,k0,0x1e;             \
-		mtc0	k0,CP0_STATUS
+#else /* !defined (__R4000__) */
+
+#error "Implement SAVE_ALL and RESTORE_ALL!"
+
+#endif /* !defined (__R4000__) */
 
 #endif /* __ASM_MIPS_STACKFRAME_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/stat.h linux/include/asm-mips/stat.h
--- v1.3.47/linux/include/asm-mips/stat.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/stat.h	Wed Dec 13 12:39:46 1995
@@ -0,0 +1,55 @@
+#ifndef __ASM_MIPS_STAT_H
+#define __ASM_MIPS_STAT_H
+
+#include <linux/types.h>
+
+struct old_stat {
+	unsigned int	st_dev;
+	unsigned int	st_ino;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+	unsigned int	st_rdev;
+	long		st_size;
+	unsigned int	st_atime, st_res1;
+	unsigned int	st_mtime, st_res2;
+	unsigned int	st_ctime, st_res3;
+	unsigned int	st_blkize;
+	int		st_blocks;
+	unsigned int	st_flags;
+	unsigned int	st_gen;
+};
+
+struct new_stat {
+	dev_t		st_dev;
+	long		st_pad1[3];		/* Reserved for network id */
+	ino_t		st_ino;
+	mode_t		st_mode;
+	nlink_t		st_nlink;
+	uid_t		st_uid;
+	gid_t		st_gid;
+	dev_t		st_rdev;
+	long		st_pad2[2];
+	off_t		st_size;
+	long		st_pad3;
+	/*
+	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+	 * but we don't have it under Linux.
+	 */
+	time_t		st_atime;
+	long		reserved0;
+	time_t		st_mtime;
+	long		reserved1;
+	time_t		st_ctime;
+	long		reserved2;
+	long		st_blksize;
+	long		st_blocks;
+	char		st_fstype[16];	/* Filesystem type name */
+	long		st_pad4[8];
+	/* Linux specific fields */
+	unsigned int	st_flags;
+	unsigned int	st_gen;
+};
+
+#endif /* __ASM_MIPS_STAT_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/statfs.h linux/include/asm-mips/statfs.h
--- v1.3.47/linux/include/asm-mips/statfs.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/statfs.h	Wed Dec 13 12:39:47 1995
@@ -0,0 +1,25 @@
+#ifndef __ASM_MIPS_STATFS_H
+#define __ASM_MIPS_STATFS_H
+
+typedef struct {
+	long    val[2];
+} fsid_t;
+
+struct statfs {
+	long	f_type;
+#define f_fstyp f_type
+	long	f_bsize;
+	long	f_frsize;	/* Fragment size - unsupported */
+	long	f_blocks;
+	long	f_bfree;
+	long	f_files;
+	long	f_ffree;
+
+	/* Linux specials */
+	long	f_bavail;
+	fsid_t	f_fsid;
+	long	f_namelen;
+	long	f_spare[6];
+};
+
+#endif /* __ASM_MIPS_STATFS_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/string.h linux/include/asm-mips/string.h
--- v1.3.47/linux/include/asm-mips/string.h	Sat Jan 14 01:15:15 1995
+++ linux/include/asm-mips/string.h	Wed Dec 13 12:39:47 1995
@@ -8,12 +8,10 @@
  * Copyright (c) 1994, 1995  Waldorf Electronics
  * written by Ralf Baechle
  */
-
 #ifndef __ASM_MIPS_STRING_H
 #define __ASM_MIPS_STRING_H
 
-#include <asm/mipsregs.h>
-
+#define __HAVE_ARCH_STRCPY
 extern __inline__ char * strcpy(char * dest, const char *src)
 {
   char *xdest = dest;
@@ -22,10 +20,10 @@
 	".set\tnoreorder\n\t"
 	".set\tnoat\n"
 	"1:\tlbu\t$1,(%1)\n\t"
-	"addiu\t%1,%1,1\n\t"
+	"addiu\t%1,1\n\t"
 	"sb\t$1,(%0)\n\t"
 	"bnez\t$1,1b\n\t"
-	"addiu\t%0,%0,1\n\t"
+	"addiu\t%0,1\n\t"
 	".set\tat\n\t"
 	".set\treorder"
 	: "=r" (dest), "=r" (src)
@@ -35,6 +33,7 @@
   return xdest;
 }
 
+#define __HAVE_ARCH_STRNCPY
 extern __inline__ char * strncpy(char *dest, const char *src, size_t n)
 {
   char *xdest = dest;
@@ -62,6 +61,7 @@
   return dest;
 }
 
+#define __HAVE_ARCH_STRCMP
 extern __inline__ int strcmp(const char * cs, const char * ct)
 {
   int __res;
@@ -71,16 +71,18 @@
 	".set\tnoat\n\t"
 	"lbu\t%2,(%0)\n"
 	"1:\tlbu\t$1,(%1)\n\t"
-	"addiu\t%0,%0,1\n\t"
+	"addiu\t%0,1\n\t"
 	"bne\t$1,%2,2f\n\t"
-	"addiu\t%1,%1,1\n\t"
+	"addiu\t%1,1\n\t"
 	"bnez\t%2,1b\n\t"
 	"lbu\t%2,(%0)\n\t"
-	STR(FILL_LDS) "\n\t"
+#ifndef __R4000__
+	"nop\n\t"
+#endif
 	"move\t%2,$1\n"
-	"2:\tsub\t%2,%2,$1\n"
+	"2:\tsubu\t%2,$1\n"
 	"3:\t.set\tat\n\t"
-	".set\treorder\n\t"
+	".set\treorder"
 	: "=d" (cs), "=d" (ct), "=d" (__res)
 	: "0" (cs), "1" (ct)
 	: "$1");
@@ -88,6 +90,7 @@
   return __res;
 }
 
+#define __HAVE_ARCH_STRNCMP
 extern __inline__ int strncmp(const char * cs, const char * ct, size_t count)
 {
   char __res;
@@ -98,13 +101,13 @@
        	"1:\tlbu\t%3,(%0)\n\t"
 	"beqz\t%2,2f\n\t"
         "lbu\t$1,(%1)\n\t"
-       	"addiu\t%2,%2,-1\n\t"
+       	"subu\t%2,1\n\t"
         "bne\t$1,%3,3f\n\t"
-        "addiu\t%0,%0,1\n\t"
+        "addiu\t%0,1\n\t"
         "bnez\t%3,1b\n\t"
-        "addiu\t%1,%1,1\n"
+        "addiu\t%1,1\n"
 	"2:\tmove\t%3,$1\n"
-	"3:\tsub\t%3,%3,$1\n\t"
+	"3:\tsubu\t%3,$1\n\t"
 	".set\tat\n\t"
 	".set\treorder"
         : "=d" (cs), "=d" (ct), "=d" (count), "=d" (__res)
@@ -114,6 +117,7 @@
   return __res;
 }
 
+#define __HAVE_ARCH_MEMSET
 extern __inline__ void * memset(void * s, int c, size_t count)
 {
   void *xs = s;
@@ -133,6 +137,7 @@
   return xs;
 }
 
+#define __HAVE_ARCH_MEMCPY
 extern __inline__ void * memcpy(void * to, const void * from, size_t n)
 {
   void *xto = to;
@@ -143,11 +148,11 @@
 	".set\tnoreorder\n\t"
 	".set\tnoat\n"
 	"1:\tlbu\t$1,(%1)\n\t"
-	"addiu\t%1,%1,1\n\t"
+	"addiu\t%1,1\n\t"
 	"sb\t$1,(%0)\n\t"
-	"subu\t%2,%2,1\n\t"
+	"subu\t%2,1\n\t"
 	"bnez\t%2,1b\n\t"
-	"addiu\t%0,%0,1\n\t"
+	"addiu\t%0,1\n\t"
 	".set\tat\n\t"
 	".set\treorder"
         : "=r" (to), "=r" (from), "=r" (n)
@@ -156,6 +161,7 @@
   return xto;
 }
 
+#define __HAVE_ARCH_MEMMOVE
 extern __inline__ void * memmove(void * dest,const void * src, size_t n)
 {
   void *xdest = dest;
@@ -168,11 +174,11 @@
 	".set\tnoreorder\n\t"
 	".set\tnoat\n"
 	"1:\tlbu\t$1,(%1)\n\t"
-	"addiu\t%1,%1,1\n\t"
+	"addiu\t%1,1\n\t"
 	"sb\t$1,(%0)\n\t"
-	"subu\t%2,%2,1\n\t"
+	"subu\t%2,1\n\t"
 	"bnez\t%2,1b\n\t"
-	"addiu\t%0,%0,1\n\t"
+	"addiu\t%0,1\n\t"
 	".set\tat\n\t"
 	".set\treorder"
         : "=r" (dest), "=r" (src), "=r" (n)
@@ -183,11 +189,11 @@
 	".set\tnoreorder\n\t"
 	".set\tnoat\n"
 	"1:\tlbu\t$1,-1(%1)\n\t"
-	"subu\t%1,%1,1\n\t"
+	"subu\t%1,1\n\t"
 	"sb\t$1,-1(%0)\n\t"
-	"subu\t%2,%2,1\n\t"
+	"subu\t%2,1\n\t"
 	"bnez\t%2,1b\n\t"
-	"subu\t%0,%0,1\n\t"
+	"subu\t%0,1\n\t"
 	".set\tat\n\t"
 	".set\treorder"
         : "=r" (dest), "=r" (src), "=r" (n)
@@ -196,17 +202,18 @@
   return xdest;
 }
 
+#define __HAVE_ARCH_MEMSCAN
 extern __inline__ void * memscan(void * addr, int c, size_t size)
 {
 	if (!size)
 		return addr;
 	__asm__(".set\tnoreorder\n\t"
 		".set\tnoat\n"
-		"1:\tbeq\t$0,%1,2f\n\t"
+		"1:\tbeqz\t%1,2f\n\t"
 		"lbu\t$1,(%0)\n\t"
-		"subu\t%1,%1,1\n\t"
+		"subu\t%1,1\n\t"
 		"bnez\t%1,1b\n\t"
-		"addiu\t%0,%0,1\n\t"
+		"addiu\t%0,1\n\t"
 		".set\tat\n\t"
 		".set\treorder\n"
 		"2:"
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/sysmips.h linux/include/asm-mips/sysmips.h
--- v1.3.47/linux/include/asm-mips/sysmips.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/sysmips.h	Wed Dec 13 12:39:47 1995
@@ -0,0 +1,24 @@
+/*
+ * Definitions for the MIPS sysmips(2) call
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_SYSMIPS_H
+#define __ASM_MIPS_SYSMIPS_H
+
+/*
+ * Commands for the sysmips(2) call
+ *
+ * sysmips(2) is deprecated - though some existing software uses it.
+ * We only support the following commands.
+ */
+#define SETNAME                    1	/* set hostname                  */
+#define FLUSH_CACHE		   3	/* writeback and invalide caches */
+#define MIPS_FIXADE                7	/* control address error fixing  */
+#define MIPS_ATOMIC_SET		2001	/* atomically set variable       */
+
+#endif /* __ASM_MIPS_SYSMIPS_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/system.h linux/include/asm-mips/system.h
--- v1.3.47/linux/include/asm-mips/system.h	Fri Jan 13 20:37:06 1995
+++ linux/include/asm-mips/system.h	Wed Dec 13 12:39:47 1995
@@ -5,81 +5,108 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 by Ralf Baechle
+ * Copyright (C) 1994, 1995 by Ralf Baechle
  */
-
 #ifndef __ASM_MIPS_SYSTEM_H
 #define __ASM_MIPS_SYSTEM_H
 
-#include <linux/types.h>
-#include <asm/segment.h>
-#include <asm/mipsregs.h>
-#include <asm/mipsconfig.h>
+#include <linux/kernel.h>
 
-/*
- * (Currently empty to support debugging)
- */
-#define move_to_user_mode()              \
-__asm__ __volatile__ (                   \
+#if defined (__R4000__)
+#define sti()                            \
+__asm__ __volatile__(                    \
 	".set\tnoreorder\n\t"            \
 	".set\tnoat\n\t"                 \
-	"la\t$1,1f\n\t"                  \
-	"subu\t$1,$1,%0\n\t"             \
-	"jr\t$1\n\t"                     \
 	"mfc0\t$1,$12\n\t"               \
-	"1:ori\t$1,0x00\n\t"             \
+	"ori\t$1,0x1f\n\t"               \
+	"xori\t$1,0x1e\n\t"              \
 	"mtc0\t$1,$12\n\t"               \
-	"subu\t$29,%0\n\t"               \
 	".set\tat\n\t"                   \
 	".set\treorder"                  \
 	: /* no outputs */               \
-	: "r" (KERNELBASE));
+	: /* no inputs */                \
+	: "$1")
 
-#if defined (__R4000__)
-#define sti() \
+#define cli()                            \
 __asm__ __volatile__(                    \
+	".set\tnoreorder\n\t"            \
 	".set\tnoat\n\t"                 \
-	"mfc0\t$1,"STR(CP0_STATUS)"\n\t" \
-	"ori\t$1,$1,0x1f\n\t"            \
-	"xori\t$1,$1,0x1e\n\t"           \
-	"mtc0\t$1,"STR(CP0_STATUS)"\n\t" \
-	".set\tat"                       \
+	"mfc0\t$1,$12\n\t"               \
+	"ori\t$1,1\n\t"                  \
+	"xori\t$1,1\n\t"                 \
+	"mtc0\t$1,$12\n\t"               \
+	"nop\n\t"                        \
+	"nop\n\t"                        \
+	"nop\n\t"                        \
+	".set\tat\n\t"                   \
+	".set\treorder"                  \
 	: /* no outputs */               \
 	: /* no inputs */                \
 	: "$1")
 
-#define cli() \
+#else /* !defined (__R4000__) */
+/*
+ * Untested goodies for the R3000 based DECstation et al.
+ */
+#define sti()                            \
 __asm__ __volatile__(                    \
+	".set\tnoreorder\n\t"            \
 	".set\tnoat\n\t"                 \
-	"mfc0\t$1,"STR(CP0_STATUS)"\n\t" \
-	"ori\t$1,$1,1\n\t"               \
-	"xori\t$1,$1,1\n\t"              \
-	"mtc0\t$1,"STR(CP0_STATUS)"\n\t" \
-	".set\tat"                       \
+	"mfc0\t$1,$12\n\t"               \
+	"ori\t$1,0x01\n\t"               \
+	"mtc0\t$1,$12\n\t"               \
+	".set\tat\n\t"                   \
+	".set\treorder"                  \
+	: /* no outputs */               \
+	: /* no inputs */                \
+	: "$1")
+
+#define cli()                            \
+__asm__ __volatile__(                    \
+	".set\tnoreorder\n\t"            \
+	".set\tnoat\n\t"                 \
+	"mfc0\t$1,$12\n\t"               \
+	"ori\t$1,1\n\t"                  \
+	"xori\t$1,1\n\t"                 \
+	"mtc0\t$1,$12\n\t"               \
+	".set\tat\n\t"                   \
+	".set\treorder"                  \
 	: /* no outputs */               \
 	: /* no inputs */                \
 	: "$1")
-#else /* !defined (__R4000__) */
-/*
- * Cheese - I don't have a R3000 manual
- */
-#error "Yikes - write cli()/sti() macros for  R3000!"
 #endif /* !defined (__R4000__) */
 
 #define nop() __asm__ __volatile__ ("nop")
 
 #define save_flags(x)                    \
 __asm__ __volatile__(                    \
-	"mfc0\t%0,$12"                   \
+	".set\tnoreorder\n\t"            \
+	"mfc0\t%0,$12\n\t"               \
+	".set\treorder"                  \
 	: "=r" (x))                      \
 
 #define restore_flags(x)                 \
 __asm__ __volatile__(                    \
-	"mtc0\t%0,$12"                   \
+	".set\tnoreorder\n\t"            \
+	"mtc0\t%0,$12\n\t"               \
+	"nop\n\t"                        \
+	"nop\n\t"                        \
+	"nop\n\t"                        \
+	".set\treorder"                  \
 	: /* no output */                \
 	: "r" (x))                       \
 
-extern inline unsigned long xchg_u8(char * m, unsigned long val)
+#define sync_mem()                       \
+__asm__ __volatile__(                    \
+	".set\tnoreorder\n\t"            \
+	"sync\n\t"                       \
+	".set\treorder")                 \
+
+/*
+ * The 8 and 16 bit variants have to disable interrupts temporarily.
+ * Both are currently unused.
+ */
+extern inline unsigned long xchg_u8(volatile char * m, unsigned long val)
 {
 	unsigned long flags, retval;
 
@@ -92,7 +119,7 @@
 	return retval;
 }
 
-extern inline unsigned long xchg_u16(short * m, unsigned long val)
+extern inline unsigned long xchg_u16(volatile short * m, unsigned long val)
 {
 	unsigned long flags, retval;
 
@@ -107,9 +134,9 @@
 
 /*
  * For 32 and 64 bit operands we can take advantage of ll and sc.
- * The later isn't currently being used.
+ * FIXME: This doesn't work for R3000 machines.
  */
-extern inline unsigned long xchg_u32(int * m, unsigned long val)
+extern inline unsigned long xchg_u32(volatile int * m, unsigned long val)
 {
 	unsigned long dummy;
 
@@ -119,17 +146,20 @@
 		"ll\t%0,(%1)\n"
 		"1:\tmove\t$1,%2\n\t"
 		"sc\t$1,(%1)\n\t"
-		"beqzl\t%3,1b\n\t"
+		"beqzl\t$1,1b\n\t"
 		"ll\t%0,(%1)\n\t"
 		".set\tat\n\t"
 		".set\treorder"
 		: "=r" (val), "=r" (m), "=r" (dummy)
-		: "1" (*m), "2" (val));
+		: "1" (m), "2" (val));
 
 	return val;
 }
 
-extern inline unsigned long xchg_u64(long * m, unsigned long val)
+/*
+ * Only used for 64 bit kernel.
+ */
+extern inline unsigned long xchg_u64(volatile long * m, unsigned long val)
 {
 	unsigned long dummy;
 
@@ -139,65 +169,52 @@
 		"lld\t%0,(%1)\n"
 		"1:\tmove\t$1,%2\n\t"
 		"scd\t$1,(%1)\n\t"
-		"beqzl\t%3,1b\n\t"
+		"beqzl\t$1,1b\n\t"
 		"ll\t%0,(%1)\n\t"
 		".set\tat\n\t"
 		".set\treorder"
 		: "=r" (val), "=r" (m), "=r" (dummy)
-		: "1" (*m), "2" (val));
+		: "1" (m), "2" (val));
 
 	return val;
 }
 
-#if 0
-extern inline int tas(char * m)
-{
-	return xchg_u8(m,1);
-}
-#endif
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#define tas(ptr) (xchg((ptr),1))
+
+/*
+ * This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid xchg().
+ *
+ * This only works if the compiler isn't horribly bad at optimizing.
+ * gcc-2.5.8 reportedly can't handle this, but I define that one to
+ * be dead anyway.
+ */
+extern void __xchg_called_with_bad_pointer(void);
 
-extern inline void * xchg_ptr(void * m, void * val)
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
 {
-	return (void *) xchg_u32(m, (unsigned long) val);
+	switch (size) {
+		case 1:
+			return xchg_u8(ptr, x);
+		case 2:
+			return xchg_u16(ptr, x);
+		case 4:
+			return xchg_u32(ptr, x);
+		case 8:
+			return xchg_u64(ptr, x);
+	}
+	__xchg_called_with_bad_pointer();
+	return x;
 }
 
-extern ulong IRQ_vectors[256];
-extern ulong exception_handlers[256];
+extern unsigned long IRQ_vectors[16];
+extern unsigned long exception_handlers[32];
 
-#define set_intr_gate(n,addr) \
-	IRQ_vectors[n] = (ulong) (addr)
+#define set_int_vector(n,addr) \
+	IRQ_vectors[n] = (unsigned long) (addr)
 
 #define set_except_vector(n,addr) \
-	exception_handlers[n] = (ulong) (addr)
-
-/*
- * atomic exchange of one word
- */
-#if defined (__R4000__)
-#define atomic_exchange(m,r)             \
-	__asm__ __volatile__(            \
-		".set\tnoreorder\n\t"    \
-		"ll\t%0,(%2)\n"          \
-		"1:\tmove\t$8,%1\n\t"    \
-		"sc\t$8,(%2)\n\t"        \
-		"beql\t$0,$8,1b\n\t"     \
-		"ll\t%0,(%2)\n\t"        \
-		".set\treorder"          \
-		: "=r" (r)               \
-		: "r" (r), "r" (&(m))    \
-		: "$8","memory")
-#else
-#define atomic_exchange(m,r)             \
-	{                                \
-		unsigned long flags;     \
-		unsigned long tmp;       \
-		save_flags(flags);       \	
-		cli();                   \
-		tmp = (m);               \
-		(m) = (r);               \
-		(r) = tmp;               \
-		restore_flags(flags);    \	
-	}
-#endif
+	exception_handlers[n] = (unsigned long) (addr)
 
 #endif /* __ASM_MIPS_SYSTEM_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/termbits.h linux/include/asm-mips/termbits.h
--- v1.3.47/linux/include/asm-mips/termbits.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/termbits.h	Wed Dec 13 12:39:47 1995
@@ -0,0 +1,35 @@
+#ifndef __ASM_MIPS_TERMBITS_H
+#define __ASM_MIPS_TERMBITS_H
+
+#include <asm/ioctl.h>
+#include <asm/ioctls.h>
+
+/*
+ * The ABI says nothing about NCC but seems to use NCCS as
+ * replacement for it in struct termio
+ */
+#define NCC	8
+#define NCCS	23
+
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	char c_line;			/* line discipline */
+	unsigned char c_cc[NCCS];	/* control characters */
+};
+
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	/*
+	 * Seems nonexistant in the ABI, but Linux assumes existence ...
+	 */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+#endif /* __ASM_MIPS_TERMBITS_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- v1.3.47/linux/include/asm-mips/termios.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/termios.h	Wed Dec 13 12:39:47 1995
@@ -0,0 +1,49 @@
+#ifndef __ASM_MIPS_TERMIOS_H
+#define __ASM_MIPS_TERMIOS_H
+
+#include <linux/types.h>
+#include <asm/termbits.h>
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef __KERNEL__
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+extern inline void trans_from_termio(struct termio * termio,
+	struct termios * termios)
+{
+#define SET_LOW_BITS(x,y)	((x) = (0xffff0000 & (x)) | (y))
+	SET_LOW_BITS(termios->c_iflag, termio->c_iflag);
+	SET_LOW_BITS(termios->c_oflag, termio->c_oflag);
+	SET_LOW_BITS(termios->c_cflag, termio->c_cflag);
+	SET_LOW_BITS(termios->c_lflag, termio->c_lflag);
+#undef SET_LOW_BITS
+	memcpy(termios->c_cc, termio->c_cc, NCC);
+}
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+extern inline void trans_to_termio(struct termios * termios,
+	struct termio * termio)
+{
+	termio->c_iflag = termios->c_iflag;
+	termio->c_oflag = termios->c_oflag;
+	termio->c_cflag = termios->c_cflag;
+	termio->c_lflag = termios->c_lflag;
+	termio->c_line	= termios->c_line;
+	memcpy(termio->c_cc, termios->c_cc, NCC);
+}
+
+#endif	/* __KERNEL__ */
+
+#endif /* __ASM_MIPS_TERMIOS_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/types.h linux/include/asm-mips/types.h
--- v1.3.47/linux/include/asm-mips/types.h	Tue Jan 10 03:34:06 1995
+++ linux/include/asm-mips/types.h	Wed Dec 13 12:39:47 1995
@@ -1,19 +1,39 @@
+/*
+ * include/asm-mips/types.h
+ *
+ * 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, 1995 by Waldorf GMBH
+ * written by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_TYPES_H
 #define __ASM_MIPS_TYPES_H
 
 #ifndef _SIZE_T
 #define _SIZE_T
-typedef unsigned long size_t;
+typedef __SIZE_TYPE__ size_t;
 #endif
 
 #ifndef _SSIZE_T
 #define _SSIZE_T
-typedef long ssize_t;
+typedef __SSIZE_TYPE__ ssize_t;
 #endif
 
 #ifndef _PTRDIFF_T
 #define _PTRDIFF_T
-typedef long ptrdiff_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+#endif
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef long time_t;
+#endif
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef long clock_t;
 #endif
 
 /*
@@ -55,8 +75,8 @@
 typedef __signed short s16;
 typedef unsigned short u16;
 
-typedef __signed long s32;
-typedef unsigned long u32;
+typedef __signed int s32;
+typedef unsigned int u32;
 
 #if ((~0UL) == 0xffffffff)
 
@@ -74,20 +94,65 @@
 
 #endif /* __KERNEL__ */
 
+typedef __s32 pid_t;
+typedef __s32 uid_t;
+typedef __s32 gid_t;
+typedef __u32 dev_t;
+typedef __u32 ino_t;
+typedef __u32 mode_t;
+typedef __u32 umode_t;
+typedef __u32 nlink_t;
+typedef long daddr_t;
+typedef long off_t;
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long fd, fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long fd, fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long fd, fd_set *p)
+{ 
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
 /*
- * These definitions double the definitions from <gnu/types.h>.
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
  */
-#undef  __FDELT
-#define __FDELT(d)      ((d) / __NFDBITS)
-#undef  __FDMASK
-#define __FDMASK(d)     (1 << ((d) % __NFDBITS))
-#undef  __FD_SET
-#define __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-#undef  __FD_CLR
-#define __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#undef  __FD_ISSET
-#define __FD_ISSET(d, set)      ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
-#undef  __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(fd_set *p)
+{
+	unsigned int *tmp = p->fds_bits;
+	int i;
+
+	if (__builtin_constant_p(__FDSET_INTS)) {
+		switch (__FDSET_INTS) {
+			case 8:
+				tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
+				tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
+				return;
+		}
+	}
+	i = __FDSET_INTS;
+	while (i) {
+		i--;
+		*tmp = 0;
+		tmp++;
+	}
+}
 
 #endif /* __ASM_MIPS_TYPES_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h
--- v1.3.47/linux/include/asm-mips/unistd.h	Thu Jan 12 00:54:19 1995
+++ linux/include/asm-mips/unistd.h	Wed Dec 13 12:39:47 1995
@@ -1,43 +1,1191 @@
+/*
+ * This file contains the system call numbers.
+ *
+ * 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) 1995 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_UNISTD_H
 #define __ASM_MIPS_UNISTD_H
 
-#ifdef __KERNEL__
+/*
+ * The syscalls 0 - 3999 are reserved for a down to the root syscall
+ * compatibility with Risc/OS and IRIX.  None of these syscalls has yet been
+ * implemented.  We'll see how to deal with the various "real" BSD variants
+ * like Ultrix, NetBSD ...
+ */
+
+/*
+ * SVR4 syscalls are in the range from 1 to 999
+ */
+#define __NR_SVR4			0
+#define __NR_SVR4_syscall		(__NR_SVR4 +   0)
+#define __NR_SVR4_exit			(__NR_SVR4 +   1)
+#define __NR_SVR4_fork			(__NR_SVR4 +   2)
+#define __NR_SVR4_read			(__NR_SVR4 +   3)
+#define __NR_SVR4_write			(__NR_SVR4 +   4)
+#define __NR_SVR4_open			(__NR_SVR4 +   5)
+#define __NR_SVR4_close			(__NR_SVR4 +   6)
+#define __NR_SVR4_wait			(__NR_SVR4 +   7)
+#define __NR_SVR4_creat			(__NR_SVR4 +   8)
+#define __NR_SVR4_link			(__NR_SVR4 +   9)
+#define __NR_SVR4_unlink		(__NR_SVR4 +  10)
+#define __NR_SVR4_exec			(__NR_SVR4 +  11)
+#define __NR_SVR4_chdir			(__NR_SVR4 +  12)
+#define __NR_SVR4_gtime			(__NR_SVR4 +  13)
+#define __NR_SVR4_mknod			(__NR_SVR4 +  14)
+#define __NR_SVR4_chmod			(__NR_SVR4 +  15)
+#define __NR_SVR4_chown			(__NR_SVR4 +  16)
+#define __NR_SVR4_sbreak		(__NR_SVR4 +  17)
+#define __NR_SVR4_stat			(__NR_SVR4 +  18)
+#define __NR_SVR4_lseek			(__NR_SVR4 +  19)
+#define __NR_SVR4_getpid		(__NR_SVR4 +  20)
+#define __NR_SVR4_mount			(__NR_SVR4 +  21)
+#define __NR_SVR4_umount		(__NR_SVR4 +  22)
+#define __NR_SVR4_setuid		(__NR_SVR4 +  23)
+#define __NR_SVR4_getuid		(__NR_SVR4 +  24)
+#define __NR_SVR4_stime			(__NR_SVR4 +  25)
+#define __NR_SVR4_ptrace		(__NR_SVR4 +  26)
+#define __NR_SVR4_alarm			(__NR_SVR4 +  27)
+#define __NR_SVR4_fstat			(__NR_SVR4 +  28)
+#define __NR_SVR4_pause			(__NR_SVR4 +  29)
+#define __NR_SVR4_utime			(__NR_SVR4 +  30)
+#define __NR_SVR4_stty			(__NR_SVR4 +  31)
+#define __NR_SVR4_gtty			(__NR_SVR4 +  32)
+#define __NR_SVR4_access		(__NR_SVR4 +  33)
+#define __NR_SVR4_nice			(__NR_SVR4 +  34)
+#define __NR_SVR4_statfs		(__NR_SVR4 +  35)
+#define __NR_SVR4_sync			(__NR_SVR4 +  36)
+#define __NR_SVR4_kill			(__NR_SVR4 +  37)
+#define __NR_SVR4_fstatfs		(__NR_SVR4 +  38)
+#define __NR_SVR4_setpgrp		(__NR_SVR4 +  39)
+#define __NR_SVR4_cxenix		(__NR_SVR4 +  40)
+#define __NR_SVR4_dup			(__NR_SVR4 +  41)
+#define __NR_SVR4_pipe			(__NR_SVR4 +  42)
+#define __NR_SVR4_times			(__NR_SVR4 +  43)
+#define __NR_SVR4_profil		(__NR_SVR4 +  44)
+#define __NR_SVR4_plock			(__NR_SVR4 +  45)
+#define __NR_SVR4_setgid		(__NR_SVR4 +  46)
+#define __NR_SVR4_getgid		(__NR_SVR4 +  47)
+#define __NR_SVR4_sig			(__NR_SVR4 +  48)
+#define __NR_SVR4_msgsys		(__NR_SVR4 +  49)
+#define __NR_SVR4_sysmips		(__NR_SVR4 +  50)
+#define __NR_SVR4_sysacct		(__NR_SVR4 +  51)
+#define __NR_SVR4_shmsys		(__NR_SVR4 +  52)
+#define __NR_SVR4_semsys		(__NR_SVR4 +  53)
+#define __NR_SVR4_ioctl			(__NR_SVR4 +  54)
+#define __NR_SVR4_uadmin		(__NR_SVR4 +  55)
+#define __NR_SVR4_exch 			(__NR_SVR4 +  56)
+#define __NR_SVR4_utssys		(__NR_SVR4 +  57)
+#define __NR_SVR4_fsync			(__NR_SVR4 +  58)
+#define __NR_SVR4_exece			(__NR_SVR4 +  59)
+#define __NR_SVR4_umask			(__NR_SVR4 +  60)
+#define __NR_SVR4_chroot		(__NR_SVR4 +  61)
+#define __NR_SVR4_fcntl			(__NR_SVR4 +  62)
+#define __NR_SVR4_ulimit		(__NR_SVR4 +  63)
+#define __NR_SVR4_reserved1		(__NR_SVR4 +  64)
+#define __NR_SVR4_reserved2		(__NR_SVR4 +  65)
+#define __NR_SVR4_reserved3		(__NR_SVR4 +  66)
+#define __NR_SVR4_reserved4		(__NR_SVR4 +  67)
+#define __NR_SVR4_reserved5		(__NR_SVR4 +  68)
+#define __NR_SVR4_reserved6		(__NR_SVR4 +  69)
+#define __NR_SVR4_advfs			(__NR_SVR4 +  70)
+#define __NR_SVR4_unadvfs		(__NR_SVR4 +  71)
+#define __NR_SVR4_unused1		(__NR_SVR4 +  72)
+#define __NR_SVR4_unused2		(__NR_SVR4 +  73)
+#define __NR_SVR4_rfstart		(__NR_SVR4 +  74)
+#define __NR_SVR4_unused3		(__NR_SVR4 +  75)
+#define __NR_SVR4_rdebug		(__NR_SVR4 +  76)
+#define __NR_SVR4_rfstop		(__NR_SVR4 +  77)
+#define __NR_SVR4_rfsys			(__NR_SVR4 +  78)
+#define __NR_SVR4_rmdir			(__NR_SVR4 +  79)
+#define __NR_SVR4_mkdir			(__NR_SVR4 +  80)
+#define __NR_SVR4_getdents		(__NR_SVR4 +  81)
+#define __NR_SVR4_libattach		(__NR_SVR4 +  82)
+#define __NR_SVR4_libdetach		(__NR_SVR4 +  83)
+#define __NR_SVR4_sysfs			(__NR_SVR4 +  84)
+#define __NR_SVR4_getmsg		(__NR_SVR4 +  85)
+#define __NR_SVR4_putmsg		(__NR_SVR4 +  86)
+#define __NR_SVR4_poll			(__NR_SVR4 +  87)
+#define __NR_SVR4_lstat			(__NR_SVR4 +  88)
+#define __NR_SVR4_symlink		(__NR_SVR4 +  89)
+#define __NR_SVR4_readlink		(__NR_SVR4 +  90)
+#define __NR_SVR4_setgroups		(__NR_SVR4 +  91)
+#define __NR_SVR4_getgroups		(__NR_SVR4 +  92)
+#define __NR_SVR4_fchmod		(__NR_SVR4 +  93)
+#define __NR_SVR4_fchown		(__NR_SVR4 +  94)
+#define __NR_SVR4_sigprocmask		(__NR_SVR4 +  95)
+#define __NR_SVR4_sigsuspend		(__NR_SVR4 +  96)
+#define __NR_SVR4_sigaltstack		(__NR_SVR4 +  97)
+#define __NR_SVR4_sigaction		(__NR_SVR4 +  98)
+#define __NR_SVR4_sigpending		(__NR_SVR4 +  99)
+#define __NR_SVR4_setcontext		(__NR_SVR4 + 100)
+#define __NR_SVR4_evsys			(__NR_SVR4 + 101)
+#define __NR_SVR4_evtrapret		(__NR_SVR4 + 102)
+#define __NR_SVR4_statvfs		(__NR_SVR4 + 103)
+#define __NR_SVR4_fstatvfs		(__NR_SVR4 + 104)
+#define __NR_SVR4_reserved7		(__NR_SVR4 + 105)
+#define __NR_SVR4_nfssys		(__NR_SVR4 + 106)
+#define __NR_SVR4_waitid		(__NR_SVR4 + 107)
+#define __NR_SVR4_sigsendset		(__NR_SVR4 + 108)
+#define __NR_SVR4_hrtsys		(__NR_SVR4 + 109)
+#define __NR_SVR4_acancel		(__NR_SVR4 + 110)
+#define __NR_SVR4_async			(__NR_SVR4 + 111)
+#define __NR_SVR4_priocntlset		(__NR_SVR4 + 112)
+#define __NR_SVR4_pathconf		(__NR_SVR4 + 113)
+#define __NR_SVR4_mincore		(__NR_SVR4 + 114)
+#define __NR_SVR4_mmap			(__NR_SVR4 + 115)
+#define __NR_SVR4_mprotect		(__NR_SVR4 + 116)
+#define __NR_SVR4_munmap		(__NR_SVR4 + 117)
+#define __NR_SVR4_fpathconf		(__NR_SVR4 + 118)
+#define __NR_SVR4_vfork			(__NR_SVR4 + 119)
+#define __NR_SVR4_fchdir		(__NR_SVR4 + 120)
+#define __NR_SVR4_readv			(__NR_SVR4 + 121)
+#define __NR_SVR4_writev		(__NR_SVR4 + 122)
+#define __NR_SVR4_xstat			(__NR_SVR4 + 123)
+#define __NR_SVR4_lxstat		(__NR_SVR4 + 124)
+#define __NR_SVR4_fxstat		(__NR_SVR4 + 125)
+#define __NR_SVR4_xmknod		(__NR_SVR4 + 126)
+#define __NR_SVR4_clocal		(__NR_SVR4 + 127)
+#define __NR_SVR4_setrlimit		(__NR_SVR4 + 128)
+#define __NR_SVR4_getrlimit		(__NR_SVR4 + 129)
+#define __NR_SVR4_lchown		(__NR_SVR4 + 130)
+#define __NR_SVR4_memcntl		(__NR_SVR4 + 131)
+#define __NR_SVR4_getpmsg		(__NR_SVR4 + 132)
+#define __NR_SVR4_putpmsg		(__NR_SVR4 + 133)
+#define __NR_SVR4_rename		(__NR_SVR4 + 134)
+#define __NR_SVR4_nuname		(__NR_SVR4 + 135)
+#define __NR_SVR4_setegid		(__NR_SVR4 + 136)
+#define __NR_SVR4_sysconf		(__NR_SVR4 + 137)
+#define __NR_SVR4_adjtime		(__NR_SVR4 + 138)
+#define __NR_SVR4_sysinfo		(__NR_SVR4 + 139)
+#define __NR_SVR4_reserved8		(__NR_SVR4 + 140)
+#define __NR_SVR4_seteuid		(__NR_SVR4 + 141)
+#define __NR_SVR4_PYRAMID_statis	(__NR_SVR4 + 142)
+#define __NR_SVR4_PYRAMID_tuning	(__NR_SVR4 + 143)
+#define __NR_SVR4_PYRAMID_forcerr	(__NR_SVR4 + 144)
+#define __NR_SVR4_PYRAMID_mpcntl	(__NR_SVR4 + 145)
+#define __NR_SVR4_reserved9		(__NR_SVR4 + 146)
+#define __NR_SVR4_reserved10		(__NR_SVR4 + 147)
+#define __NR_SVR4_reserved11		(__NR_SVR4 + 148)
+#define __NR_SVR4_reserved12		(__NR_SVR4 + 149)
+#define __NR_SVR4_reserved13		(__NR_SVR4 + 150)
+#define __NR_SVR4_reserved14		(__NR_SVR4 + 151)
+#define __NR_SVR4_reserved15		(__NR_SVR4 + 152)
+#define __NR_SVR4_reserved16		(__NR_SVR4 + 153)
+#define __NR_SVR4_reserved17		(__NR_SVR4 + 154)
+#define __NR_SVR4_reserved18		(__NR_SVR4 + 155)
+#define __NR_SVR4_reserved19		(__NR_SVR4 + 156)
+#define __NR_SVR4_reserved20		(__NR_SVR4 + 157)
+#define __NR_SVR4_reserved21		(__NR_SVR4 + 158)
+#define __NR_SVR4_reserved22		(__NR_SVR4 + 159)
+#define __NR_SVR4_reserved23		(__NR_SVR4 + 160)
+#define __NR_SVR4_reserved24		(__NR_SVR4 + 161)
+#define __NR_SVR4_reserved25		(__NR_SVR4 + 162)
+#define __NR_SVR4_reserved26		(__NR_SVR4 + 163)
+#define __NR_SVR4_reserved27		(__NR_SVR4 + 164)
+#define __NR_SVR4_reserved28		(__NR_SVR4 + 165)
+#define __NR_SVR4_reserved29		(__NR_SVR4 + 166)
+#define __NR_SVR4_reserved30		(__NR_SVR4 + 167)
+#define __NR_SVR4_reserved31		(__NR_SVR4 + 168)
+#define __NR_SVR4_reserved32		(__NR_SVR4 + 169)
+#define __NR_SVR4_reserved33		(__NR_SVR4 + 170)
+#define __NR_SVR4_reserved34		(__NR_SVR4 + 171)
+#define __NR_SVR4_reserved35		(__NR_SVR4 + 172)
+#define __NR_SVR4_reserved36		(__NR_SVR4 + 173)
+#define __NR_SVR4_reserved37		(__NR_SVR4 + 174)
+#define __NR_SVR4_reserved38		(__NR_SVR4 + 175)
+#define __NR_SVR4_reserved39		(__NR_SVR4 + 176)
+#define __NR_SVR4_reserved40		(__NR_SVR4 + 177)
+#define __NR_SVR4_reserved41		(__NR_SVR4 + 178)
+#define __NR_SVR4_reserved42		(__NR_SVR4 + 179)
+#define __NR_SVR4_reserved43		(__NR_SVR4 + 180)
+#define __NR_SVR4_reserved44		(__NR_SVR4 + 181)
+#define __NR_SVR4_reserved45		(__NR_SVR4 + 182)
+#define __NR_SVR4_reserved46		(__NR_SVR4 + 183)
+#define __NR_SVR4_reserved47		(__NR_SVR4 + 184)
+#define __NR_SVR4_reserved48		(__NR_SVR4 + 185)
+#define __NR_SVR4_reserved49		(__NR_SVR4 + 186)
+#define __NR_SVR4_reserved50		(__NR_SVR4 + 187)
+#define __NR_SVR4_reserved51		(__NR_SVR4 + 188)
+#define __NR_SVR4_reserved52		(__NR_SVR4 + 189)
+#define __NR_SVR4_reserved53		(__NR_SVR4 + 190)
+#define __NR_SVR4_reserved54		(__NR_SVR4 + 191)
+#define __NR_SVR4_reserved55		(__NR_SVR4 + 192)
+#define __NR_SVR4_reserved56		(__NR_SVR4 + 193)
+#define __NR_SVR4_reserved57		(__NR_SVR4 + 194)
+#define __NR_SVR4_reserved58		(__NR_SVR4 + 195)
+#define __NR_SVR4_reserved59		(__NR_SVR4 + 196)
+#define __NR_SVR4_reserved60		(__NR_SVR4 + 197)
+#define __NR_SVR4_reserved61		(__NR_SVR4 + 198)
+#define __NR_SVR4_reserved62		(__NR_SVR4 + 199)
+#define __NR_SVR4_reserved63		(__NR_SVR4 + 200)
+#define __NR_SVR4_aread			(__NR_SVR4 + 201)
+#define __NR_SVR4_awrite		(__NR_SVR4 + 202)	
+#define __NR_SVR4_listio		(__NR_SVR4 + 203)
+#define __NR_SVR4_mips_acancel		(__NR_SVR4 + 204)
+#define __NR_SVR4_astatus		(__NR_SVR4 + 205)
+#define __NR_SVR4_await			(__NR_SVR4 + 206)
+#define __NR_SVR4_areadv		(__NR_SVR4 + 207)
+#define __NR_SVR4_awritev		(__NR_SVR4 + 208)
+#define __NR_SVR4_MIPS_reserved1	(__NR_SVR4 + 209)
+#define __NR_SVR4_MIPS_reserved2	(__NR_SVR4 + 210)
+#define __NR_SVR4_MIPS_reserved3	(__NR_SVR4 + 211)
+#define __NR_SVR4_MIPS_reserved4	(__NR_SVR4 + 212)
+#define __NR_SVR4_MIPS_reserved5	(__NR_SVR4 + 213)
+#define __NR_SVR4_MIPS_reserved6	(__NR_SVR4 + 214)
+#define __NR_SVR4_MIPS_reserved7	(__NR_SVR4 + 215)
+#define __NR_SVR4_MIPS_reserved8	(__NR_SVR4 + 216)
+#define __NR_SVR4_MIPS_reserved9	(__NR_SVR4 + 217)
+#define __NR_SVR4_MIPS_reserved10	(__NR_SVR4 + 218)
+#define __NR_SVR4_MIPS_reserved11	(__NR_SVR4 + 219)
+#define __NR_SVR4_MIPS_reserved12	(__NR_SVR4 + 220)
+#define __NR_SVR4_CDC_reserved1		(__NR_SVR4 + 221)
+#define __NR_SVR4_CDC_reserved2		(__NR_SVR4 + 222)
+#define __NR_SVR4_CDC_reserved3		(__NR_SVR4 + 223)
+#define __NR_SVR4_CDC_reserved4		(__NR_SVR4 + 224)
+#define __NR_SVR4_CDC_reserved5		(__NR_SVR4 + 225)
+#define __NR_SVR4_CDC_reserved6		(__NR_SVR4 + 226)
+#define __NR_SVR4_CDC_reserved7		(__NR_SVR4 + 227)
+#define __NR_SVR4_CDC_reserved8		(__NR_SVR4 + 228)
+#define __NR_SVR4_CDC_reserved9		(__NR_SVR4 + 229)
+#define __NR_SVR4_CDC_reserved10	(__NR_SVR4 + 230)
+#define __NR_SVR4_CDC_reserved11	(__NR_SVR4 + 231)
+#define __NR_SVR4_CDC_reserved12	(__NR_SVR4 + 232)
+#define __NR_SVR4_CDC_reserved13	(__NR_SVR4 + 233)
+#define __NR_SVR4_CDC_reserved14	(__NR_SVR4 + 234)
+#define __NR_SVR4_CDC_reserved15	(__NR_SVR4 + 235)
+#define __NR_SVR4_CDC_reserved16	(__NR_SVR4 + 236)
+#define __NR_SVR4_CDC_reserved17	(__NR_SVR4 + 237)
+#define __NR_SVR4_CDC_reserved18	(__NR_SVR4 + 238)
+#define __NR_SVR4_CDC_reserved19	(__NR_SVR4 + 239)
+#define __NR_SVR4_CDC_reserved20	(__NR_SVR4 + 240)
+
+/*
+ * SYS V syscalls are in the range from 1000 to 1999
+ */
+#define __NR_SYSV			1000
+#define __NR_SYSV_syscall		(__NR_SYSV +   0)
+#define __NR_SYSV_exit			(__NR_SYSV +   1)
+#define __NR_SYSV_fork			(__NR_SYSV +   2)
+#define __NR_SYSV_read			(__NR_SYSV +   3)
+#define __NR_SYSV_write			(__NR_SYSV +   4)
+#define __NR_SYSV_open			(__NR_SYSV +   5)
+#define __NR_SYSV_close			(__NR_SYSV +   6)
+#define __NR_SYSV_wait			(__NR_SYSV +   7)
+#define __NR_SYSV_creat			(__NR_SYSV +   8)
+#define __NR_SYSV_link			(__NR_SYSV +   9)
+#define __NR_SYSV_unlink		(__NR_SYSV +  10)
+#define __NR_SYSV_execv			(__NR_SYSV +  11)
+#define __NR_SYSV_chdir			(__NR_SYSV +  12)
+#define __NR_SYSV_time			(__NR_SYSV +  13)
+#define __NR_SYSV_mknod			(__NR_SYSV +  14)
+#define __NR_SYSV_chmod			(__NR_SYSV +  15)
+#define __NR_SYSV_chown			(__NR_SYSV +  16)
+#define __NR_SYSV_brk			(__NR_SYSV +  17)
+#define __NR_SYSV_stat			(__NR_SYSV +  18)
+#define __NR_SYSV_lseek			(__NR_SYSV +  19)
+#define __NR_SYSV_getpid		(__NR_SYSV +  20)
+#define __NR_SYSV_mount			(__NR_SYSV +  21)
+#define __NR_SYSV_umount		(__NR_SYSV +  22)
+#define __NR_SYSV_setuid		(__NR_SYSV +  23)
+#define __NR_SYSV_getuid		(__NR_SYSV +  24)
+#define __NR_SYSV_stime			(__NR_SYSV +  25)
+#define __NR_SYSV_ptrace		(__NR_SYSV +  26)
+#define __NR_SYSV_alarm			(__NR_SYSV +  27)
+#define __NR_SYSV_fstat			(__NR_SYSV +  28)
+#define __NR_SYSV_pause			(__NR_SYSV +  29)
+#define __NR_SYSV_utime			(__NR_SYSV +  30)
+#define __NR_SYSV_stty			(__NR_SYSV +  31)
+#define __NR_SYSV_gtty			(__NR_SYSV +  32)
+#define __NR_SYSV_access		(__NR_SYSV +  33)
+#define __NR_SYSV_nice			(__NR_SYSV +  34)
+#define __NR_SYSV_statfs		(__NR_SYSV +  35)
+#define __NR_SYSV_sync			(__NR_SYSV +  36)
+#define __NR_SYSV_kill			(__NR_SYSV +  37)
+#define __NR_SYSV_fstatfs		(__NR_SYSV +  38)
+#define __NR_SYSV_setpgrp		(__NR_SYSV +  39)
+#define __NR_SYSV_syssgi		(__NR_SYSV +  40)
+#define __NR_SYSV_dup			(__NR_SYSV +  41)
+#define __NR_SYSV_pipe			(__NR_SYSV +  42)
+#define __NR_SYSV_times			(__NR_SYSV +  43)
+#define __NR_SYSV_profil		(__NR_SYSV +  44)
+#define __NR_SYSV_plock			(__NR_SYSV +  45)
+#define __NR_SYSV_setgid		(__NR_SYSV +  46)
+#define __NR_SYSV_getgid		(__NR_SYSV +  47)
+#define __NR_SYSV_sig			(__NR_SYSV +  48)
+#define __NR_SYSV_msgsys		(__NR_SYSV +  49)
+#define __NR_SYSV_sysmips		(__NR_SYSV +  50)
+#define __NR_SYSV_acct			(__NR_SYSV +  51)
+#define __NR_SYSV_shmsys		(__NR_SYSV +  52)
+#define __NR_SYSV_semsys		(__NR_SYSV +  53)
+#define __NR_SYSV_ioctl			(__NR_SYSV +  54)
+#define __NR_SYSV_uadmin		(__NR_SYSV +  55)
+#define __NR_SYSV_sysmp			(__NR_SYSV +  56)
+#define __NR_SYSV_utssys		(__NR_SYSV +  57)
+#define __NR_SYSV_USG_reserved1		(__NR_SYSV +  58)
+#define __NR_SYSV_execve		(__NR_SYSV +  59)
+#define __NR_SYSV_umask			(__NR_SYSV +  60)
+#define __NR_SYSV_chroot		(__NR_SYSV +  61)
+#define __NR_SYSV_fcntl			(__NR_SYSV +  62)
+#define __NR_SYSV_ulimit		(__NR_SYSV +  63)
+#define __NR_SYSV_SAFARI4_reserved1	(__NR_SYSV +  64)
+#define __NR_SYSV_SAFARI4_reserved2	(__NR_SYSV +  65)
+#define __NR_SYSV_SAFARI4_reserved3	(__NR_SYSV +  66)
+#define __NR_SYSV_SAFARI4_reserved4	(__NR_SYSV +  67)
+#define __NR_SYSV_SAFARI4_reserved5	(__NR_SYSV +  68)
+#define __NR_SYSV_SAFARI4_reserved6	(__NR_SYSV +  69)
+#define __NR_SYSV_advfs			(__NR_SYSV +  70)
+#define __NR_SYSV_unadvfs		(__NR_SYSV +  71)
+#define __NR_SYSV_rmount		(__NR_SYSV +  72)
+#define __NR_SYSV_rumount		(__NR_SYSV +  73)
+#define __NR_SYSV_rfstart		(__NR_SYSV +  74)
+#define __NR_SYSV_getrlimit64		(__NR_SYSV +  75)
+#define __NR_SYSV_setrlimit64		(__NR_SYSV +  76)
+#define __NR_SYSV_nanosleep		(__NR_SYSV +  77)
+#define __NR_SYSV_lseek64		(__NR_SYSV +  78)
+#define __NR_SYSV_rmdir			(__NR_SYSV +  79)
+#define __NR_SYSV_mkdir			(__NR_SYSV +  80)
+#define __NR_SYSV_getdents		(__NR_SYSV +  81)
+#define __NR_SYSV_sginap		(__NR_SYSV +  82)
+#define __NR_SYSV_sgikopt		(__NR_SYSV +  83)
+#define __NR_SYSV_sysfs			(__NR_SYSV +  84)
+#define __NR_SYSV_getmsg		(__NR_SYSV +  85)
+#define __NR_SYSV_putmsg		(__NR_SYSV +  86)
+#define __NR_SYSV_poll			(__NR_SYSV +  87)
+#define __NR_SYSV_sigreturn		(__NR_SYSV +  88)
+#define __NR_SYSV_accept		(__NR_SYSV +  89)
+#define __NR_SYSV_bind			(__NR_SYSV +  90)
+#define __NR_SYSV_connect		(__NR_SYSV +  91)
+#define __NR_SYSV_gethostid		(__NR_SYSV +  92)
+#define __NR_SYSV_getpeername		(__NR_SYSV +  93)
+#define __NR_SYSV_getsockname		(__NR_SYSV +  94)
+#define __NR_SYSV_getsockopt		(__NR_SYSV +  95)
+#define __NR_SYSV_listen		(__NR_SYSV +  96)
+#define __NR_SYSV_recv			(__NR_SYSV +  97)
+#define __NR_SYSV_recvfrom		(__NR_SYSV +  98)
+#define __NR_SYSV_recvmsg		(__NR_SYSV +  99)
+#define __NR_SYSV_select		(__NR_SYSV + 100)
+#define __NR_SYSV_send			(__NR_SYSV + 101)
+#define __NR_SYSV_sendmsg		(__NR_SYSV + 102)
+#define __NR_SYSV_sendto		(__NR_SYSV + 103)
+#define __NR_SYSV_sethostid		(__NR_SYSV + 104)
+#define __NR_SYSV_setsockopt		(__NR_SYSV + 105)
+#define __NR_SYSV_shutdown		(__NR_SYSV + 106)
+#define __NR_SYSV_socket		(__NR_SYSV + 107)
+#define __NR_SYSV_gethostname		(__NR_SYSV + 108)
+#define __NR_SYSV_sethostname		(__NR_SYSV + 109)
+#define __NR_SYSV_getdomainname		(__NR_SYSV + 110)
+#define __NR_SYSV_setdomainname		(__NR_SYSV + 111)
+#define __NR_SYSV_truncate		(__NR_SYSV + 112)
+#define __NR_SYSV_ftruncate		(__NR_SYSV + 113)
+#define __NR_SYSV_rename		(__NR_SYSV + 114)
+#define __NR_SYSV_symlink		(__NR_SYSV + 115)
+#define __NR_SYSV_readlink		(__NR_SYSV + 116)
+#define __NR_SYSV_lstat			(__NR_SYSV + 117)
+#define __NR_SYSV_nfsmount		(__NR_SYSV + 118)
+#define __NR_SYSV_nfssvc		(__NR_SYSV + 119)
+#define __NR_SYSV_getfh			(__NR_SYSV + 120)
+#define __NR_SYSV_async_daemon		(__NR_SYSV + 121)
+#define __NR_SYSV_exportfs		(__NR_SYSV + 122)
+#define __NR_SYSV_setregid		(__NR_SYSV + 123)
+#define __NR_SYSV_setreuid		(__NR_SYSV + 124)
+#define __NR_SYSV_getitimer		(__NR_SYSV + 125)
+#define __NR_SYSV_setitimer		(__NR_SYSV + 126)
+#define __NR_SYSV_adjtime		(__NR_SYSV + 127)
+#define __NR_SYSV_BSD_getime		(__NR_SYSV + 128)
+#define __NR_SYSV_sproc			(__NR_SYSV + 129)
+#define __NR_SYSV_prctl			(__NR_SYSV + 130)
+#define __NR_SYSV_procblk		(__NR_SYSV + 131)
+#define __NR_SYSV_sprocsp		(__NR_SYSV + 132)
+#define __NR_SYSV_sgigsc		(__NR_SYSV + 133)
+#define __NR_SYSV_mmap			(__NR_SYSV + 134)
+#define __NR_SYSV_munmap		(__NR_SYSV + 135)
+#define __NR_SYSV_mprotect		(__NR_SYSV + 136)
+#define __NR_SYSV_msync			(__NR_SYSV + 137)
+#define __NR_SYSV_madvise		(__NR_SYSV + 138)
+#define __NR_SYSV_pagelock		(__NR_SYSV + 139)
+#define __NR_SYSV_getpagesize		(__NR_SYSV + 140)
+#define __NR_SYSV_quotactl		(__NR_SYSV + 141)
+#define __NR_SYSV_libdetach		(__NR_SYSV + 142)
+#define __NR_SYSV_BSDgetpgrp		(__NR_SYSV + 143)
+#define __NR_SYSV_BSDsetpgrp		(__NR_SYSV + 144)
+#define __NR_SYSV_vhangup		(__NR_SYSV + 145)
+#define __NR_SYSV_fsync			(__NR_SYSV + 146)
+#define __NR_SYSV_fchdir		(__NR_SYSV + 147)
+#define __NR_SYSV_getrlimit		(__NR_SYSV + 148)
+#define __NR_SYSV_setrlimit		(__NR_SYSV + 149)
+#define __NR_SYSV_cacheflush		(__NR_SYSV + 150)
+#define __NR_SYSV_cachectl		(__NR_SYSV + 151)
+#define __NR_SYSV_fchown		(__NR_SYSV + 152)
+#define __NR_SYSV_fchmod		(__NR_SYSV + 153)
+#define __NR_SYSV_wait3			(__NR_SYSV + 154)
+#define __NR_SYSV_socketpair		(__NR_SYSV + 155)
+#define __NR_SYSV_sysinfo		(__NR_SYSV + 156)
+#define __NR_SYSV_nuname		(__NR_SYSV + 157)
+#define __NR_SYSV_xstat			(__NR_SYSV + 158)
+#define __NR_SYSV_lxstat		(__NR_SYSV + 159)
+#define __NR_SYSV_fxstat		(__NR_SYSV + 160)
+#define __NR_SYSV_xmknod		(__NR_SYSV + 161)
+#define __NR_SYSV_ksigaction		(__NR_SYSV + 162)
+#define __NR_SYSV_sigpending		(__NR_SYSV + 163)
+#define __NR_SYSV_sigprocmask		(__NR_SYSV + 164)
+#define __NR_SYSV_sigsuspend		(__NR_SYSV + 165)
+#define __NR_SYSV_sigpoll		(__NR_SYSV + 166)
+#define __NR_SYSV_swapctl		(__NR_SYSV + 167)
+#define __NR_SYSV_getcontext		(__NR_SYSV + 168)
+#define __NR_SYSV_setcontext		(__NR_SYSV + 169)
+#define __NR_SYSV_waitsys		(__NR_SYSV + 170)
+#define __NR_SYSV_sigstack		(__NR_SYSV + 171)
+#define __NR_SYSV_sigaltstack		(__NR_SYSV + 172)
+#define __NR_SYSV_sigsendset		(__NR_SYSV + 173)
+#define __NR_SYSV_statvfs		(__NR_SYSV + 174)
+#define __NR_SYSV_fstatvfs		(__NR_SYSV + 175)
+#define __NR_SYSV_getpmsg		(__NR_SYSV + 176)
+#define __NR_SYSV_putpmsg		(__NR_SYSV + 177)
+#define __NR_SYSV_lchown		(__NR_SYSV + 178)
+#define __NR_SYSV_priocntl		(__NR_SYSV + 179)
+#define __NR_SYSV_ksigqueue		(__NR_SYSV + 180)
+#define __NR_SYSV_readv			(__NR_SYSV + 181)
+#define __NR_SYSV_writev		(__NR_SYSV + 182)
+#define __NR_SYSV_truncate64		(__NR_SYSV + 183)
+#define __NR_SYSV_ftruncate64		(__NR_SYSV + 184)
+#define __NR_SYSV_mmap64		(__NR_SYSV + 185)
+#define __NR_SYSV_dmi			(__NR_SYSV + 186)
+#define __NR_SYSV_pread			(__NR_SYSV + 187)
+#define __NR_SYSV_pwrite		(__NR_SYSV + 188)
+
+/*
+ * BSD 4.3 syscalls are in the range from 2000 to 2999
+ */
+#define __NR_BSD43			2000
+#define __NR_BSD43_syscall		(__NR_BSD43 +   0)
+#define __NR_BSD43_exit			(__NR_BSD43 +   1)
+#define __NR_BSD43_fork			(__NR_BSD43 +   2)
+#define __NR_BSD43_read			(__NR_BSD43 +   3)
+#define __NR_BSD43_write		(__NR_BSD43 +   4)
+#define __NR_BSD43_open			(__NR_BSD43 +   5)
+#define __NR_BSD43_close		(__NR_BSD43 +   6)
+#define __NR_BSD43_wait			(__NR_BSD43 +   7)
+#define __NR_BSD43_creat		(__NR_BSD43 +   8)
+#define __NR_BSD43_link			(__NR_BSD43 +   9)
+#define __NR_BSD43_unlink		(__NR_BSD43 +  10)
+#define __NR_BSD43_exec			(__NR_BSD43 +  11)
+#define __NR_BSD43_chdir		(__NR_BSD43 +  12)
+#define __NR_BSD43_time			(__NR_BSD43 +  13)
+#define __NR_BSD43_mknod		(__NR_BSD43 +  14)
+#define __NR_BSD43_chmod		(__NR_BSD43 +  15)
+#define __NR_BSD43_chown		(__NR_BSD43 +  16)
+#define __NR_BSD43_sbreak		(__NR_BSD43 +  17)
+#define __NR_BSD43_oldstat		(__NR_BSD43 +  18)
+#define __NR_BSD43_lseek		(__NR_BSD43 +  19)
+#define __NR_BSD43_getpid		(__NR_BSD43 +  20)
+#define __NR_BSD43_oldmount		(__NR_BSD43 +  21)
+#define __NR_BSD43_umount		(__NR_BSD43 +  22)
+#define __NR_BSD43_setuid		(__NR_BSD43 +  23)
+#define __NR_BSD43_getuid		(__NR_BSD43 +  24)
+#define __NR_BSD43_stime		(__NR_BSD43 +  25)
+#define __NR_BSD43_ptrace		(__NR_BSD43 +  26)
+#define __NR_BSD43_alarm		(__NR_BSD43 +  27)
+#define __NR_BSD43_oldfstat		(__NR_BSD43 +  28)
+#define __NR_BSD43_pause		(__NR_BSD43 +  29)
+#define __NR_BSD43_utime		(__NR_BSD43 +  30)
+#define __NR_BSD43_stty			(__NR_BSD43 +  31)
+#define __NR_BSD43_gtty			(__NR_BSD43 +  32)
+#define __NR_BSD43_access		(__NR_BSD43 +  33)
+#define __NR_BSD43_nice			(__NR_BSD43 +  34)
+#define __NR_BSD43_ftime		(__NR_BSD43 +  35)
+#define __NR_BSD43_sync			(__NR_BSD43 +  36)
+#define __NR_BSD43_kill			(__NR_BSD43 +  37)
+#define __NR_BSD43_stat			(__NR_BSD43 +  38)
+#define __NR_BSD43_oldsetpgrp		(__NR_BSD43 +  39)
+#define __NR_BSD43_lstat		(__NR_BSD43 +  40)
+#define __NR_BSD43_dup			(__NR_BSD43 +  41)
+#define __NR_BSD43_pipe			(__NR_BSD43 +  42)
+#define __NR_BSD43_times		(__NR_BSD43 +  43)
+#define __NR_BSD43_profil		(__NR_BSD43 +  44)
+#define __NR_BSD43_msgsys		(__NR_BSD43 +  45)
+#define __NR_BSD43_setgid		(__NR_BSD43 +  46)
+#define __NR_BSD43_getgid		(__NR_BSD43 +  47)
+#define __NR_BSD43_ssig			(__NR_BSD43 +  48)
+#define __NR_BSD43_reserved1		(__NR_BSD43 +  49)
+#define __NR_BSD43_reserved2		(__NR_BSD43 +  50)
+#define __NR_BSD43_sysacct		(__NR_BSD43 +  51)
+#define __NR_BSD43_phys			(__NR_BSD43 +  52)
+#define __NR_BSD43_lock			(__NR_BSD43 +  53)
+#define __NR_BSD43_ioctl		(__NR_BSD43 +  54)
+#define __NR_BSD43_reboot		(__NR_BSD43 +  55)
+#define __NR_BSD43_mpxchan		(__NR_BSD43 +  56)
+#define __NR_BSD43_symlink		(__NR_BSD43 +  57)
+#define __NR_BSD43_readlink		(__NR_BSD43 +  58)
+#define __NR_BSD43_execve		(__NR_BSD43 +  59)
+#define __NR_BSD43_umask		(__NR_BSD43 +  60)
+#define __NR_BSD43_chroot		(__NR_BSD43 +  61)
+#define __NR_BSD43_fstat		(__NR_BSD43 +  62)
+#define __NR_BSD43_reserved3		(__NR_BSD43 +  63)
+#define __NR_BSD43_getpagesize		(__NR_BSD43 +  64)
+#define __NR_BSD43_mremap		(__NR_BSD43 +  65)
+#define __NR_BSD43_vfork		(__NR_BSD43 +  66)
+#define __NR_BSD43_vread		(__NR_BSD43 +  67)
+#define __NR_BSD43_vwrite		(__NR_BSD43 +  68)
+#define __NR_BSD43_sbrk			(__NR_BSD43 +  69)
+#define __NR_BSD43_sstk			(__NR_BSD43 +  70)
+#define __NR_BSD43_mmap			(__NR_BSD43 +  71)
+#define __NR_BSD43_vadvise		(__NR_BSD43 +  72)
+#define __NR_BSD43_munmap		(__NR_BSD43 +  73)
+#define __NR_BSD43_mprotect		(__NR_BSD43 +  74)
+#define __NR_BSD43_madvise		(__NR_BSD43 +  75)
+#define __NR_BSD43_vhangup		(__NR_BSD43 +  76)
+#define __NR_BSD43_vlimit		(__NR_BSD43 +  77)
+#define __NR_BSD43_mincore		(__NR_BSD43 +  78)
+#define __NR_BSD43_getgroups		(__NR_BSD43 +  79)
+#define __NR_BSD43_setgroups		(__NR_BSD43 +  80)
+#define __NR_BSD43_getpgrp		(__NR_BSD43 +  81)
+#define __NR_BSD43_setpgrp		(__NR_BSD43 +  82)
+#define __NR_BSD43_setitimer		(__NR_BSD43 +  83)
+#define __NR_BSD43_wait3		(__NR_BSD43 +  84)
+#define __NR_BSD43_swapon		(__NR_BSD43 +  85)
+#define __NR_BSD43_getitimer		(__NR_BSD43 +  86)
+#define __NR_BSD43_gethostname		(__NR_BSD43 +  87)
+#define __NR_BSD43_sethostname		(__NR_BSD43 +  88)
+#define __NR_BSD43_getdtablesize	(__NR_BSD43 +  89)
+#define __NR_BSD43_dup2			(__NR_BSD43 +  90)
+#define __NR_BSD43_getdopt		(__NR_BSD43 +  91)
+#define __NR_BSD43_fcntl		(__NR_BSD43 +  92)
+#define __NR_BSD43_select		(__NR_BSD43 +  93)
+#define __NR_BSD43_setdopt		(__NR_BSD43 +  94)
+#define __NR_BSD43_fsync		(__NR_BSD43 +  95)
+#define __NR_BSD43_setpriority		(__NR_BSD43 +  96)
+#define __NR_BSD43_socket		(__NR_BSD43 +  97)
+#define __NR_BSD43_connect		(__NR_BSD43 +  98)
+#define __NR_BSD43_oldaccept		(__NR_BSD43 +  99)
+#define __NR_BSD43_getpriority		(__NR_BSD43 + 100)
+#define __NR_BSD43_send			(__NR_BSD43 + 101)
+#define __NR_BSD43_recv			(__NR_BSD43 + 102)
+#define __NR_BSD43_sigreturn		(__NR_BSD43 + 103)
+#define __NR_BSD43_bind			(__NR_BSD43 + 104)
+#define __NR_BSD43_setsockopt		(__NR_BSD43 + 105)
+#define __NR_BSD43_listen		(__NR_BSD43 + 106)
+#define __NR_BSD43_vtimes		(__NR_BSD43 + 107)
+#define __NR_BSD43_sigvec		(__NR_BSD43 + 108)
+#define __NR_BSD43_sigblock		(__NR_BSD43 + 109)
+#define __NR_BSD43_sigsetmask		(__NR_BSD43 + 110)
+#define __NR_BSD43_sigpause		(__NR_BSD43 + 111)
+#define __NR_BSD43_sigstack		(__NR_BSD43 + 112)
+#define __NR_BSD43_oldrecvmsg		(__NR_BSD43 + 113)
+#define __NR_BSD43_oldsendmsg		(__NR_BSD43 + 114)
+#define __NR_BSD43_vtrace		(__NR_BSD43 + 115)
+#define __NR_BSD43_gettimeofday		(__NR_BSD43 + 116)
+#define __NR_BSD43_getrusage		(__NR_BSD43 + 117)
+#define __NR_BSD43_getsockopt		(__NR_BSD43 + 118)
+#define __NR_BSD43_reserved4		(__NR_BSD43 + 119)
+#define __NR_BSD43_readv		(__NR_BSD43 + 120)
+#define __NR_BSD43_writev		(__NR_BSD43 + 121)
+#define __NR_BSD43_settimeofday		(__NR_BSD43 + 122)
+#define __NR_BSD43_fchown		(__NR_BSD43 + 123)
+#define __NR_BSD43_fchmod		(__NR_BSD43 + 124)
+#define __NR_BSD43_oldrecvfrom		(__NR_BSD43 + 125)
+#define __NR_BSD43_setreuid		(__NR_BSD43 + 126)
+#define __NR_BSD43_setregid		(__NR_BSD43 + 127)
+#define __NR_BSD43_rename		(__NR_BSD43 + 128)
+#define __NR_BSD43_truncate		(__NR_BSD43 + 129)
+#define __NR_BSD43_ftruncate		(__NR_BSD43 + 130)
+#define __NR_BSD43_flock		(__NR_BSD43 + 131)
+#define __NR_BSD43_semsys		(__NR_BSD43 + 132)
+#define __NR_BSD43_sendto		(__NR_BSD43 + 133)
+#define __NR_BSD43_shutdown		(__NR_BSD43 + 134)
+#define __NR_BSD43_socketpair		(__NR_BSD43 + 135)
+#define __NR_BSD43_mkdir		(__NR_BSD43 + 136)
+#define __NR_BSD43_rmdir		(__NR_BSD43 + 137)
+#define __NR_BSD43_utimes		(__NR_BSD43 + 138)
+#define __NR_BSD43_sigcleanup		(__NR_BSD43 + 139)
+#define __NR_BSD43_adjtime		(__NR_BSD43 + 140)
+#define __NR_BSD43_oldgetpeername	(__NR_BSD43 + 141)
+#define __NR_BSD43_gethostid		(__NR_BSD43 + 142)
+#define __NR_BSD43_sethostid		(__NR_BSD43 + 143)
+#define __NR_BSD43_getrlimit		(__NR_BSD43 + 144)
+#define __NR_BSD43_setrlimit		(__NR_BSD43 + 145)
+#define __NR_BSD43_killpg		(__NR_BSD43 + 146)
+#define __NR_BSD43_shmsys		(__NR_BSD43 + 147)
+#define __NR_BSD43_quota		(__NR_BSD43 + 148)
+#define __NR_BSD43_qquota		(__NR_BSD43 + 149)
+#define __NR_BSD43_oldgetsockname	(__NR_BSD43 + 150)
+#define __NR_BSD43_sysmips		(__NR_BSD43 + 151)
+#define __NR_BSD43_cacheflush		(__NR_BSD43 + 152)
+#define __NR_BSD43_cachectl		(__NR_BSD43 + 153)
+#define __NR_BSD43_debug		(__NR_BSD43 + 154)
+#define __NR_BSD43_reserved5		(__NR_BSD43 + 155)
+#define __NR_BSD43_reserved6		(__NR_BSD43 + 156)
+#define __NR_BSD43_nfs_mount		(__NR_BSD43 + 157)
+#define __NR_BSD43_nfs_svc		(__NR_BSD43 + 158)
+#define __NR_BSD43_getdirentries	(__NR_BSD43 + 159)
+#define __NR_BSD43_statfs		(__NR_BSD43 + 160)
+#define __NR_BSD43_fstatfs		(__NR_BSD43 + 161)
+#define __NR_BSD43_unmount		(__NR_BSD43 + 162)
+#define __NR_BSD43_async_daemon		(__NR_BSD43 + 163)
+#define __NR_BSD43_nfs_getfh		(__NR_BSD43 + 164)
+#define __NR_BSD43_getdomainname	(__NR_BSD43 + 165)
+#define __NR_BSD43_setdomainname	(__NR_BSD43 + 166)
+#define __NR_BSD43_pcfs_mount		(__NR_BSD43 + 167)
+#define __NR_BSD43_quotactl		(__NR_BSD43 + 168)
+#define __NR_BSD43_oldexportfs		(__NR_BSD43 + 169)
+#define __NR_BSD43_smount		(__NR_BSD43 + 170)
+#define __NR_BSD43_mipshwconf		(__NR_BSD43 + 171)
+#define __NR_BSD43_exportfs		(__NR_BSD43 + 172)
+#define __NR_BSD43_nfsfh_open		(__NR_BSD43 + 173)
+#define __NR_BSD43_libattach		(__NR_BSD43 + 174)
+#define __NR_BSD43_libdetach		(__NR_BSD43 + 175)
+#define __NR_BSD43_accept		(__NR_BSD43 + 176)
+#define __NR_BSD43_reserved7		(__NR_BSD43 + 177)
+#define __NR_BSD43_reserved8		(__NR_BSD43 + 178)
+#define __NR_BSD43_recvmsg		(__NR_BSD43 + 179)
+#define __NR_BSD43_recvfrom		(__NR_BSD43 + 180)
+#define __NR_BSD43_sendmsg		(__NR_BSD43 + 181)
+#define __NR_BSD43_getpeername		(__NR_BSD43 + 182)
+#define __NR_BSD43_getsockname		(__NR_BSD43 + 183)
+#define __NR_BSD43_aread		(__NR_BSD43 + 184)
+#define __NR_BSD43_awrite		(__NR_BSD43 + 185)
+#define __NR_BSD43_listio		(__NR_BSD43 + 186)
+#define __NR_BSD43_acancel		(__NR_BSD43 + 187)
+#define __NR_BSD43_astatus		(__NR_BSD43 + 188)
+#define __NR_BSD43_await		(__NR_BSD43 + 189)
+#define __NR_BSD43_areadv		(__NR_BSD43 + 190)
+#define __NR_BSD43_awritev		(__NR_BSD43 + 191)
+
+/*
+ * POSIX syscalls are in the range from 3000 to 3999
+ */
+#define __NR_POSIX			3000
+#define __NR_POSIX_syscall		(__NR_POSIX +   0)
+#define __NR_POSIX_exit			(__NR_POSIX +   1)
+#define __NR_POSIX_fork			(__NR_POSIX +   2)
+#define __NR_POSIX_read			(__NR_POSIX +   3)
+#define __NR_POSIX_write		(__NR_POSIX +   4)
+#define __NR_POSIX_open			(__NR_POSIX +   5)
+#define __NR_POSIX_close		(__NR_POSIX +   6)
+#define __NR_POSIX_wait			(__NR_POSIX +   7)
+#define __NR_POSIX_creat		(__NR_POSIX +   8)
+#define __NR_POSIX_link			(__NR_POSIX +   9)
+#define __NR_POSIX_unlink		(__NR_POSIX +  10)
+#define __NR_POSIX_exec			(__NR_POSIX +  11)
+#define __NR_POSIX_chdir		(__NR_POSIX +  12)
+#define __NR_POSIX_gtime		(__NR_POSIX +  13)
+#define __NR_POSIX_mknod		(__NR_POSIX +  14)
+#define __NR_POSIX_chmod		(__NR_POSIX +  15)
+#define __NR_POSIX_chown		(__NR_POSIX +  16)
+#define __NR_POSIX_sbreak		(__NR_POSIX +  17)
+#define __NR_POSIX_stat			(__NR_POSIX +  18)
+#define __NR_POSIX_lseek		(__NR_POSIX +  19)
+#define __NR_POSIX_getpid		(__NR_POSIX +  20)
+#define __NR_POSIX_mount		(__NR_POSIX +  21)
+#define __NR_POSIX_umount		(__NR_POSIX +  22)
+#define __NR_POSIX_setuid		(__NR_POSIX +  23)
+#define __NR_POSIX_getuid		(__NR_POSIX +  24)
+#define __NR_POSIX_stime		(__NR_POSIX +  25)
+#define __NR_POSIX_ptrace		(__NR_POSIX +  26)
+#define __NR_POSIX_alarm		(__NR_POSIX +  27)
+#define __NR_POSIX_fstat		(__NR_POSIX +  28)
+#define __NR_POSIX_pause		(__NR_POSIX +  29)
+#define __NR_POSIX_utime		(__NR_POSIX +  30)
+#define __NR_POSIX_stty			(__NR_POSIX +  31)
+#define __NR_POSIX_gtty			(__NR_POSIX +  32)
+#define __NR_POSIX_access		(__NR_POSIX +  33)
+#define __NR_POSIX_nice			(__NR_POSIX +  34)
+#define __NR_POSIX_statfs		(__NR_POSIX +  35)
+#define __NR_POSIX_sync			(__NR_POSIX +  36)
+#define __NR_POSIX_kill			(__NR_POSIX +  37)
+#define __NR_POSIX_fstatfs		(__NR_POSIX +  38)
+#define __NR_POSIX_getpgrp		(__NR_POSIX +  39)
+#define __NR_POSIX_syssgi		(__NR_POSIX +  40)
+#define __NR_POSIX_dup			(__NR_POSIX +  41)
+#define __NR_POSIX_pipe			(__NR_POSIX +  42)
+#define __NR_POSIX_times		(__NR_POSIX +  43)
+#define __NR_POSIX_profil		(__NR_POSIX +  44)
+#define __NR_POSIX_lock			(__NR_POSIX +  45)
+#define __NR_POSIX_setgid		(__NR_POSIX +  46)
+#define __NR_POSIX_getgid		(__NR_POSIX +  47)
+#define __NR_POSIX_sig			(__NR_POSIX +  48)
+#define __NR_POSIX_msgsys		(__NR_POSIX +  49)
+#define __NR_POSIX_sysmips		(__NR_POSIX +  50)
+#define __NR_POSIX_sysacct		(__NR_POSIX +  51)
+#define __NR_POSIX_shmsys		(__NR_POSIX +  52)
+#define __NR_POSIX_semsys		(__NR_POSIX +  53)
+#define __NR_POSIX_ioctl		(__NR_POSIX +  54)
+#define __NR_POSIX_uadmin		(__NR_POSIX +  55)
+#define __NR_POSIX_exch			(__NR_POSIX +  56)
+#define __NR_POSIX_utssys		(__NR_POSIX +  57)
+#define __NR_POSIX_USG_reserved1	(__NR_POSIX +  58)
+#define __NR_POSIX_exece		(__NR_POSIX +  59)
+#define __NR_POSIX_umask		(__NR_POSIX +  60)
+#define __NR_POSIX_chroot		(__NR_POSIX +  61)
+#define __NR_POSIX_fcntl		(__NR_POSIX +  62)
+#define __NR_POSIX_ulimit		(__NR_POSIX +  63)
+#define __NR_POSIX_SAFARI4_reserved1	(__NR_POSIX +  64)
+#define __NR_POSIX_SAFARI4_reserved2	(__NR_POSIX +  65)
+#define __NR_POSIX_SAFARI4_reserved3	(__NR_POSIX +  66)
+#define __NR_POSIX_SAFARI4_reserved4	(__NR_POSIX +  67)
+#define __NR_POSIX_SAFARI4_reserved5	(__NR_POSIX +  68)
+#define __NR_POSIX_SAFARI4_reserved6	(__NR_POSIX +  69)
+#define __NR_POSIX_advfs		(__NR_POSIX +  70)
+#define __NR_POSIX_unadvfs		(__NR_POSIX +  71)
+#define __NR_POSIX_rmount		(__NR_POSIX +  72)
+#define __NR_POSIX_rumount		(__NR_POSIX +  73)
+#define __NR_POSIX_rfstart		(__NR_POSIX +  74)
+#define __NR_POSIX_reserved1		(__NR_POSIX +  75)
+#define __NR_POSIX_rdebug		(__NR_POSIX +  76)
+#define __NR_POSIX_rfstop		(__NR_POSIX +  77)
+#define __NR_POSIX_rfsys		(__NR_POSIX +  78)
+#define __NR_POSIX_rmdir		(__NR_POSIX +  79)
+#define __NR_POSIX_mkdir		(__NR_POSIX +  80)
+#define __NR_POSIX_getdents		(__NR_POSIX +  81)
+#define __NR_POSIX_sginap		(__NR_POSIX +  82)
+#define __NR_POSIX_sgikopt		(__NR_POSIX +  83)
+#define __NR_POSIX_sysfs		(__NR_POSIX +  84)
+#define __NR_POSIX_getmsg		(__NR_POSIX +  85)
+#define __NR_POSIX_putmsg		(__NR_POSIX +  86)
+#define __NR_POSIX_poll			(__NR_POSIX +  87)
+#define __NR_POSIX_sigreturn		(__NR_POSIX +  88)
+#define __NR_POSIX_accept		(__NR_POSIX +  89)
+#define __NR_POSIX_bind			(__NR_POSIX +  90)
+#define __NR_POSIX_connect		(__NR_POSIX +  91)
+#define __NR_POSIX_gethostid		(__NR_POSIX +  92)
+#define __NR_POSIX_getpeername		(__NR_POSIX +  93)
+#define __NR_POSIX_getsockname		(__NR_POSIX +  94)
+#define __NR_POSIX_getsockopt		(__NR_POSIX +  95)
+#define __NR_POSIX_listen		(__NR_POSIX +  96)
+#define __NR_POSIX_recv			(__NR_POSIX +  97)
+#define __NR_POSIX_recvfrom		(__NR_POSIX +  98)
+#define __NR_POSIX_recvmsg		(__NR_POSIX +  99)
+#define __NR_POSIX_select		(__NR_POSIX + 100)
+#define __NR_POSIX_send			(__NR_POSIX + 101)
+#define __NR_POSIX_sendmsg		(__NR_POSIX + 102)
+#define __NR_POSIX_sendto		(__NR_POSIX + 103)
+#define __NR_POSIX_sethostid		(__NR_POSIX + 104)
+#define __NR_POSIX_setsockopt		(__NR_POSIX + 105)
+#define __NR_POSIX_shutdown		(__NR_POSIX + 106)
+#define __NR_POSIX_socket		(__NR_POSIX + 107)
+#define __NR_POSIX_gethostname		(__NR_POSIX + 108)
+#define __NR_POSIX_sethostname		(__NR_POSIX + 109)
+#define __NR_POSIX_getdomainname	(__NR_POSIX + 110)
+#define __NR_POSIX_setdomainname	(__NR_POSIX + 111)
+#define __NR_POSIX_truncate		(__NR_POSIX + 112)
+#define __NR_POSIX_ftruncate		(__NR_POSIX + 113)
+#define __NR_POSIX_rename		(__NR_POSIX + 114)
+#define __NR_POSIX_symlink		(__NR_POSIX + 115)
+#define __NR_POSIX_readlink		(__NR_POSIX + 116)
+#define __NR_POSIX_lstat		(__NR_POSIX + 117)
+#define __NR_POSIX_nfs_mount		(__NR_POSIX + 118)
+#define __NR_POSIX_nfs_svc		(__NR_POSIX + 119)
+#define __NR_POSIX_nfs_getfh		(__NR_POSIX + 120)
+#define __NR_POSIX_async_daemon		(__NR_POSIX + 121)
+#define __NR_POSIX_exportfs		(__NR_POSIX + 122)
+#define __NR_POSIX_SGI_setregid		(__NR_POSIX + 123)
+#define __NR_POSIX_SGI_setreuid		(__NR_POSIX + 124)
+#define __NR_POSIX_getitimer		(__NR_POSIX + 125)
+#define __NR_POSIX_setitimer		(__NR_POSIX + 126)
+#define __NR_POSIX_adjtime		(__NR_POSIX + 127)
+#define __NR_POSIX_SGI_bsdgettime	(__NR_POSIX + 128)
+#define __NR_POSIX_SGI_sproc		(__NR_POSIX + 129)
+#define __NR_POSIX_SGI_prctl		(__NR_POSIX + 130)
+#define __NR_POSIX_SGI_blkproc		(__NR_POSIX + 131)
+#define __NR_POSIX_SGI_reserved1	(__NR_POSIX + 132)
+#define __NR_POSIX_SGI_sgigsc		(__NR_POSIX + 133)
+#define __NR_POSIX_SGI_mmap		(__NR_POSIX + 134)
+#define __NR_POSIX_SGI_munmap		(__NR_POSIX + 135)
+#define __NR_POSIX_SGI_mprotect		(__NR_POSIX + 136)
+#define __NR_POSIX_SGI_msync		(__NR_POSIX + 137)
+#define __NR_POSIX_SGI_madvise		(__NR_POSIX + 138)
+#define __NR_POSIX_SGI_mpin		(__NR_POSIX + 139)
+#define __NR_POSIX_SGI_getpagesize	(__NR_POSIX + 140)
+#define __NR_POSIX_SGI_libattach	(__NR_POSIX + 141)
+#define __NR_POSIX_SGI_libdetach	(__NR_POSIX + 142)
+#define __NR_POSIX_SGI_getpgrp		(__NR_POSIX + 143)
+#define __NR_POSIX_SGI_setpgrp		(__NR_POSIX + 144)
+#define __NR_POSIX_SGI_reserved2	(__NR_POSIX + 145)
+#define __NR_POSIX_SGI_reserved3	(__NR_POSIX + 146)
+#define __NR_POSIX_SGI_reserved4	(__NR_POSIX + 147)
+#define __NR_POSIX_SGI_reserved5	(__NR_POSIX + 148)
+#define __NR_POSIX_SGI_reserved6	(__NR_POSIX + 149)
+#define __NR_POSIX_cacheflush		(__NR_POSIX + 150)
+#define __NR_POSIX_cachectl		(__NR_POSIX + 151)
+#define __NR_POSIX_fchown		(__NR_POSIX + 152)
+#define __NR_POSIX_fchmod		(__NR_POSIX + 153)
+#define __NR_POSIX_wait3		(__NR_POSIX + 154)
+#define __NR_POSIX_mmap			(__NR_POSIX + 155)
+#define __NR_POSIX_munmap		(__NR_POSIX + 156)
+#define __NR_POSIX_madvise		(__NR_POSIX + 157)
+#define __NR_POSIX_BSD_getpagesize	(__NR_POSIX + 158)
+#define __NR_POSIX_setreuid		(__NR_POSIX + 159)
+#define __NR_POSIX_setregid		(__NR_POSIX + 160)
+#define __NR_POSIX_setpgid		(__NR_POSIX + 161)
+#define __NR_POSIX_getgroups		(__NR_POSIX + 162)
+#define __NR_POSIX_setgroups		(__NR_POSIX + 163)
+#define __NR_POSIX_gettimeofday		(__NR_POSIX + 164)
+#define __NR_POSIX_getrusage		(__NR_POSIX + 165)
+#define __NR_POSIX_getrlimit		(__NR_POSIX + 166)
+#define __NR_POSIX_setrlimit		(__NR_POSIX + 167)
+#define __NR_POSIX_waitpid		(__NR_POSIX + 168)
+#define __NR_POSIX_dup2			(__NR_POSIX + 169)
+#define __NR_POSIX_reserved2		(__NR_POSIX + 170)
+#define __NR_POSIX_reserved3		(__NR_POSIX + 171)
+#define __NR_POSIX_reserved4		(__NR_POSIX + 172)
+#define __NR_POSIX_reserved5		(__NR_POSIX + 173)
+#define __NR_POSIX_reserved6		(__NR_POSIX + 174)
+#define __NR_POSIX_reserved7		(__NR_POSIX + 175)
+#define __NR_POSIX_reserved8		(__NR_POSIX + 176)
+#define __NR_POSIX_reserved9		(__NR_POSIX + 177)
+#define __NR_POSIX_reserved10		(__NR_POSIX + 178)
+#define __NR_POSIX_reserved11		(__NR_POSIX + 179)
+#define __NR_POSIX_reserved12		(__NR_POSIX + 180)
+#define __NR_POSIX_reserved13		(__NR_POSIX + 181)
+#define __NR_POSIX_reserved14		(__NR_POSIX + 182)
+#define __NR_POSIX_reserved15		(__NR_POSIX + 183)
+#define __NR_POSIX_reserved16		(__NR_POSIX + 184)
+#define __NR_POSIX_reserved17		(__NR_POSIX + 185)
+#define __NR_POSIX_reserved18		(__NR_POSIX + 186)
+#define __NR_POSIX_reserved19		(__NR_POSIX + 187)
+#define __NR_POSIX_reserved20		(__NR_POSIX + 188)
+#define __NR_POSIX_reserved21		(__NR_POSIX + 189)
+#define __NR_POSIX_reserved22		(__NR_POSIX + 190)
+#define __NR_POSIX_reserved23		(__NR_POSIX + 191)
+#define __NR_POSIX_reserved24		(__NR_POSIX + 192)
+#define __NR_POSIX_reserved25		(__NR_POSIX + 193)
+#define __NR_POSIX_reserved26		(__NR_POSIX + 194)
+#define __NR_POSIX_reserved27		(__NR_POSIX + 195)
+#define __NR_POSIX_reserved28		(__NR_POSIX + 196)
+#define __NR_POSIX_reserved29		(__NR_POSIX + 197)
+#define __NR_POSIX_reserved30		(__NR_POSIX + 198)
+#define __NR_POSIX_reserved31		(__NR_POSIX + 199)
+#define __NR_POSIX_reserved32		(__NR_POSIX + 200)
+#define __NR_POSIX_reserved33		(__NR_POSIX + 201)
+#define __NR_POSIX_reserved34		(__NR_POSIX + 202)
+#define __NR_POSIX_reserved35		(__NR_POSIX + 203)
+#define __NR_POSIX_reserved36		(__NR_POSIX + 204)
+#define __NR_POSIX_reserved37		(__NR_POSIX + 205)
+#define __NR_POSIX_reserved38		(__NR_POSIX + 206)
+#define __NR_POSIX_reserved39		(__NR_POSIX + 207)
+#define __NR_POSIX_reserved40		(__NR_POSIX + 208)
+#define __NR_POSIX_reserved41		(__NR_POSIX + 209)
+#define __NR_POSIX_reserved42		(__NR_POSIX + 210)
+#define __NR_POSIX_reserved43		(__NR_POSIX + 211)
+#define __NR_POSIX_reserved44		(__NR_POSIX + 212)
+#define __NR_POSIX_reserved45		(__NR_POSIX + 213)
+#define __NR_POSIX_reserved46		(__NR_POSIX + 214)
+#define __NR_POSIX_reserved47		(__NR_POSIX + 215)
+#define __NR_POSIX_reserved48		(__NR_POSIX + 216)
+#define __NR_POSIX_reserved49		(__NR_POSIX + 217)
+#define __NR_POSIX_reserved50		(__NR_POSIX + 218)
+#define __NR_POSIX_reserved51		(__NR_POSIX + 219)
+#define __NR_POSIX_reserved52		(__NR_POSIX + 220)
+#define __NR_POSIX_reserved53		(__NR_POSIX + 221)
+#define __NR_POSIX_reserved54		(__NR_POSIX + 222)
+#define __NR_POSIX_reserved55		(__NR_POSIX + 223)
+#define __NR_POSIX_reserved56		(__NR_POSIX + 224)
+#define __NR_POSIX_reserved57		(__NR_POSIX + 225)
+#define __NR_POSIX_reserved58		(__NR_POSIX + 226)
+#define __NR_POSIX_reserved59		(__NR_POSIX + 227)
+#define __NR_POSIX_reserved60		(__NR_POSIX + 228)
+#define __NR_POSIX_reserved61		(__NR_POSIX + 229)
+#define __NR_POSIX_reserved62		(__NR_POSIX + 230)
+#define __NR_POSIX_reserved63		(__NR_POSIX + 231)
+#define __NR_POSIX_reserved64		(__NR_POSIX + 232)
+#define __NR_POSIX_reserved65		(__NR_POSIX + 233)
+#define __NR_POSIX_reserved66		(__NR_POSIX + 234)
+#define __NR_POSIX_reserved67		(__NR_POSIX + 235)
+#define __NR_POSIX_reserved68		(__NR_POSIX + 236)
+#define __NR_POSIX_reserved69		(__NR_POSIX + 237)
+#define __NR_POSIX_reserved70		(__NR_POSIX + 238)
+#define __NR_POSIX_reserved71		(__NR_POSIX + 239)
+#define __NR_POSIX_reserved72		(__NR_POSIX + 240)
+#define __NR_POSIX_reserved73		(__NR_POSIX + 241)
+#define __NR_POSIX_reserved74		(__NR_POSIX + 242)
+#define __NR_POSIX_reserved75		(__NR_POSIX + 243)
+#define __NR_POSIX_reserved76		(__NR_POSIX + 244)
+#define __NR_POSIX_reserved77		(__NR_POSIX + 245)
+#define __NR_POSIX_reserved78		(__NR_POSIX + 246)
+#define __NR_POSIX_reserved79		(__NR_POSIX + 247)
+#define __NR_POSIX_reserved80		(__NR_POSIX + 248)
+#define __NR_POSIX_reserved81		(__NR_POSIX + 249)
+#define __NR_POSIX_reserved82		(__NR_POSIX + 250)
+#define __NR_POSIX_reserved83		(__NR_POSIX + 251)
+#define __NR_POSIX_reserved84		(__NR_POSIX + 252)
+#define __NR_POSIX_reserved85		(__NR_POSIX + 253)
+#define __NR_POSIX_reserved86		(__NR_POSIX + 254)
+#define __NR_POSIX_reserved87		(__NR_POSIX + 255)
+#define __NR_POSIX_reserved88		(__NR_POSIX + 256)
+#define __NR_POSIX_reserved89		(__NR_POSIX + 257)
+#define __NR_POSIX_reserved90		(__NR_POSIX + 258)
+#define __NR_POSIX_reserved91		(__NR_POSIX + 259)
+#define __NR_POSIX_netboot		(__NR_POSIX + 260)
+#define __NR_POSIX_netunboot		(__NR_POSIX + 261)
+#define __NR_POSIX_rdump		(__NR_POSIX + 262)
+#define __NR_POSIX_setsid		(__NR_POSIX + 263)
+#define __NR_POSIX_getmaxsig		(__NR_POSIX + 264)
+#define __NR_POSIX_sigpending		(__NR_POSIX + 265)
+#define __NR_POSIX_sigprocmask		(__NR_POSIX + 266)
+#define __NR_POSIX_sigsuspend		(__NR_POSIX + 267)
+#define __NR_POSIX_sigaction		(__NR_POSIX + 268)
+#define __NR_POSIX_MIPS_reserved1	(__NR_POSIX + 269)
+#define __NR_POSIX_MIPS_reserved2	(__NR_POSIX + 270)
+#define __NR_POSIX_MIPS_reserved3	(__NR_POSIX + 271)
+#define __NR_POSIX_MIPS_reserved4	(__NR_POSIX + 272)
+#define __NR_POSIX_MIPS_reserved5	(__NR_POSIX + 273)
+#define __NR_POSIX_MIPS_reserved6	(__NR_POSIX + 274)
+#define __NR_POSIX_MIPS_reserved7	(__NR_POSIX + 275)
+#define __NR_POSIX_MIPS_reserved8	(__NR_POSIX + 276)
+#define __NR_POSIX_MIPS_reserved9	(__NR_POSIX + 277)
+#define __NR_POSIX_MIPS_reserved10	(__NR_POSIX + 278)
+#define __NR_POSIX_MIPS_reserved11	(__NR_POSIX + 279)
+#define __NR_POSIX_TANDEM_reserved1	(__NR_POSIX + 280)
+#define __NR_POSIX_TANDEM_reserved2	(__NR_POSIX + 281)
+#define __NR_POSIX_TANDEM_reserved3	(__NR_POSIX + 282)
+#define __NR_POSIX_TANDEM_reserved4	(__NR_POSIX + 283)
+#define __NR_POSIX_TANDEM_reserved5	(__NR_POSIX + 284)
+#define __NR_POSIX_TANDEM_reserved6	(__NR_POSIX + 285)
+#define __NR_POSIX_TANDEM_reserved7	(__NR_POSIX + 286)
+#define __NR_POSIX_TANDEM_reserved8	(__NR_POSIX + 287)
+#define __NR_POSIX_TANDEM_reserved9	(__NR_POSIX + 288)
+#define __NR_POSIX_TANDEM_reserved10	(__NR_POSIX + 289)
+#define __NR_POSIX_TANDEM_reserved11	(__NR_POSIX + 290)
+#define __NR_POSIX_TANDEM_reserved12	(__NR_POSIX + 291)
+#define __NR_POSIX_TANDEM_reserved13	(__NR_POSIX + 292)
+#define __NR_POSIX_TANDEM_reserved14	(__NR_POSIX + 293)
+#define __NR_POSIX_TANDEM_reserved15	(__NR_POSIX + 294)
+#define __NR_POSIX_TANDEM_reserved16	(__NR_POSIX + 295)
+#define __NR_POSIX_TANDEM_reserved17	(__NR_POSIX + 296)
+#define __NR_POSIX_TANDEM_reserved18	(__NR_POSIX + 297)
+#define __NR_POSIX_TANDEM_reserved19	(__NR_POSIX + 298)
+#define __NR_POSIX_TANDEM_reserved20	(__NR_POSIX + 299)
+#define __NR_POSIX_SGI_reserved7	(__NR_POSIX + 300)
+#define __NR_POSIX_SGI_reserved8	(__NR_POSIX + 301)
+#define __NR_POSIX_SGI_reserved9	(__NR_POSIX + 302)
+#define __NR_POSIX_SGI_reserved10	(__NR_POSIX + 303)
+#define __NR_POSIX_SGI_reserved11	(__NR_POSIX + 304)
+#define __NR_POSIX_SGI_reserved12	(__NR_POSIX + 305)
+#define __NR_POSIX_SGI_reserved13	(__NR_POSIX + 306)
+#define __NR_POSIX_SGI_reserved14	(__NR_POSIX + 307)
+#define __NR_POSIX_SGI_reserved15	(__NR_POSIX + 308)
+#define __NR_POSIX_SGI_reserved16	(__NR_POSIX + 309)
+#define __NR_POSIX_SGI_reserved17	(__NR_POSIX + 310)
+#define __NR_POSIX_SGI_reserved18	(__NR_POSIX + 311)
+#define __NR_POSIX_SGI_reserved19	(__NR_POSIX + 312)
+#define __NR_POSIX_SGI_reserved20	(__NR_POSIX + 313)
+#define __NR_POSIX_SGI_reserved21	(__NR_POSIX + 314)
+#define __NR_POSIX_SGI_reserved22	(__NR_POSIX + 315)
+#define __NR_POSIX_SGI_reserved23	(__NR_POSIX + 316)
+#define __NR_POSIX_SGI_reserved24	(__NR_POSIX + 317)
+#define __NR_POSIX_SGI_reserved25	(__NR_POSIX + 318)
+#define __NR_POSIX_SGI_reserved26	(__NR_POSIX + 319)
+
+/*
+ * Linux syscalls are in the range from 4000 to 4999
+ * Hopefully these syscall numbers are unused ...  If not everyone using
+ * statically linked binaries is pretty upsh*t.  You've been warned.
+ */
+#define __NR_Linux			4000
+#define __NR_syscall			(__NR_Linux +   0)
+#define __NR_exit			(__NR_Linux +   1)
+#define __NR_fork			(__NR_Linux +   2)
+#define __NR_read			(__NR_Linux +   3)
+#define __NR_write			(__NR_Linux +   4)
+#define __NR_open			(__NR_Linux +   5)
+#define __NR_close			(__NR_Linux +   6)
+#define __NR_waitpid			(__NR_Linux +   7)
+#define __NR_creat			(__NR_Linux +   8)
+#define __NR_link			(__NR_Linux +   9)
+#define __NR_unlink			(__NR_Linux +  10)
+#define __NR_execve			(__NR_Linux +  11)
+#define __NR_chdir			(__NR_Linux +  12)
+#define __NR_time			(__NR_Linux +  13)
+#define __NR_mknod			(__NR_Linux +  14)
+#define __NR_chmod			(__NR_Linux +  15)
+#define __NR_chown			(__NR_Linux +  16)
+#define __NR_break			(__NR_Linux +  17)
+#define __NR_oldstat			(__NR_Linux +  18)
+#define __NR_lseek			(__NR_Linux +  19)
+#define __NR_getpid			(__NR_Linux +  20)
+#define __NR_mount			(__NR_Linux +  21)
+#define __NR_umount			(__NR_Linux +  22)
+#define __NR_setuid			(__NR_Linux +  23)
+#define __NR_getuid			(__NR_Linux +  24)
+#define __NR_stime			(__NR_Linux +  25)
+#define __NR_ptrace			(__NR_Linux +  26)
+#define __NR_alarm			(__NR_Linux +  27)
+#define __NR_oldfstat			(__NR_Linux +  28)
+#define __NR_pause			(__NR_Linux +  29)
+#define __NR_utime			(__NR_Linux +  30)
+#define __NR_stty			(__NR_Linux +  31)
+#define __NR_gtty			(__NR_Linux +  32)
+#define __NR_access			(__NR_Linux +  33)
+#define __NR_nice			(__NR_Linux +  34)
+#define __NR_ftime			(__NR_Linux +  35)
+#define __NR_sync			(__NR_Linux +  36)
+#define __NR_kill			(__NR_Linux +  37)
+#define __NR_rename			(__NR_Linux +  38)
+#define __NR_mkdir			(__NR_Linux +  39)
+#define __NR_rmdir			(__NR_Linux +  40)
+#define __NR_dup			(__NR_Linux +  41)
+#define __NR_pipe			(__NR_Linux +  42)
+#define __NR_times			(__NR_Linux +  43)
+#define __NR_prof			(__NR_Linux +  44)
+#define __NR_brk			(__NR_Linux +  45)
+#define __NR_setgid			(__NR_Linux +  46)
+#define __NR_getgid			(__NR_Linux +  47)
+#define __NR_signal			(__NR_Linux +  48)
+#define __NR_geteuid			(__NR_Linux +  49)
+#define __NR_getegid			(__NR_Linux +  50)
+#define __NR_acct			(__NR_Linux +  51)
+#define __NR_phys			(__NR_Linux +  52)
+#define __NR_lock			(__NR_Linux +  53)
+#define __NR_ioctl			(__NR_Linux +  54)
+#define __NR_fcntl			(__NR_Linux +  55)
+#define __NR_mpx			(__NR_Linux +  56)
+#define __NR_setpgid			(__NR_Linux +  57)
+#define __NR_ulimit			(__NR_Linux +  58)
+#define __NR_oldolduname		(__NR_Linux +  59)
+#define __NR_umask			(__NR_Linux +  60)
+#define __NR_chroot			(__NR_Linux +  61)
+#define __NR_ustat			(__NR_Linux +  62)
+#define __NR_dup2			(__NR_Linux +  63)
+#define __NR_getppid			(__NR_Linux +  64)
+#define __NR_getpgrp			(__NR_Linux +  65)
+#define __NR_setsid			(__NR_Linux +  66)
+#define __NR_sigaction			(__NR_Linux +  67)
+#define __NR_sgetmask			(__NR_Linux +  68)
+#define __NR_ssetmask			(__NR_Linux +  69)
+#define __NR_setreuid			(__NR_Linux +  70)
+#define __NR_setregid			(__NR_Linux +  71)
+#define __NR_sigsuspend			(__NR_Linux +  72)
+#define __NR_sigpending			(__NR_Linux +  73)
+#define __NR_sethostname		(__NR_Linux +  74)
+#define __NR_setrlimit			(__NR_Linux +  75)
+#define __NR_getrlimit			(__NR_Linux +  76)
+#define __NR_getrusage			(__NR_Linux +  77)
+#define __NR_gettimeofday		(__NR_Linux +  78)
+#define __NR_settimeofday		(__NR_Linux +  79)
+#define __NR_getgroups			(__NR_Linux +  80)
+#define __NR_setgroups			(__NR_Linux +  81)
+#define __NR_select			(__NR_Linux +  82)
+#define __NR_symlink			(__NR_Linux +  83)
+#define __NR_oldlstat			(__NR_Linux +  84)
+#define __NR_readlink			(__NR_Linux +  85)
+#define __NR_uselib			(__NR_Linux +  86)
+#define __NR_swapon			(__NR_Linux +  87)
+#define __NR_reboot			(__NR_Linux +  88)
+#define __NR_readdir			(__NR_Linux +  89)
+#define __NR_mmap			(__NR_Linux +  90)
+#define __NR_munmap			(__NR_Linux +  91)
+#define __NR_truncate			(__NR_Linux +  92)
+#define __NR_ftruncate			(__NR_Linux +  93)
+#define __NR_fchmod			(__NR_Linux +  94)
+#define __NR_fchown			(__NR_Linux +  95)
+#define __NR_getpriority		(__NR_Linux +  96)
+#define __NR_setpriority		(__NR_Linux +  97)
+#define __NR_profil			(__NR_Linux +  98)
+#define __NR_statfs			(__NR_Linux +  99)
+#define __NR_fstatfs			(__NR_Linux + 100)
+#define __NR_ioperm			(__NR_Linux + 101)
+#define __NR_socketcall			(__NR_Linux + 102)
+#define __NR_syslog			(__NR_Linux + 103)
+#define __NR_setitimer			(__NR_Linux + 104)
+#define __NR_getitimer			(__NR_Linux + 105)
+#define __NR_stat			(__NR_Linux + 106)
+#define __NR_lstat			(__NR_Linux + 107)
+#define __NR_fstat			(__NR_Linux + 108)
+#define __NR_olduname			(__NR_Linux + 109)
+#define __NR_iopl			(__NR_Linux + 110)
+#define __NR_vhangup			(__NR_Linux + 111)
+#define __NR_idle			(__NR_Linux + 112)
+#define __NR_vm86			(__NR_Linux + 113)
+#define __NR_wait4			(__NR_Linux + 114)
+#define __NR_swapoff			(__NR_Linux + 115)
+#define __NR_sysinfo			(__NR_Linux + 116)
+#define __NR_ipc			(__NR_Linux + 117)
+#define __NR_fsync			(__NR_Linux + 118)
+#define __NR_sigreturn			(__NR_Linux + 119)
+#define __NR_clone			(__NR_Linux + 120)
+#define __NR_setdomainname		(__NR_Linux + 121)
+#define __NR_uname			(__NR_Linux + 122)
+#define __NR_modify_ldt			(__NR_Linux + 123)
+#define __NR_adjtimex			(__NR_Linux + 124)
+#define __NR_mprotect			(__NR_Linux + 125)
+#define __NR_sigprocmask		(__NR_Linux + 126)
+#define __NR_create_module		(__NR_Linux + 127)
+#define __NR_init_module		(__NR_Linux + 128)
+#define __NR_delete_module		(__NR_Linux + 129)
+#define __NR_get_kernel_syms		(__NR_Linux + 130)
+#define __NR_quotactl			(__NR_Linux + 131)
+#define __NR_getpgid			(__NR_Linux + 132)
+#define __NR_fchdir			(__NR_Linux + 133)
+#define __NR_bdflush			(__NR_Linux + 134)
+#define __NR_sysfs			(__NR_Linux + 135)
+#define __NR_personality		(__NR_Linux + 136)
+#define __NR_afs_syscall		(__NR_Linux + 137) /* Syscall for Andrew File System */
+#define __NR_setfsuid			(__NR_Linux + 138)
+#define __NR_setfsgid			(__NR_Linux + 139)
+#define __NR__llseek			(__NR_Linux + 140)
+#define __NR_getdents			(__NR_Linux + 141)
+#define __NR__newselect			(__NR_Linux + 142)
+#define __NR_flock			(__NR_Linux + 143)
+#define __NR_msync			(__NR_Linux + 144)
+#define __NR_readv			(__NR_Linux + 145)
+#define __NR_writev			(__NR_Linux + 146)
+#define __NR_cacheflush			(__NR_Linux + 147)
+#define __NR_cachectl			(__NR_Linux + 148)
+#define __NR_sysmips			(__NR_Linux + 149)
+#define __NR_setup			(__NR_Linux + 150)	/* used only by init, to get system going */
+#define __NR_getsid			(__NR_Linux + 151)
+#define __NR_reserved1			(__NR_Linux + 152)
+#define __NR_reserved2			(__NR_Linux + 153)
+#define __NR_mlock			(__NR_Linux + 154)
+#define __NR_munlock			(__NR_Linux + 155)
+#define __NR_mlockall			(__NR_Linux + 156)
+#define __NR_munlockall			(__NR_Linux + 157)
+
 
-#include <asm/mipsconfig.h>
 /*
- * Ugly kludge to enforce 32bit mode proof code.
- * Access errno via USEG, not KSEGx for internal kernel syscalls
+ * Offset of the last Linux flavoured syscall
  */
-#define errno (*(int *)((unsigned long)&errno - KERNELBASE))
+#define __NR_Linux_syscalls		157
 
-#endif /* __KERNEL__ */
+#ifndef __LANGUAGE_ASSEMBLY__
 
 /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
 #define _syscall0(type,name) \
 type name(void) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile ("syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name)); \
-if (__res >= 0) \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("li\t$2,%2\n\t" \
+		  "syscall" \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name)); \
+if (__err == 0) \
 	return (type) __res; \
-errno = -__res; \
+errno = __res; \
 return -1; \
 }
 
+/*
+ * DANGER: This macro isn't usable for the pipe(2) call
+ * which has a unusual return convention.
+ */
 #define _syscall1(type,name,atype,a) \
 type name(atype a) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile ("move\t$4,%2\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+		  "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)) \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)) \
                   : "$4"); \
-if (__res >= 0) \
+if (__err == 0) \
 	return (type) __res; \
-errno = -__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -45,16 +1193,18 @@
 type name(atype a,btype b) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile ("move\t$4,%2\n\t" \
-                  "move\t$5,%3\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+		  "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)), \
-                                      "r" ((long)(b))); \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
+                                      "r" ((long)(b)) \
                   : "$4","$5"); \
-if (__res >= 0) \
+if (__err == 0) \
 	return (type) __res; \
-errno = -__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -62,18 +1212,20 @@
 type name (atype a, btype b, ctype c) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile ("move\t$4,%2\n\t" \
-                  "move\t$5,%3\n\t" \
-                  "move\t$6,%4\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+		  "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)), \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)) \
                   : "$4","$5","$6"); \
-if (__res>=0) \
+if (__err == 0) \
 	return (type) __res; \
-errno=-__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -81,21 +1233,22 @@
 type name (atype a, btype b, ctype c, dtype d) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile (".set\tnoat\n\t" \
-                  "move\t$4,%2\n\t" \
-                  "move\t$5,%3\n\t" \
-                  "move\t$6,%4\n\t" \
-                  "move\t$7,%5\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+                  "move\t$7,%6\n\t" \
+		  "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)), \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)) \
-                  : "$4","$5","$6","$7"); \
-if (__res>=0) \
+                  : "$4","$5","$6"); \
+if (__err == 0) \
 	return (type) __res; \
-errno=-__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -103,24 +1256,105 @@
 type name (atype a,btype b,ctype c,dtype d,etype e) \
 { \
 register long __res __asm__ ("$2"); \
-__asm__ volatile (".set\tnoat\n\t" \
-                  "move\t$4,%2\n\t" \
-                  "move\t$5,%3\n\t" \
-                  "move\t$6,%4\n\t" \
-                  "move\t$7,%5\n\t" \
-                  "move\t$3,%6\n\t" \
+register long __err __asm__ ("$7"); \
+__asm__ volatile ("move\t$4,%3\n\t" \
+                  "move\t$5,%4\n\t" \
+                  "move\t$6,%5\n\t" \
+                  "move\t$7,%6\n\t" \
+                  "move\t$3,%7\n\t" \
+		  "li\t$2,%2\n\t" \
                   "syscall" \
-                  : "=r" (__res) \
-                  : "0" (__NR_##name),"r" ((long)(a)), \
+                  : "=r" (__res), "=r" (__err) \
+                  : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)), \
                                       "r" ((long)(e)) \
-                  : "$3","$4","$5","$6","$7"); \
-if (__res>=0) \
+                  : "$3","$4","$5","$6"); \
+if (__err == 0) \
 	return (type) __res; \
-errno=-__res; \
+errno = __res; \
 return -1; \
 }
+
+#ifdef __KERNEL_SYSCALLS__
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+#define __NR__exit __NR_exit
+static inline _syscall0(int,idle)
+static inline _syscall0(int,fork)
+static inline _syscall2(int,clone,unsigned long,flags,char *,esp)
+static inline _syscall0(int,pause)
+static inline _syscall0(int,setup)
+static inline _syscall0(int,sync)
+static inline _syscall0(pid_t,setsid)
+static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static inline _syscall1(int,dup,int,fd)
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+static inline _syscall1(int,close,int,fd)
+static inline _syscall1(int,_exit,int,exitcode)
+static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+
+static inline pid_t wait(int * wait_stat)
+{
+	return waitpid(-1,wait_stat,0);
+}
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process(ie the swapper or direct descendants
+ * who haven't done an "execve()") should use this: it will work within
+ * a system call from a "real" process, but the process memory space will
+ * not be free'd until both the parent and the child have exited.
+ */
+static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	long retval;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		"move\t$8,$sp\n\t"
+		"move\t$4,%5\n\t"
+		"li\t$2,%1\n\t"
+		"syscall\n\t"
+		"beq\t$8,$sp,1f\n\t"
+		"subu\t$sp,16\n\t"	/* delay slot */
+		"jalr\t%4\n\t"
+		"move\t$4,%3\n\t"	/* delay slot */
+		"move\t$4,$2\n\t"
+		"li\t$2,%2\n\t"
+		"syscall\n"
+		"1:\taddiu\t$sp,16\n\t"
+		"move\t%0,$2\n\t"
+		".set\treorder"
+		:"=r" (retval)
+		:"i" (__NR_clone), "i" (__NR_exit),
+		 "r" (arg), "r" (fn),
+		 "r" (flags | CLONE_VM)
+		 /*
+		  * The called subroutine might have destroyed any of the
+		  * at, result, argument or temporary registers ...
+		  */
+		:"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+		 "$9","$10","$11","$12","$13","$14","$15","$24","$25");
+
+	return retval;
+}
+
+#endif /* !defined (__KERNEL_SYSCALLS__) */
+#endif /* !defined (__LANGUAGE_ASSEMBLY__) */
 
 #endif /* __ASM_MIPS_UNISTD_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/user.h linux/include/asm-mips/user.h
--- v1.3.47/linux/include/asm-mips/user.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/user.h	Wed Dec 13 12:39:47 1995
@@ -0,0 +1,52 @@
+#ifndef __ASM_MIPS_USER_H
+#define __ASM_MIPS_USER_H
+
+#include <linux/ptrace.h>
+
+#include <asm/page.h>
+#include <asm/reg.h>
+
+/*
+ * Core file format: The core file is written in such a way that gdb
+ * can understand it and provide useful information to the user (under
+ * linux we use the `trad-core' bfd, NOT the osf-core).  The file contents
+ * are as follows:
+ *
+ *  upage: 1 page consisting of a user struct that tells gdb
+ *	what is present in the file.  Directly after this is a
+ *	copy of the task_struct, which is currently not used by gdb,
+ *	but it may come in handy at some point.  All of the registers
+ *	are stored as part of the upage.  The upage should always be
+ *	only one page long.
+ *  data: The data segment follows next.  We use current->end_text to
+ *	current->brk to pick up all of the user variables, plus any memory
+ *	that may have been sbrk'ed.  No attempt is made to determine if a
+ *	page is demand-zero or if a page is totally unused, we just cover
+ *	the entire range.  All of the addresses are rounded in such a way
+ *	that an integral number of pages is written.
+ *  stack: We need the stack information in order to get a meaningful
+ *	backtrace.  We need to write the data from usp to
+ *	current->start_stack, so we round each of these in order to be able
+ *	to write an integer number of pages.
+ */
+struct user {
+	unsigned long	regs[EF_SIZE/8+32];	/* integer and fp regs */
+	size_t		u_tsize;		/* text size (pages) */
+	size_t		u_dsize;		/* data size (pages) */
+	size_t		u_ssize;		/* stack size (pages) */
+	unsigned long	start_code;		/* text starting address */
+	unsigned long	start_data;		/* data starting address */
+	unsigned long	start_stack;		/* stack starting address */
+	long int	signal;			/* signal causing core dump */
+	struct regs *	u_ar0;			/* help gdb find registers */
+	unsigned long	magic;			/* identifies a core file */
+	char		u_comm[32];		/* user command name */
+};
+
+#define NBPG			PAGE_SIZE
+#define UPAGES			1
+#define HOST_TEXT_START_ADDR	(u.start_code)
+#define HOST_DATA_START_ADDR	(u.start_data)
+#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
+
+#endif /* __ASM_MIPS_USER_H */
diff -u --recursive --new-file v1.3.47/linux/include/asm-mips/vector.h linux/include/asm-mips/vector.h
--- v1.3.47/linux/include/asm-mips/vector.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-mips/vector.h	Wed Dec 13 12:39:47 1995
@@ -0,0 +1,61 @@
+/*
+ * include/asm-mips/vector.h
+ *
+ * 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) 1995 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_VECTOR_H
+#define __ASM_MIPS_VECTOR_H
+
+/*
+ * This structure defines how to access various features of
+ * different machine types and how to access them.
+ *
+ * FIXME: More things need to be accessed via this vector.
+ */
+struct feature {
+	void (*handle_int)(void);
+	/*
+	 * How to access the floppy controller's ports.
+	 */
+	unsigned char (*fd_inb)(unsigned int port);
+	void (*fd_outb)(unsigned char value, unsigned int port);
+	/*
+	 * How to access the floppy DMA functions.
+	 */
+	void (*fd_enable_dma)(void);
+	void (*fd_disable_dma)(void);
+	int (*fd_request_dma)(void);
+	void (*fd_free_dma)(void);
+	void (*fd_clear_dma_ff)(void);
+	void (*fd_set_dma_mode)(char mode);
+	void (*fd_set_dma_addr)(unsigned int a);
+	void (*fd_set_dma_count)(unsigned int count);
+	int (*fd_get_dma_residue)(void);
+	void (*fd_enable_irq)(void);
+	void (*fd_disable_irq)(void);
+	void (*fd_cacheflush)(unsigned char *addr, unsigned int size);
+	/*
+	 * How to access the RTC register of DS1287
+	 */
+	unsigned char (*rtc_read_data)(void);
+	void (*rtc_write_data)(unsigned char);
+};
+
+/*
+ * Similar to the above this is a structure that describes various
+ * CPU dependend features.
+ *
+ * FIXME: This vector isn't being used yet
+ */
+struct cpu {
+	int dummy;	/* keep GCC from complaining */
+};
+
+extern struct feature *feature;
+extern struct cpu *cpu;
+
+#endif /* __ASM_MIPS_VECTOR_H */
diff -u --recursive --new-file v1.3.47/linux/include/linux/a.out.h linux/include/linux/a.out.h
--- v1.3.47/linux/include/linux/a.out.h	Fri Jun 16 22:02:55 1995
+++ linux/include/linux/a.out.h	Wed Dec 13 12:39:47 1995
@@ -33,6 +33,8 @@
 #endif
   /* skip a bunch so we don't run into any of sun's numbers */
   M_386 = 100,
+  M_MIPS1 = 151,	/* MIPS R3000/R3000 binary */
+  M_MIPS2 = 152,	/* MIPS R6000/R4000 binary */
 };
 
 #if !defined (N_MAGIC)
diff -u --recursive --new-file v1.3.47/linux/include/linux/blk.h linux/include/linux/blk.h
--- v1.3.47/linux/include/linux/blk.h	Mon Dec 11 15:42:05 1995
+++ linux/include/linux/blk.h	Fri Dec 15 12:56:00 1995
@@ -78,11 +78,14 @@
 #endif
 
 extern void set_device_ro(kdev_t dev,int flag);
+void add_blkdev_randomness(int major);
 
 extern int floppy_init(void);
 extern void rd_load(void);
-extern long rd_init(long mem_start, int length);
-extern int ramdisk_size;
+extern int rd_init(void);
+extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;	/* starting block # of image */
 
 #define RO_IOCTLS(dev,where) \
   case BLKROSET: if (!suser()) return -EACCES; \
@@ -102,14 +105,15 @@
 #define DEVICE_ON(device)	/* nothing */
 #define DEVICE_OFF(device)	/* nothing */
 
-#elif (MAJOR_NR == MEM_MAJOR)
+#elif (MAJOR_NR == RAMDISK_MAJOR)
 
 /* ram disk */
 #define DEVICE_NAME "ramdisk"
-#define DEVICE_REQUEST do_rd_request
-#define DEVICE_NR(device) (MINOR(device) & 7)
+#define DEVICE_REQUEST rd_request
+#define DEVICE_NR(device) (MINOR(device))
 #define DEVICE_ON(device) 
 #define DEVICE_OFF(device)
+#define DEVICE_NO_RANDOM
 
 #elif (MAJOR_NR == FLOPPY_MAJOR)
 
@@ -374,6 +378,9 @@
 			return;
 		}
 	}
+#ifndef DEVICE_NO_RANDOM
+	add_blkdev_randomness(MAJOR(req->rq_dev));
+#endif
 #ifdef IDE_DRIVER
 	blk_dev[MAJOR(req->rq_dev)].current_request = req->next;
 	hwgroup->rq = NULL;
diff -u --recursive --new-file v1.3.47/linux/include/linux/busmouse.h linux/include/linux/busmouse.h
--- v1.3.47/linux/include/linux/busmouse.h	Tue Nov 21 13:22:13 1995
+++ linux/include/linux/busmouse.h	Thu Dec 14 08:16:53 1995
@@ -33,11 +33,13 @@
 
 /*--------- LOGITECH BUSMOUSE ITEMS -------------*/
 
+#define	LOGIBM_BASE		0x23c
 #define	MSE_DATA_PORT		0x23c
 #define	MSE_SIGNATURE_PORT	0x23d
 #define	MSE_CONTROL_PORT	0x23e
-#define MSE_INTERRUPT_PORT	0x23e
+#define	MSE_INTERRUPT_PORT	0x23e
 #define	MSE_CONFIG_PORT		0x23f
+#define	LOGIBM_EXTENT		0x4
 
 #define	MSE_ENABLE_INTERRUPTS	0x00
 #define	MSE_DISABLE_INTERRUPTS	0x10
@@ -59,10 +61,12 @@
 
 /*--------- MICROSOFT BUSMOUSE ITEMS -------------*/
 
+#define	MSBM_BASE			0x23d
 #define	MS_MSE_DATA_PORT	        0x23d
 #define	MS_MSE_SIGNATURE_PORT	        0x23e
 #define	MS_MSE_CONTROL_PORT	        0x23c
 #define	MS_MSE_CONFIG_PORT		0x23f
+#define	MSBM_EXTENT			0x3
 
 #define	MS_MSE_ENABLE_INTERRUPTS	0x11
 #define	MS_MSE_DISABLE_INTERRUPTS	0x10
diff -u --recursive --new-file v1.3.47/linux/include/linux/fs.h linux/include/linux/fs.h
--- v1.3.47/linux/include/linux/fs.h	Mon Dec 11 15:42:05 1995
+++ linux/include/linux/fs.h	Fri Dec 15 08:07:26 1995
@@ -15,8 +15,6 @@
 #include <linux/kdev_t.h>
 #include <linux/ioctl.h>
 
-#include <asm/bitops.h>
-
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but I'll fix
  * that later. Anyway, now the file code is no longer dependent
@@ -114,6 +112,9 @@
 #define FIGETBSZ   _IO(0x00,2)	/* get the block size used for bmap */
 
 #ifdef __KERNEL__
+
+#include <asm/bitops.h>
+
 extern void buffer_init(void);
 extern unsigned long inode_init(unsigned long start, unsigned long end);
 extern unsigned long file_table_init(unsigned long start, unsigned long end);
@@ -128,6 +129,7 @@
 #define BH_Req		3	/* 0 if the buffer has been invalidated */
 #define BH_Touched	4	/* 1 if the buffer has been touched (aging) */
 #define BH_Has_aged	5	/* 1 if the buffer has been aged (aging) */
+#define BH_Protected	6	/* 1 if the buffer is protected */
 
 struct buffer_head {
 	char * b_data;			/* pointer to data block (1024 bytes) */
@@ -178,6 +180,11 @@
 static inline int buffer_has_aged(struct buffer_head * bh)
 {
 	return test_bit(BH_Has_aged, &bh->b_state);
+}
+
+static inline int buffer_protected(struct buffer_head * bh)
+{
+	return test_bit(BH_Protected, &bh->b_state);
 }
 
 #include <linux/pipe_fs_i.h>
diff -u --recursive --new-file v1.3.47/linux/include/linux/major.h linux/include/linux/major.h
--- v1.3.47/linux/include/linux/major.h	Mon Dec 11 15:42:05 1995
+++ linux/include/linux/major.h	Thu Dec 14 08:16:52 1995
@@ -55,6 +55,7 @@
 
 #define UNNAMED_MAJOR	0
 #define MEM_MAJOR	1
+#define RAMDISK_MAJOR	1
 #define FLOPPY_MAJOR	2
 #define PTY_MASTER_MAJOR 2
 #define IDE0_MAJOR	3
diff -u --recursive --new-file v1.3.47/linux/include/linux/mount.h linux/include/linux/mount.h
--- v1.3.47/linux/include/linux/mount.h	Mon Dec 11 15:42:05 1995
+++ linux/include/linux/mount.h	Fri Dec 15 07:31:39 1995
@@ -13,7 +13,7 @@
 
 struct vfsmount
 {
-   dev_t mnt_dev;                      /* Device this applies to */
+   kdev_t mnt_dev;                     /* Device this applies to */
    char *mnt_devname;                  /* Name of device e.g. /dev/dsk/hda1 */
    char *mnt_dirname;                  /* Name of directory mounted on */
    unsigned int mnt_flags;             /* Flags of this device */
@@ -25,6 +25,6 @@
    struct vfsmount *mnt_next;          /* pointer to next in linkedlist */
 };
 
-struct vfsmount *lookup_vfsmnt(dev_t dev);
+struct vfsmount *lookup_vfsmnt(kdev_t dev);
 
 #endif /* _LINUX_MOUNT_H */
diff -u --recursive --new-file v1.3.47/linux/include/linux/serial.h linux/include/linux/serial.h
--- v1.3.47/linux/include/linux/serial.h	Fri Oct  6 14:35:16 1995
+++ linux/include/linux/serial.h	Thu Dec 14 08:26:30 1995
@@ -97,6 +97,16 @@
 	int	reserved[32];
 };
 
+/*
+ * Serial input interrupt line counters -- external structure
+ * Four lines can interrupt: CTS, DSR, RI, DCD
+ */
+struct serial_icounter_struct {
+	int cts, dsr, rng, dcd;
+	int reserved[16];
+};
+
+
 #ifdef __KERNEL__
 /*
  * This is our internal structure for each serial port's state.
@@ -110,6 +120,13 @@
 #include <linux/termios.h>
 #include <linux/tqueue.h>
 
+/*
+ * Counters of the input lines (CTS, DSR, RI, CD) interrupts
+ */
+struct async_icount {
+	__u32	cts, dsr, rng, dcd;	
+};
+
 struct async_struct {
 	int			magic;
 	int			baud_base;
@@ -148,6 +165,8 @@
 	struct termios		callout_termios;
 	struct wait_queue	*open_wait;
 	struct wait_queue	*close_wait;
+	struct wait_queue	*delta_msr_wait;
+	struct async_icount	icount;	/* kernel counters for the 4 input interrupts */
 	struct async_struct	*next_port; /* For the linked list */
 	struct async_struct	*prev_port;
 };
diff -u --recursive --new-file v1.3.47/linux/init/main.c linux/init/main.c
--- v1.3.47/linux/init/main.c	Mon Dec 11 15:42:06 1995
+++ linux/init/main.c	Thu Dec 14 08:16:52 1995
@@ -49,7 +49,6 @@
 extern long console_init(long, long);
 extern long kmalloc_init(long,long);
 extern void sock_init(void);
-extern long rd_init(long mem_start, int length);
 extern long pci_init(long, long);
 
 extern void swap_setup(char *str, int *ints);
@@ -102,7 +101,9 @@
 #ifdef CONFIG_SJCD
 extern void sjcd_setup(char *str, int *ints);
 #endif CONFIG_SJCD
-static void ramdisk_setup(char *str, int *ints);
+static void ramdisk_start_setup(char *str, int *ints);
+static void load_ramdisk(char *str, int *ints);
+static void prompt_ramdisk(char *str, int *ints);
 
 #ifdef CONFIG_SYSVIPC
 extern void ipc_init(void);
@@ -121,7 +122,9 @@
 
 int rows, cols;
 
-int ramdisk_size;
+extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;	/* starting block # of image */
 int root_mountflags = MS_RDONLY;
 char *execute_command = 0;
 
@@ -173,7 +176,9 @@
 } bootsetups[] = {
 	{ "reserve=", reserve_setup },
 	{ "profile=", profile_setup },
-	{ "ramdisk=", ramdisk_setup },
+	{ "ramdisk_start=", ramdisk_start_setup },
+	{ "load_ramdisk", load_ramdisk },
+	{ "prompt_ramdisk", prompt_ramdisk },
 	{ "swap=", swap_setup },
 	{ "buff=", buff_setup },
 #ifdef CONFIG_BUGi386
@@ -268,10 +273,20 @@
 	{ 0, 0 }
 };
 
-static void ramdisk_setup(char *str, int *ints)
+static void ramdisk_start_setup(char *str, int *ints)
 {
    if (ints[0] > 0 && ints[1] >= 0)
-      ramdisk_size = ints[1];
+      rd_image_start = ints[1];
+}
+
+static void load_ramdisk(char *str, int *ints)
+{
+	rd_doload = 1;
+}
+
+static void prompt_ramdisk(char *str, int *ints)
+{
+	rd_prompt = 1;
 }
 
 static int checksetup(char *line)
@@ -578,8 +593,6 @@
 	memory_start = inode_init(memory_start,memory_end);
 	memory_start = file_table_init(memory_start,memory_end);
 	memory_start = name_cache_init(memory_start,memory_end);
-	if (ramdisk_size)
-		memory_start += rd_init(memory_start, ramdisk_size*1024);
 	mem_init(memory_start,memory_end);
 	buffer_init();
 	sock_init();
diff -u --recursive --new-file v1.3.47/linux/kernel/exit.c linux/kernel/exit.c
--- v1.3.47/linux/kernel/exit.c	Fri Nov 17 08:42:29 1995
+++ linux/kernel/exit.c	Fri Dec 15 12:48:37 1995
@@ -96,7 +96,7 @@
 			release_thread(p);
 			if (STACK_MAGIC != *(unsigned long *)p->kernel_stack_page)
 				printk(KERN_ALERT "release: %s kernel stack corruption. Aiee\n", p->comm);
-			free_page(p->kernel_stack_page);
+			free_kernel_stack(p->kernel_stack_page);
 			current->cmin_flt += p->min_flt + p->cmin_flt;
 			current->cmaj_flt += p->maj_flt + p->cmaj_flt;
 			current->cnswap += p->nswap + p->cnswap;
@@ -446,7 +446,7 @@
 	/* 
 	 * Check to see if any process groups have become orphaned
 	 * as a result of our exiting, and if they have any stopped
-	 * jobs, send them a SIGUP and then a SIGCONT.  (POSIX 3.2.2.2)
+	 * jobs, send them a SIGHUP and then a SIGCONT.  (POSIX 3.2.2.2)
 	 *
 	 * Case i: Our father is in a different pgrp than we are
 	 * and we were the only connection outside, so our pgrp
diff -u --recursive --new-file v1.3.47/linux/kernel/fork.c linux/kernel/fork.c
--- v1.3.47/linux/kernel/fork.c	Tue Nov 21 13:22:14 1995
+++ linux/kernel/fork.c	Fri Dec 15 12:48:37 1995
@@ -206,7 +206,7 @@
 	p = (struct task_struct *) kmalloc(sizeof(*p), GFP_KERNEL);
 	if (!p)
 		goto bad_fork;
-	new_stack = get_free_page(GFP_KERNEL);
+	new_stack = alloc_kernel_stack();
 	if (!new_stack)
 		goto bad_fork_free_p;
 	error = -EAGAIN;
@@ -285,7 +285,7 @@
 	REMOVE_LINKS(p);
 	nr_tasks--;
 bad_fork_free_stack:
-	free_page(new_stack);
+	free_kernel_stack(new_stack);
 bad_fork_free_p:
 	kfree(p);
 bad_fork:
diff -u --recursive --new-file v1.3.47/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.3.47/linux/kernel/ksyms.c	Wed Dec 13 09:02:47 1995
+++ linux/kernel/ksyms.c	Sun Dec 17 11:17:18 1995
@@ -15,6 +15,7 @@
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/sched.h>
+#include <linux/kernel_stat.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
 #include <linux/ptrace.h>
@@ -342,6 +343,7 @@
 	X(do_gettimeofday),
 	X(loops_per_sec),
 	X(need_resched),
+	X(kstat),
 	X(kill_proc),
 	X(kill_pg),
 	X(kill_sl),
@@ -473,6 +475,7 @@
  	X(scsi_init_malloc),
  	X(scsi_init_free),
  	X(scsi_ioctl),
+	X(scsi_mark_host_bus_reset),
   	X(print_command),
       	X(print_msg),
   	X(print_status),
diff -u --recursive --new-file v1.3.47/linux/lib/inflate.c linux/lib/inflate.c
--- v1.3.47/linux/lib/inflate.c	Thu Jan  1 02:00:00 1970
+++ linux/lib/inflate.c	Thu Dec 14 08:16:52 1995
@@ -0,0 +1,1167 @@
+#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 
+ */
+
+/*
+   Inflate deflated (PKZIP's method 8 compressed) data.  The compression
+   method searches for as much of the current string of bytes (up to a
+   length of 258) in the previous 32K bytes.  If it doesn't find any
+   matches (of at least length 3), it codes the next byte.  Otherwise, it
+   codes the length of the matched string and its distance backwards from
+   the current position.  There is a single Huffman code that codes both
+   single bytes (called "literals") and match lengths.  A second Huffman
+   code codes the distance information, which follows a length code.  Each
+   length or distance code actually represents a base value and a number
+   of "extra" (sometimes zero) bits to get to add to the base value.  At
+   the end of each deflated block is a special end-of-block (EOB) literal/
+   length code.  The decoding process is basically: get a literal/length
+   code; if EOB then done; if a literal, emit the decoded byte; if a
+   length then get the distance and emit the referred-to bytes from the
+   sliding window of previously emitted data.
+
+   There are (currently) three kinds of inflate blocks: stored, fixed, and
+   dynamic.  The compressor deals with some chunk of data at a time, and
+   decides which method to use on a chunk-by-chunk basis.  A chunk might
+   typically be 32K or 64K.  If the chunk is uncompressible, then the
+   "stored" method is used.  In this case, the bytes are simply stored as
+   is, eight bits per byte, with none of the above coding.  The bytes are
+   preceded by a count, since there is no longer an EOB code.
+
+   If the data is compressible, then either the fixed or dynamic methods
+   are used.  In the dynamic method, the compressed data is preceded by
+   an encoding of the literal/length and distance Huffman codes that are
+   to be used to decode this block.  The representation is itself Huffman
+   coded, and so is preceded by a description of that code.  These code
+   descriptions take up a little space, and so for small blocks, there is
+   a predefined set of codes, called the fixed codes.  The fixed method is
+   used if the block codes up smaller that way (usually for quite small
+   chunks), otherwise the dynamic method is used.  In the latter case, the
+   codes are customized to the probabilities in the current block, and so
+   can code it much better than the pre-determined fixed codes.
+ 
+   The Huffman codes themselves are decoded using a mutli-level table
+   lookup, in order to maximize the speed of decoding plus the speed of
+   building the decoding tables.  See the comments below that precede the
+   lbits and dbits tuning parameters.
+ */
+
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarly, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "#Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp #";
+#endif
+
+#ifndef STATIC
+
+#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
+#  include <sys/types.h>
+#  include <stdlib.h>
+#endif
+
+#include "gzip.h"
+#define STATIC
+#endif /* !STATIC */
+	
+#define slide window
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model).
+   Valid extra bits are 0..13.  e == 15 is EOB (end of block), e == 16
+   means that v is a literal, 16 < e < 32 means that v is a pointer to
+   the next table, which codes e - 16 bits, and lastly e == 99 indicates
+   an unused code.  If a code with e == 99 is looked up, this implies an
+   error in the data. */
+struct huft {
+  uch e;                /* number of extra bits or operation */
+  uch b;                /* number of bits in this code or subcode */
+  union {
+    ush n;              /* literal, length base, or distance base */
+    struct huft *t;     /* pointer to next level of table */
+  } v;
+};
+
+
+/* Function prototypes */
+STATIC int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
+                   struct huft **, int *));
+STATIC int huft_free OF((struct huft *));
+STATIC int inflate_codes OF((struct huft *, struct huft *, int, int));
+STATIC int inflate_stored OF((void));
+STATIC int inflate_fixed OF((void));
+STATIC int inflate_dynamic OF((void));
+STATIC int inflate_block OF((int *));
+STATIC int inflate OF((void));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+   stream to find repeated byte strings.  This is implemented here as a
+   circular buffer.  The index is updated simply by incrementing and then
+   and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area.  It is assumed
+   to be usable as if it were declared "uch slide[32768];" or as just
+   "uch *slide;" and then malloc'ed in the latter case.  The definition
+   must be in unzip.h, included above. */
+/* unsigned wp;             current position in slide */
+#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};
+
+
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+   
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed, and are initialized at the beginning of a
+   routine that uses these macros from a global bit buffer and count.
+
+   If we assume that EOB will be the longest code, then we will never
+   ask for bits with NEEDBITS that are beyond the end of the stream.
+   So, NEEDBITS should not read any more bytes than are needed to
+   meet the request.  Then no bytes need to be "returned" to the buffer
+   at the end of the last block.
+
+   However, this assumption is not true for fixed blocks--the EOB code
+   is 7 bits, but the other literal/length codes can be 8 or 9 bits.
+   (The EOB code is shorter than other codes because fixed blocks are
+   generally short.  So, while a block always has an EOB, many other
+   literal/length codes have a significantly lower probability of
+   showing up at all.)  However, by making the first table have a
+   lookup of seven bits, the EOB code will be found in that first
+   lookup, and so will not require that too many bits be pulled from
+   the stream.
+ */
+
+STATIC ulg bb;                         /* bit buffer */
+STATIC unsigned bk;                    /* bits in bit buffer */
+
+STATIC ush mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#define NEXTBYTE()  (uch)get_byte()
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+STATIC int lbits = 9;          /* bits in base literal/length lookup table */
+STATIC 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 */
+
+
+STATIC unsigned hufts;         /* track memory usage */
+
+
+STATIC 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 {
+    Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"), 
+	    n-i, *p));
+    c[*p]++;                    /* assume all entries <= BMAX */
+    p++;                      /* Can't combine with above line (Solaris bug) */
+  } 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 */
+        if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+            (struct huft *)NULL)
+        {
+          if (h)
+            huft_free(u[0]);
+          return 3;             /* not enough memory */
+        }
+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 = (ush)(*p);             /* simple code is just the value */
+	p++;                           /* one compiler does not like *p++ */
+      }
+      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;
+}
+
+
+
+STATIC 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((char*)p);
+    p = q;
+  } 
+  return 0;
+}
+
+
+STATIC 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;
+      Tracevv((stderr, "%c", slide[w-1]));
+      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)
+      Tracevv((stderr,"\\[%d,%d]", w-d, n));
+
+      /* 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++];
+	    Tracevv((stderr, "%c", slide[w-1]));
+          } 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;
+}
+
+
+
+STATIC 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;
+}
+
+
+
+STATIC 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;
+}
+
+
+
+STATIC 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;
+}
+
+
+
+STATIC 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;
+}
+
+
+
+STATIC int inflate()
+/* decompress an inflated entry */
+{
+  int e;                /* last block flag */
+  int r;                /* result code */
+  unsigned h;           /* maximum struct huft's malloc'ed */
+  void *ptr;
+
+  /* initialize window, bit buffer */
+  wp = 0;
+  bk = 0;
+  bb = 0;
+
+
+  /* decompress until the last block */
+  h = 0;
+  do {
+    hufts = 0;
+    gzip_mark(&ptr);
+    if ((r = inflate_block(&e)) != 0) {
+      gzip_release(&ptr);	    
+      return r;
+    }
+    gzip_release(&ptr);
+    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;
+}
+
+/**********************************************************************
+ *
+ * The following are support routines for inflate.c
+ *
+ **********************************************************************/
+
+static ulg crc_32_tab[256];
+static ulg crc = (ulg)0xffffffffL; /* shift register contents */
+#define CRC_VALUE (crc ^ 0xffffffffL)
+
+/*
+ * Code to compute the CRC-32 table. Borrowed from 
+ * gzip-1.0.3/makecrc.c.
+ */
+
+static 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;
+  }
+}
+
+/* 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 */
+
+/*
+ * Do the uncompression!
+ */
+static int gunzip(void)
+{
+    uch flags;
+    unsigned char magic[2]; /* magic header */
+    char method;
+    ulg orig_crc = 0;       /* original crc */
+    ulg orig_len = 0;       /* original uncompressed length */
+    int res;
+
+    magic[0] = (unsigned char)get_byte();
+    magic[1] = (unsigned char)get_byte();
+    method = (unsigned char)get_byte();
+
+    if (magic[0] != 037 ||
+	((magic[1] != 0213) && (magic[1] != 0236))) {
+	    error("bad gzip magic numbers");
+	    return -1;
+    }
+
+    /* We only support method #8, DEFLATED */
+    if (method != 8)  {
+	    error("internal error, invalid method");
+	    return -1;
+    }
+
+    flags  = (uch)get_byte();
+    if ((flags & ENCRYPTED) != 0) {
+	    error("Input is encrypted\n");
+	    return -1;
+    }
+    if ((flags & CONTINUATION) != 0) {
+	    error("Multi part input\n");
+	    return -1;
+    }
+    if ((flags & RESERVED) != 0) {
+	    error("Input has invalid flags\n");
+	    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) {
+	    /* Discard the old name */
+	    while (get_byte() != 0) /* null */ ;
+    } 
+
+    /* Discard file comment if any */
+    if ((flags & COMMENT) != 0) {
+	    while (get_byte() != 0) /* null */ ;
+    }
+
+    /* Decompress */
+    if ((res = inflate())) {
+	    switch (res) {
+	    case 0:
+		    break;
+	    case 1:
+		    error("invalid compressed format (err=1)");
+		    break;
+	    case 2:
+		    error("invalid compressed format (err=2)");
+		    break;
+	    case 3:
+		    error("out of memory");
+		    break;
+	    default:
+		    error("invalid compressed format (other)");
+	    }
+	    return -1;
+    }
+	    
+    /* Get the crc and original length */
+    /* crc32  (see algorithm.doc)
+     * uncompressed input size modulo 2^32
+     */
+    orig_crc = (ulg) get_byte();
+    orig_crc |= (ulg) get_byte() << 8;
+    orig_crc |= (ulg) get_byte() << 16;
+    orig_crc |= (ulg) get_byte() << 24;
+    
+    orig_len = (ulg) get_byte();
+    orig_len |= (ulg) get_byte() << 8;
+    orig_len |= (ulg) get_byte() << 16;
+    orig_len |= (ulg) get_byte() << 24;
+    
+    /* Validate decompression */
+    if (orig_crc != CRC_VALUE) {
+	    error("crc error");
+	    return -1;
+    }
+    if (orig_len != bytes_out) {
+	    error("length error");
+	    return -1;
+    }
+    return 0;
+}
+
+
diff -u --recursive --new-file v1.3.47/linux/mm/filemap.c linux/mm/filemap.c
--- v1.3.47/linux/mm/filemap.c	Wed Dec 13 09:02:47 1995
+++ linux/mm/filemap.c	Fri Dec 15 07:31:39 1995
@@ -142,7 +142,7 @@
 
 	set_pte(page_table, __pte(entry));
 	/* Yuck, perhaps a slightly modified swapout parameter set? */
-	invalidate_page(vma->vm_mm, (offset + vma->vm_start - vma->vm_offset));
+	invalidate_page(vma, (offset + vma->vm_start - vma->vm_offset));
 	error = filemap_write_page(vma, offset, page);
 	if (pte_val(*page_table) == entry)
 		pte_clear(page_table);
@@ -180,14 +180,14 @@
 		if (!pte_dirty(pte))
 			return 0;
 		set_pte(ptep, pte_mkclean(pte));
-		invalidate_page(vma->vm_mm, address);
+		invalidate_page(vma, address);
 		page = pte_page(pte);
 		mem_map[MAP_NR(page)].count++;
 	} else {
 		if (pte_none(pte))
 			return 0;
 		pte_clear(ptep);
-		invalidate_page(vma->vm_mm, address);
+		invalidate_page(vma, address);
 		if (!pte_present(pte)) {
 			swap_free(pte_val(pte));
 			return 0;
diff -u --recursive --new-file v1.3.47/linux/mm/memory.c linux/mm/memory.c
--- v1.3.47/linux/mm/memory.c	Wed Dec 13 09:02:47 1995
+++ linux/mm/memory.c	Fri Dec 15 07:31:39 1995
@@ -59,7 +59,19 @@
 struct mem_list free_area_list[NR_MEM_LISTS];
 unsigned char * free_area_map[NR_MEM_LISTS];
 
-#define copy_page(from,to) memcpy((void *) to, (void *) from, PAGE_SIZE)
+/*
+ * We special-case the C-O-W ZERO_PAGE, because it's such
+ * a common occurrence (no need to read the page to know
+ * that it's zero - better for the cache and memory subsystem).
+ */
+static inline void copy_page(unsigned long from, unsigned long to)
+{
+	if (from == ZERO_PAGE) {
+		memset((void *) to, 0, PAGE_SIZE);
+		return;
+	}
+	memcpy((void *) to, (void *) from, PAGE_SIZE);
+}
 
 #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
 
@@ -549,8 +561,8 @@
 	}
 	if (!pte_none(*pte)) {
 		printk("put_dirty_page: page already exists\n");
-		pte_clear(pte);
-		invalidate_page(tsk->mm, address);
+		free_page(page);
+		return 0;
 	}
 	set_pte(pte, pte_mkwrite(pte_mkdirty(mk_pte(page, PAGE_COPY))));
 /* no need for invalidate */
@@ -613,17 +625,17 @@
 			copy_page(old_page,new_page);
 			set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
 			free_page(old_page);
-			invalidate_page(vma->vm_mm, address);
+			invalidate_page(vma, address);
 			return;
 		}
 		set_pte(page_table, BAD_PAGE);
 		free_page(old_page);
 		oom(tsk);
-		invalidate_page(vma->vm_mm, address);
+		invalidate_page(vma, address);
 		return;
 	}
 	set_pte(page_table, pte_mkdirty(pte_mkwrite(pte)));
-	invalidate_page(vma->vm_mm, address);
+	invalidate_page(vma, address);
 	if (new_page)
 		free_page(new_page);
 	return;
@@ -845,7 +857,7 @@
 		return 1;
 /* ok, need to mark it read-only, so invalidate any possible old TB entry */
 	set_pte(from_table, pte_wrprotect(from));
-	invalidate_page(from_area->vm_mm, from_address);
+	invalidate_page(from_area, from_address);
 	return 1;
 }
 
diff -u --recursive --new-file v1.3.47/linux/mm/swap.c linux/mm/swap.c
--- v1.3.47/linux/mm/swap.c	Wed Dec 13 09:02:47 1995
+++ linux/mm/swap.c	Fri Dec 15 07:31:39 1995
@@ -457,7 +457,7 @@
 				return 0;
 			vma->vm_mm->rss--;
 			set_pte(page_table, __pte(entry));
-			invalidate_page(vma->vm_mm, address);
+			invalidate_page(vma, address);
 			tsk->nswap++;
 			write_swap_page(entry, (char *) page);
 		}
@@ -472,13 +472,13 @@
 		}
 		vma->vm_mm->rss--;
 		set_pte(page_table, __pte(entry));
-		invalidate_page(vma->vm_mm, address);
+		invalidate_page(vma, address);
 		free_page(page);
 		return 1;
 	} 
 	vma->vm_mm->rss--;
 	pte_clear(page_table);
-	invalidate_page(vma->vm_mm, address);
+	invalidate_page(vma, address);
 	entry = mem_map[MAP_NR(page)].count;
 	free_page(page);
 	return entry;
diff -u --recursive --new-file v1.3.47/linux/net/netlink.c linux/net/netlink.c
--- v1.3.47/linux/net/netlink.c	Mon Dec 11 15:42:11 1995
+++ linux/net/netlink.c	Thu Dec 14 08:07:07 1995
@@ -193,7 +193,7 @@
 int netlink_post(int unit, struct sk_buff *skb)
 {
 	unsigned long flags;
-	int ret=0;
+	int ret=-EUNATCH;
 	if(open_map&(1<<unit))
 	{
 		save_flags(flags);
