diff -u --recursive --new-file v1.3.52/linux/CREDITS linux/CREDITS
--- v1.3.52/linux/CREDITS	Wed Dec 27 09:12:11 1995
+++ linux/CREDITS	Tue Jan  2 07:24:04 1996
@@ -372,6 +372,14 @@
 S: Atlanta, Georgia 30332
 S: USA
 
+N: Kai Harrekilde-Petersen
+E: khp@pip.dknet.dk
+W: http://www.pip.dknet.dk/~pip93
+D: ftape-HOWTO, i82078 fdc detection code, various ftape related stuff.
+S: Studsgade 40, 2tv
+S: DK-8000 Aarhus C
+S: Denmark
+
 N: Andrew Haylett
 E: ajh@primag.co.uk
 D: Selection mechanism
diff -u --recursive --new-file v1.3.52/linux/Documentation/CodingStyle linux/Documentation/CodingStyle
--- v1.3.52/linux/Documentation/CodingStyle	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/CodingStyle	Sun Dec 31 14:32:45 1995
@@ -0,0 +1,193 @@
+
+		Linux kernel coding style 
+
+This is a short document describing the preferred coding style for the
+linux kernel.  Coding style is very personal, and I won't _force_ my
+views on anybody, but this is what goes for anything that I have to be
+able to maintain, and I'd prefer it for most other things too.  Please
+at least consider the points made here. 
+
+First off, I'd suggest printing out a copy of the GNU coding standards,
+and NOT read it.  Burn them, it's a great symbolic gesture. 
+
+Anyway, here goes:
+
+
+	 	Chapter 1: Indentation
+
+Tabs are 8 characters, and thus indentations are also 8 characters. 
+There are heretic movements that try to make indentations 4 (or even 2!)
+characters deep, and that is akin to trying to define the value of PI to
+be 3. 
+
+Rationale: The whole idea behind indentation is to clearly define where
+a block of control starts and ends.  Especially when you've been looking
+at your screen for 20 straight hours, you'll find it a lot easier to see
+how the indentation works if you have large indentations. 
+
+Now, some people will claim that having 8-character indentations makes
+the code move too far to the right, and makes it hard to read on a
+80-character terminal screen.  The answer to that is that if you need
+more than 3 levels of indentation, you're screwed anyway, and should fix
+your program. 
+
+In short, 8-char indents make things easier to read, and have the added
+benefit of warning you when you're nesting your functions too deep. 
+Heed that warning. 
+
+
+		Chapter 2: Placing Braces
+
+The other issue that always comes up in C styling is the placement of
+braces.  Unlike the indent size, there are few technical reasons to
+choose one placement strategy over the other, but the preferred way, as
+shown to us by the prophets Kernighan and Ritchie, is to put the opening
+brace last on the line, and put the closing brace first, thusly:
+
+	if (x is true) {
+		we do y
+	}
+
+However, there is one special case, namely functions: they have the
+opening brace at the beginning of the next line, thus:
+
+	int function(int x)
+	{
+		body of function
+	}
+
+Heretic people all over the world have claimed that this inconsistency
+is ...  well ...  inconsistent, but all right-thinking people know that
+(a) K&R are _right_ and (b) K&R are right.  Besides, functions are
+special anyway (you can't nest them in C). 
+
+Note that the closing brace is empty on a line of its own, _except_ in
+the cases where it is followed by a continuation of the same statement,
+ie a "while" in a do-statement or an "else" in an if-statement, like
+this:
+
+	do {
+		body of do-loop
+	} while (condition);
+
+and
+
+	if (x == y) {
+		..
+	} else if (x > y) {
+		...
+	} else {
+		....
+	}
+			
+Rationale: K&R. 
+
+Also, note that this brace-placement also minimizes the number of empty
+(or almost empty) lines, without any loss of readability.  Thus, as the
+supply of new-lines on your screen is not a renewable resource (think
+25-line terminal screens here), you have more empty lines to put
+comments on. 
+
+
+		Chapter 3: Naming
+
+C is a Spartan language, and so should your naming be.  Unlike Modula-2
+and Pascal programmers, C programmers do not use cute names like
+ThisVariableIsATemporaryCounter.  A C programmer would call that
+variable "tmp", which is much easier to write, and not the least more
+difficult to understand. 
+
+HOWEVER, while mixed-case names are frowned upon, descriptive names for
+global variables are a must.  To call a global function "foo" is a
+shooting offense. 
+
+GLOBAL variables (to be used only if you _really_ need them) need to
+have descriptive names, as do global functions.  If you have a function
+that counts the number of active users, you should call that
+"count_active_users()" or similar, you should _not_ call it "cntusr()". 
+
+Encoding the type of a function into the name (so-called Hungarian
+notation) is brain damaged - the compiler knows the types anyway and can
+check those, and it only confuses the programmer.  No wonder MicroSoft
+makes buggy programs. 
+
+LOCAL variable names should be short, and to the point.  If you have
+some random integer loop counter, it should probably be called "i". 
+Calling it "loop_counter" is non-productive, if there is no chance of it
+being mis-understood.  Similarly, "tmp" can be just about any type of
+variable that is used to hold a temporary value. 
+
+If you are afraid to mix up your local variable names, you have another
+problem, which is called the function-growth-hormone-imbalance syndrome. 
+See next chapter. 
+
+		
+		Chapter 4: Functions
+
+Functions should be short and sweet, and do just one thing.  They should
+fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
+as we all know), and do one thing and do that well. 
+
+The maximum length of a function is inversely proportional to the
+complexity and indentation level of that function.  So, if you have a
+conceptually simple function that is just one long (but simple)
+case-statement, where you have to do lots of small things for a lot of
+different cases, it's ok to have a longer function. 
+
+However, if you have a complex function, and you suspect that a
+less-than-gifted first-year high-school student might not even
+understand what the function is all about, you should adhere to the
+maximum limits all the more closely.  Use helper functions with
+descriptive names (you can ask the compiler to in-line them if you think
+it's performance-critical, and it will probably do a better job of it
+that you would have done). 
+
+Another measure of the function is the number of local variables.  They
+shouldn't exceed 5-10, or you're doing something wrong.  Re-think the
+function, and split it into smaller pieces.  A human brain can
+generally easily keep track of about 7 different things, anything more
+and it gets confused.  You know you're brilliant, but maybe you'd like
+to understand what you did 2 weeks from now. 
+
+
+		Chapter 5: Commenting
+
+Comments are good, but there is also a danger of over-commenting.  NEVER
+try to explain HOW your code works in a comment: it's much better to
+write the code so that the _working_ is obvious, and it's a waste of
+time to explain badly written code. 
+
+Generally, you want your comments to tell WHAT your code does, not HOW. 
+Also, try to avoid putting comments inside a function body: if the
+function is so complex that you need to separately comment parts of it,
+you should probably go back to chapter 4 for a while.  You can make
+small comments to note or warn about something particularly clever (or
+ugly), but try to avoid excess.  Instead, put the comments at the head
+of the function, telling people what it does, and possibly WHY it does
+it. 
+
+
+		Chapter 6: You've made a mess of it
+
+That's ok, we all do.  You've probably been told by your long-time unix
+user helper that "GNU emacs" automatically formats the C sources for
+you, and you've noticed that yes, it does do that, but the defaults it
+uses are less than desirable (in fact, they are worse than random
+typing - a infinite number of monkeys typing into GNU emacs would never
+make a good program). 
+
+So, you can either get rid of GNU emacs, or change it to use saner
+values.  I did the first, so don't ask me how to do the latter.  But
+even if you fail in getting emacs to do sane formatting, not everything
+is lost: use "indent". 
+
+Now, again, GNU indent has the same brain dead settings that GNU emacs
+has, which is why you need to give it a few command line options. 
+However, that's not too bad, because even the makers of GNU indent
+recognize the authority of K&R (the GNU people aren't evil, they are
+just severely misguided in this matter), so you just give indent the
+options "-kr -i8" (stands for "K&R, 8 character indents"). 
+
+"indent" has a lot of options, and especially when it comes to comment
+re-formatting you may want to take a look at the manual page.  But
+remember: "indent" is not a fix for bad programming. 
diff -u --recursive --new-file v1.3.52/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v1.3.52/linux/Documentation/Configure.help	Sat Dec 30 15:50:52 1995
+++ linux/Documentation/Configure.help	Tue Jan  2 14:18:42 1996
@@ -317,6 +317,14 @@
   not sure, say N; This option will make the kernel use some
   instructions that are only available on 486+ machines.
 
+Use Pentium optimizations
+CONFIG_M586 
+  If you have a 586 or better, as opposed to a 486, or if you have a
+  486 and are very short on memory, say Y here.
+  Things will be slightly faster for a 586, and your kernel will be
+  smaller.  A kernel with this option enabled will still run on a 486,
+  although slightly slower.
+
 Enable loadable module support
 CONFIG_MODULES
   Kernel modules are small pieces of compiled code which can be 
@@ -568,11 +576,12 @@
 The IPX protocol
 CONFIG_IPX
   This is support for the Novell networking protocol, IPX. You need it
-  if you want to access Novell Netware servers from within the Linux
-  DOS emulator dosemu (read the DOSEMU-HOWTO, available via ftp (user:
-  anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO). To
-  turn your Linux box into a fully featured Netware file server and
-  IPX router, say Y here and fetch lwared from
+  if you want to access Novell Netware servers by using ncpfs or from
+  within the Linux DOS emulator dosemu (read the DOSEMU-HOWTO,
+  available via ftp (user: anonymous) in
+  sunsite.unc.edu:/pub/Linux/docs/HOWTO). To turn your Linux box into
+  a fully featured Netware file server and IPX router, say Y here and
+  fetch lwared from
   sunsite.unc.edu:/pub/Linux/system/Networking/daemons/. General
   information about how to connect Linux, Windows machines and Macs is
   on the WWW at http://eats.com/linux_mac_win.html (to browse the WWW,
@@ -2003,7 +2012,7 @@
   Documentation/modules.txt. If you haven't heard about all of this
   before, it's safe to say N.
 
-SMB filesystem (to mount WfW shares etc..) support
+SMB filesystem support (to mount WfW shares etc..)
 CONFIG_SMB_FS
   SMB (Server Message Buffer) is the protocol Windows for Workgroups
   (WfW), Windows NT and Lan Manager use to talk to each other over an
@@ -2022,6 +2031,18 @@
   as a module ( = code which can be inserted in and removed from the
   running kernel whenever you want), say M here and read
   Documentation/modules.txt. Most people say N, however.
+
+NCP filesystem support (to mount NetWare volumes)
+CONFIG_NCP_FS
+  NCP (NetWare Core Protocol) is a protocol that runs over IPX and is
+  used by NetWare clients to talk to file servers. Enabling this
+  allows you to mount NetWare file server volumes and access them just
+  like any other directory. To actually mount the filesystem, you need
+  a special mount program, available on sunsite.unc.edu via anonymous
+  ftp in /pub/Linux/system/Filesystem/ncpfs-xx.tgz. If you want to
+  compile this as a module ( = code which can be inserted in and
+  removed from the running kernel whenever you want), say M here and
+  read Documentation/modules.txt.
 
 Cyclades async mux support
 CONFIG_CYCLADES
diff -u --recursive --new-file v1.3.52/linux/Makefile linux/Makefile
--- v1.3.52/linux/Makefile	Sat Dec 30 15:50:52 1995
+++ linux/Makefile	Sun Dec 31 11:11:59 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 52
+SUBLEVEL = 53
 
 ARCH = i386
 
@@ -266,6 +266,7 @@
 	if [ -f IPV4_MODULES  ]; then inst_mod IPV4_MODULES  ipv4;  fi; \
 	if [ -f SCSI_MODULES  ]; then inst_mod SCSI_MODULES  scsi;  fi; \
 	if [ -f FS_MODULES    ]; then inst_mod FS_MODULES    fs;    fi; \
+	if [ -f CDROM_MODULES ]; then inst_mod CDROM_MODULES cdrom; fi; \
 	\
 	ls *.o > .allmods; \
 	echo $$MODULES | tr ' ' '\n' | sort | comm -23 .allmods - > .misc; \
diff -u --recursive --new-file v1.3.52/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v1.3.52/linux/arch/alpha/defconfig	Sat Dec 30 15:50:52 1995
+++ linux/arch/alpha/defconfig	Tue Jan  2 08:14:43 1996
@@ -22,6 +22,7 @@
 # CONFIG_ALPHA_SRM is not set
 CONFIG_PCI=y
 CONFIG_ALPHA_APECS=y
+CONFIG_ALPHA_NEED_ROUNDING_EMULATION=y
 # CONFIG_SERIAL_ECHO is not set
 # CONFIG_TGA_CONSOLE is not set
 CONFIG_PCI_OPTIMIZE=y
@@ -33,6 +34,7 @@
 # block devices
 #
 CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_RAM is not set
 CONFIG_ST506=y
 
 #
@@ -142,6 +144,7 @@
 #
 # Filesystems
 #
+# CONFIG_QUOTA is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_EXT_FS is not set
 CONFIG_EXT2_FS=y
@@ -168,6 +171,7 @@
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_APM is not set
+# CONFIG_WATCHDOG is not set
 
 #
 # Sound
diff -u --recursive --new-file v1.3.52/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v1.3.52/linux/arch/i386/Makefile	Fri Nov 17 08:42:24 1995
+++ linux/arch/i386/Makefile	Tue Jan  2 15:09:42 1996
@@ -46,14 +46,16 @@
 endif
 CFLAGS := $(CFLAGS) -pipe
 
+ifdef CONFIG_M386
+CFLAGS := $(CFLAGS) -m386
+endif
+
 ifdef CONFIG_M486
 CFLAGS := $(CFLAGS) -m486
-else
-ifdef CONFIG_M586
-CFLAGS := $(CFLAGS) -mpentium
-else
-CFLAGS := $(CFLAGS) -m386
 endif
+
+ifdef CONFIG_M586
+CFLAGS := $(CFLAGS) -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2
 endif
 
 ifdef SMP
diff -u --recursive --new-file v1.3.52/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.3.52/linux/arch/i386/config.in	Sat Dec 30 15:50:53 1995
+++ linux/arch/i386/config.in	Tue Jan  2 15:34:09 1996
@@ -27,10 +27,10 @@
 if [ "$CONFIG_BINFMT_ELF" = "y" ]; then
   bool 'Compile kernel as ELF - if your GCC is ELF-GCC' CONFIG_KERNEL_ELF
 fi
-#bool 'Use Pentium-specific optimizations (does NOT work on i386)' CONFIG_M586
-#if [ "$CONFIG_M586" = "n" ]; then
-bool 'Use 486-specific optimizations (does NOT work on i386)' CONFIG_M486
-#fi
+choice 'Processor type' \
+	"386		CONFIG_M386	\
+	 486		CONFIG_M486	\
+	 Pentium	CONFIG_M586" Pentium
 
 source drivers/block/Config.in
 
diff -u --recursive --new-file v1.3.52/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v1.3.52/linux/arch/i386/defconfig	Sat Dec 30 15:50:53 1995
+++ linux/arch/i386/defconfig	Tue Jan  2 15:39:15 1996
@@ -19,7 +19,9 @@
 CONFIG_SYSVIPC=y
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
-CONFIG_M486=y
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+CONFIG_M586=y
 
 #
 # block devices
@@ -109,10 +111,10 @@
 CONFIG_PROC_FS=y
 CONFIG_NFS_FS=y
 # CONFIG_ROOT_NFS is not set
+# CONFIG_SMB_FS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_HPFS_FS is not set
 # CONFIG_SYSV_FS is not set
-# CONFIG_SMB_FS is not set
 
 #
 # character devices
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v1.3.52/linux/arch/ppc/Makefile	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/Makefile	Sat Dec 30 15:48:22 1995
@@ -12,16 +12,16 @@
 #
 # Copyright (C) 1994 by Linus Torvalds
 # Changes for PPC by Gary Thomas
+# Modified by Cort Dougan
 #
-
 # PowerPC (cross) tools
-AS		= as.ppc
-ASFLAGS		=
-LD		= ld.ppc
+AS		= /usr/local/bin/as.ppc
+ASFLAGS		= 
+LD		= /u/cort/ppc-gcc/bin/ld.ppc
 #LINKFLAGS	= -T arch/ppc/ld.script -Ttext 0x90000000 -Map vmlinux.map
 LINKFLAGS	= -T arch/ppc/ld.script -Ttext 0x90000000 
 HOSTCC		= gcc
-CC		= gcc.ppc
+CC		= /usr/local/bin/gcc.ppc 
 CFLAGS		= -D__KERNEL__ -I$(TOPDIR)/include \
 		-Wstrict-prototypes \
 		-fomit-frame-pointer \
@@ -30,10 +30,10 @@
 		-O2 -pipe
 #-Wall
 CPP		= $(CC) -E $(CFLAGS)
-AR		= ar.ppc
-RANLIB		= ranlib.ppc
-STRIP		= strip.ppc
-NM		= nm.ppc
+AR		= /u/cort/ppc-gcc/bin/ar.ppc
+RANLIB		= /u/cort/ppc-gcc/bin/ranlib.ppc
+STRIP		= /u/cort/ppc-gcc/bin/strip.ppc
+NM		= /u/cort/ppc-gcc/bin/nm.ppc
 
 #
 # Set these to indicate how to link it..
@@ -99,6 +99,8 @@
 
 archclean:
 #	@$(MAKEBOOT) clean
+	/bin/rm -f arch/ppc/kernel/*.o arch/ppc/kernel/mk_defs arch/ppc/kernel/ppc_defs.h mm/*.o
+	/bin/rm -f arch/ppc/kernel/*~ arch/ppc/kernel/*~      
 
 archdep:
 #	@$(MAKEBOOT) dep
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v1.3.52/linux/arch/ppc/boot/Makefile	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/boot/Makefile	Sat Dec 30 15:48:22 1995
@@ -24,8 +24,11 @@
 
 all:	linux.boot
 
-linux.boot: $(TOPDIR)/vmlinux
-	mkboot $(TOPDIR)/vmlinux $@ 0
+linux.boot: $(TOPDIR)/vmlinux mkboot
+	mkboot $(TOPDIR)/vmlinux /u/cort/bootpd/vmlinux
+
+mkboot : cortstrip.c
+	$(HOSTCC) -o mkboot cortstrip.c
 
 clean:
 	rm -f linux.boot 
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/boot/cortstrip.c linux/arch/ppc/boot/cortstrip.c
--- v1.3.52/linux/arch/ppc/boot/cortstrip.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/ppc/boot/cortstrip.c	Sat Dec 30 15:48:22 1995
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/* amount to skip */
+#define PLACE 65536
+
+/* size of read buffer */
+#define SIZE 0x200000
+
+/* crude program to strip the elf header to make a bootable
+   image via tftp
+ */
+
+
+int main(int argc, char **argv )
+{
+  int fd, fdo;
+  unsigned char data[SIZE];
+  int i, n, skip;
+
+  if ( argc != 3 )
+  {
+    fprintf(stderr,"%s infile outfile\n", argv[0]);
+    exit(-1);
+  }
+
+
+  fd = open(argv[1], O_RDONLY);
+  if ( fd == -1 )
+  {
+    fprintf(stderr,"Couldn't open %s\n", argv[1]);
+    perror("open()");
+    exit(-1);
+  }
+  
+  fdo = open(argv[2], O_WRONLY|O_CREAT);
+  if ( fdo == -1 )
+  {
+    fprintf(stderr,"Couldn't open %s\n", argv[2]);
+    perror("open()");
+    exit(-1);
+  }
+
+#if 0
+  skip = atoi(argv[3]);
+#else
+  skip = PLACE;
+#endif
+  i = lseek(fd, skip, SEEK_SET);
+  printf("lseek'd %d bytes\n", i);
+  if ( i == -1 )
+  {
+      perror("lseek()");
+  }
+
+  while ( (n = read(fd, data, SIZE)) > 0 )
+  {
+    printf("Read %d bytes\n", n);
+    i = write(fdo, data, n);
+    printf("Wrote %d bytes\n", i);    
+  }
+
+
+  close(fdo);
+  close(fd);
+  return(0);
+}
+
+
Binary files v1.3.52/linux/arch/ppc/boot/mkboot and linux/arch/ppc/boot/mkboot differ
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v1.3.52/linux/arch/ppc/kernel/Makefile	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/kernel/Makefile	Sat Dec 30 15:48:22 1995
@@ -6,6 +6,10 @@
 # unless it's something special (ie not a .c file).
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
+#
+#
+# Modified by Cort Dougan
+#
 
 .c.s:
 	$(CC) $(CFLAGS) -S $<
@@ -26,7 +30,7 @@
 OBJS  = misc.o setup.o port_io.o irq.o pci.o traps.o stubs.o process.o \
 	signal.o raw_printf.o ramdisk.o 
 
-all: head.o kernel.o cortstrip mkboot
+all: head.o kernel.o
 
 head.o: head.s
 head.s: head.S $(TOPDIR)/include/linux/tasks.h ppc_defs.h
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v1.3.52/linux/arch/ppc/kernel/misc.S	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/kernel/misc.S	Sat Dec 30 15:48:22 1995
@@ -560,7 +560,8 @@
 	.long sys_uselib
 	.long sys_swapon
 	.long sys_reboot
-	.long sys_readdir
+/*	.long sys_readdir*/
+	.long old_readdir
 	.long sys_mmap			/* 90 */
 	.long sys_munmap
 	.long sys_truncate
@@ -623,4 +624,4 @@
 	.globl	floppy_track_buffer
 floppy_track_buffer:
 	.space	512*2*38		/* Space for one entire cylinder! */	
-#endif
+#endif
\ No newline at end of file
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v1.3.52/linux/arch/ppc/kernel/pci.c	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/kernel/pci.c	Sat Dec 30 15:48:22 1995
@@ -90,7 +90,7 @@
 #endif	
 	if ((bus != 0) || (dev < 11) || (dev > 16))
 	{
-		*val = 0xFFFFFFFF;
+		*val =(unsigned short) 0xFFFFFFFF;
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	} else
 	{
@@ -119,7 +119,7 @@
 #endif		
 	if ((bus != 0) || (dev < 11) || (dev > 16))
 	{
-		*val = 0xFFFFFFFF;
+		*val = (unsigned char) 0xFFFFFFFF;
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	} else
 	{
@@ -207,7 +207,7 @@
 		     unsigned short index, unsigned char *bus,
 		     unsigned char *dev)
 {
-	unsigned long w, desired = (device_id << 16) | vendor;
+	unsigned int w, desired = (device_id << 16) | vendor;
 	int devnr;
 
 	if (vendor == 0xffff) {
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/ppc_asm.tmpl linux/arch/ppc/kernel/ppc_asm.tmpl
--- v1.3.52/linux/arch/ppc/kernel/ppc_asm.tmpl	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/kernel/ppc_asm.tmpl	Sat Dec 30 15:48:22 1995
@@ -165,4 +165,7 @@
 /* Missing instructions */
 #define bdne	bc 0,2,
 
-#include "ppc_machine.h"
+#include <asm/ppc_machine.h>
+
+
+
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v1.3.52/linux/arch/ppc/kernel/process.c	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/kernel/process.c	Sat Dec 30 15:48:22 1995
@@ -1,9 +1,10 @@
-/* * Last edited: Nov  8 12:32 1995 (cort) */
+/* * Last edited: Dec 14 17:32 1995 (cort) */
 /*
  *  linux/arch/ppc/kernel/process.c
  *
  *  Copyright (C) 1995  Linus Torvalds
  *  Adapted for PowerPC by Gary Thomas
+ *  Modified by Cort Dougan
  */
 
 /*
@@ -27,7 +28,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <asm/processor.h>
+#include <asm/ppc_machine.h>
 
 int dump_fpu (struct user_i387_struct* fpu)
 {
@@ -122,10 +123,10 @@
 	childregs = ((struct pt_regs *) (p->kernel_stack_page + 2*PAGE_SIZE)) - 2;
 	*childregs = *regs;	/* STRUCT COPY */
 	childregs->gpr[3] = 0;  /* Result from fork() */
-	p->tss.ksp = childregs;
+	p->tss.ksp = (unsigned long)childregs;
 	if (usp >= (unsigned long)regs)
 	{ /* Stack is in kernel space - must adjust */
-		childregs->gpr[1] = childregs+1;
+		childregs->gpr[1] = (long)(childregs+1);
 	} else
 	{ /* Provided stack is in user space */
 		childregs->gpr[1] = usp;
@@ -166,8 +167,18 @@
 
 asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs)
 {
-printk("process.c: sys_fork() called\n");
-	return do_fork( CLONE_VM|SIGCHLD, regs->gpr[1], regs);
+  int i;
+  char *a;
+#if 0
+  for ( i = 0 ; i <= 0x400 ; i++)
+  {
+    printk("going to do kmalloc(%d)\n",i);
+    a = kmalloc(i,GFP_KERNEL);
+    a = kmalloc(i,GFP_KERNEL);
+    printk("a = %x\n",a);
+  }
+#endif
+  return do_fork( SIGCHLD, regs->gpr[1], regs);
 }
 
 asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
@@ -176,7 +187,6 @@
 {
 	int error;
 	char * filename;
-/*	printk("process.c: sys_execve(a0 = %s, a1 = %x, a2 = %x)\n",a0,a1,a2);*/
 
 #if 1
 	/* paranoia check.  I really don't trust head.S  -- Cort */
@@ -189,12 +199,7 @@
 	if (error)
 	  return error;
 	error = do_execve(filename, (char **) a1, (char **) a2, regs);
-#if 0
-	if (error)
-	{
-	  printk("EXECVE - file = '%s', error = %d\n", filename, error);
-	}
-#endif
+
 	putname(filename);
 	return error;
 }
@@ -210,9 +215,9 @@
     usp = regs->gpr[1];
   
 
-  i = do_fork(CLONE_VM/*clone_flags*/, /*usp*/regs->gpr[1], regs);
-/*  printk("sys_clone going to return %d\n", i);*/
-  return i;
+  /* I hard coded in all the arguments to clone since clone() is inlined
+     and has trouble with its args  with our gcc -- Cort*/
+  return do_fork(/*clone_flags*/CLONE_VM, /*usp*/ regs->gpr[1], regs);
 }
 
 
@@ -226,7 +231,7 @@
 	while (*sp)
 	{
 		printk("%08X ", sp[2]);
-		sp = *sp;
+		sp = (unsigned long *)*sp;
 		if (++cnt == 8)
 		{
 			printk("\n");
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/raw_printf.c linux/arch/ppc/kernel/raw_printf.c
--- v1.3.52/linux/arch/ppc/kernel/raw_printf.c	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/kernel/raw_printf.c	Sat Dec 30 15:48:22 1995
@@ -3,9 +3,65 @@
 #include <stdarg.h>
 
 extern void cnputc(char c);
-
+char cngetc(void);
+int cntstc(void);
+void _cnpause(void);
+void cnpause(void);
+void video_on(void);
+int CRT_init(void);
+int kbd(int noblock);
+int scankbd(void);
 static char *_sprintk_ptr;
+void kbdreset(void);
+int CRT_test(void);
+int CRT_putc(int , unsigned char );
+/*int CRT_putc(int port, u_char c)*/
+int CRT_getc(void);
+int _vprintk(   int (*putc)(), const char *fmt0, va_list ap);
+static _cvt(unsigned long val, char *buf, long radix, char *digits);
+static void cursor(void);
+static void initscreen(void );
+
+/*
+ * COM1 NS16550 support
+ */
+
+struct NS16550
+	{
+		unsigned char rbr;  /* 0 */
+		unsigned char ier;  /* 1 */
+		unsigned char fcr;  /* 2 */
+		unsigned char lcr;  /* 3 */
+		unsigned char mcr;  /* 4 */
+		unsigned char lsr;  /* 5 */
+		unsigned char msr;  /* 6 */
+		unsigned char scr;  /* 7 */
+	};
 
+#define thr rbr
+#define iir fcr
+#define dll rbr
+#define dlm ier
+
+#define LSR_DR   0x01  /* Data ready */
+#define LSR_OE   0x02  /* Overrun */
+#define LSR_PE   0x04  /* Parity error */
+#define LSR_FE   0x08  /* Framing error */
+#define LSR_BI   0x10  /* Break */
+#define LSR_THRE 0x20  /* Xmit holding register empty */
+#define LSR_TEMT 0x40  /* Xmitter empty */
+#define LSR_ERR  0x80  /* Error */
+
+#define COM1	0x800003F8
+#define COM2	0x800002F8
+
+typedef struct NS16550 *NS16550_t;
+
+const NS16550_t COM_PORTS[] = { COM1,COM2};
+
+volatile struct NS16550 *NS16550_init(int chan);
+void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c);
+unsigned char NS16550_getc(volatile struct NS16550 *com_port);
 static _sputc(char c)
 {
    *_sprintk_ptr++ = c;
@@ -46,11 +102,7 @@
 
 #define is_digit(c) ((c >= '0') && (c <= '9'))
 
-int
-_vprintk(putc, fmt0, ap)
-   int (*putc)();
-   const char *fmt0;
-   va_list ap;
+int _vprintk(   int (*putc)(), const char *fmt0, va_list ap)
 {
    char c, sign, *cp;
    int left_prec, right_prec, zero_fill, length, pad, pad_on_right;
@@ -210,7 +262,6 @@
 /*
  * Console I/O interface
  */
-
 typedef const (*proc)();
 typedef int dev_t;
 
@@ -225,24 +276,24 @@
 static int line_num = 0;
 #define MAX_LINES 24
 
-char
-cngetc()
+char cngetc(void)
 {
    int s = _disable_interrupts();
    char c = '\0';
    if (port == CRT_PORT)
    {
-      c = CRT_getc(port);
+/*      c = CRT_getc(port);*/
+     c = CRT_getc();
    } else
    if (port)
    {
-      c = NS16550_getc(port);
+      c = NS16550_getc((struct NS16550 *)port);
    }
    _enable_interrupts(s);
    return (c);
 }
 
-cntstc()
+int cntstc(void)
 {
    return (0);
 }
@@ -268,7 +319,7 @@
          port = CRT_PORT;
       } else
       {
-         port = NS16550_init(0);
+         port =(int) NS16550_init(0);
       }
       init = TRUE;
    }
@@ -278,7 +329,7 @@
    } else
    if (port)
    {
-      NS16550_putc(port, c);
+      NS16550_putc((struct NS16550 *)port, c);
    }
    if (c == '\n')
    {
@@ -294,7 +345,7 @@
    }
 }
 
-_cnpause()
+void _cnpause(void)
 {
    int c;
    int s = _disable_interrupts();
@@ -323,7 +374,7 @@
    _enable_interrupts(s);
 }
 
-cnpause()
+void cnpause(void)
 {
    int c;
    int s = _disable_interrupts();
@@ -333,45 +384,7 @@
    _enable_interrupts(s);
 }
 
-/*
- * COM1 NS16550 support
- */
-
-struct NS16550
-	{
-		unsigned char rbr;  /* 0 */
-		unsigned char ier;  /* 1 */
-		unsigned char fcr;  /* 2 */
-		unsigned char lcr;  /* 3 */
-		unsigned char mcr;  /* 4 */
-		unsigned char lsr;  /* 5 */
-		unsigned char msr;  /* 6 */
-		unsigned char scr;  /* 7 */
-	};
-
-#define thr rbr
-#define iir fcr
-#define dll rbr
-#define dlm ier
-
-#define LSR_DR   0x01  /* Data ready */
-#define LSR_OE   0x02  /* Overrun */
-#define LSR_PE   0x04  /* Parity error */
-#define LSR_FE   0x08  /* Framing error */
-#define LSR_BI   0x10  /* Break */
-#define LSR_THRE 0x20  /* Xmit holding register empty */
-#define LSR_TEMT 0x40  /* Xmitter empty */
-#define LSR_ERR  0x80  /* Error */
-
-#define COM1	0x800003F8
-#define COM2	0x800002F8
-
-typedef struct NS16550 *NS16550_t;
-
-const NS16550_t COM_PORTS[] = { COM1, COM2};
-
-volatile struct NS16550 *
-NS16550_init(int chan)
+volatile struct NS16550 *NS16550_init(int chan)
 {
 	volatile struct NS16550 *com_port;
 	volatile unsigned char xx;
@@ -393,13 +406,14 @@
 }
 
 
-NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
+void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
 {
 	volatile int i;
 	while ((com_port->lsr & LSR_THRE) == 0) ;
 	com_port->thr = c;
 }
 
+
 unsigned char NS16550_getc(volatile struct NS16550 *com_port)
 {
 	while ((com_port->lsr & LSR_DR) == 0) ;
@@ -481,8 +495,7 @@
 /*
  * cursor() sets an offset (0-1999) into the 80x25 text area   
  */
-static void
-cursor()
+static void cursor(void)
 {
  	int pos = screen.cp - Crtat;
 
@@ -495,8 +508,7 @@
 	}
 }
 
-static void
-initscreen()
+static void initscreen(void )
 {
 	struct screen *d = &screen;
 
@@ -533,8 +545,7 @@
  * "ca" is the color/attributes value (left-shifted by 8)
  * or 0 if the current regular color for that screen is to be used.
  */
-void 
-CRT_putc(int port, u_char c)
+int CRT_putc(int port, unsigned char c)
 {
 	struct screen *d = &screen;
 	u_short *base;
@@ -779,13 +790,13 @@
 	cursor();
 }
 
-video_on()
+void video_on(void)
 { /* Enable video */
 	outb(0x3C4, 0x01);
 	outb(0x3C5, inb(0x3C5)&~20);
 }
 
-CRT_init()
+int CRT_init(void)
 {
 	unsigned long *PCI_base = (unsigned long *)0x80808010;  /* Magic */
 	struct screen *d = &screen;
@@ -964,9 +975,7 @@
 	_x__, 0x4E, 0x51, 0x4A, _x__, 0x49, 0x46, 0x54, /* 0x78-0x7F */
 };
 
-int
-kbd(noblock)
-	int noblock;
+int kbd(int noblock)
 {
 	unsigned char dt, brk, act;
 	int first = 1;	
@@ -1041,11 +1050,12 @@
 	goto loop;
 }
 
-scankbd() {
+int scankbd(void)
+{
 	return (kbd(1) != -1);
 }
 
-kbdreset()
+void kbdreset(void)
 {
 	unsigned char c;
 
@@ -1066,14 +1076,14 @@
 		;
 }
 
-CRT_getc()
+int CRT_getc(void)
 {
 	int c;
 	while ((c = kbd(0)) == 0) ;
 	return(c);
 }
 
-CRT_test()
+int CRT_test(void)
 {
 	return ((inb(KBSTATP) & KBINRDY) != 0);
 }
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v1.3.52/linux/arch/ppc/kernel/setup.c	Tue Dec 26 04:45:35 1995
+++ linux/arch/ppc/kernel/setup.c	Sat Dec 30 15:48:22 1995
@@ -134,9 +134,6 @@
 
 #define DEFAULT_ROOT_DEVICE 0x0200	/* fd0 */
 
-#define COMMAND_LINE_SIZE 512	/* Should match head.S */
-char saved_command_line[COMMAND_LINE_SIZE];
-
 void setup_arch(char **cmdline_p,
 	unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
@@ -146,7 +143,6 @@
 
 	ROOT_DEV = DEFAULT_ROOT_DEVICE;
 	aux_device_present = 0xaa;
-	strcpy(saved_command_line, cmd_line);
 	*cmdline_p = cmd_line;
 	*memory_start_p = (unsigned long) &_end;
 	*memory_end_p = (unsigned long *)Hash;
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/stubs.c linux/arch/ppc/kernel/stubs.c
--- v1.3.52/linux/arch/ppc/kernel/stubs.c	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/kernel/stubs.c	Sat Dec 30 15:48:22 1995
@@ -1,5 +1,9 @@
 #include <linux/in.h>
 
+unsigned int csum_tcpudp_magic(void);
+void halt(void);
+void _do_bottom_half(void);
+
 void sys_ptrace(void) { _panic("sys_ptrace"); }
 void sys_iopl(void) { _panic("sys_iopl"); }
 void sys_vm86(void) { _panic("sys_vm86"); }
@@ -9,10 +13,11 @@
 void sys_pipe(void) {_panic("sys_pipe"); }
 void sys_ipc(void) {_panic("sys_ipc"); }
 void sys_mmap(void) {_panic("sys_mmap"); }
-void sys_readdir(void) {_panic("sys_readdir"); }
-
+/* unneeded 
+void sys_readdir(void) {panic("sys_readdir"); }
+*/
 
-halt()
+void halt(void)
 {
 	_printk("\n...Halt!\n");
 	abort();
@@ -91,7 +96,8 @@
 	return (_val);
 }
 #endif
-_do_bottom_half()
+
+void _do_bottom_half(void)
 {
 	_enable_interrupts(1);
 	do_bottom_half();
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v1.3.52/linux/arch/ppc/kernel/traps.c	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/kernel/traps.c	Sat Dec 30 15:48:22 1995
@@ -26,7 +26,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <asm/processor.h>
+#include <asm/ppc_machine.h>
 
 /*
  * Trap & Exception support
@@ -68,7 +68,8 @@
 ProgramCheckException(struct pt_regs *regs)
 {
 	printk("Program check at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr);
-	_exception(SIGILL, regs);	
+	while(1) ;
+	_exception(SIGILL, regs);
 }
 
 FloatingPointCheckException(struct pt_regs *regs)
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile
--- v1.3.52/linux/arch/ppc/mm/Makefile	Mon Nov 27 12:48:27 1995
+++ linux/arch/ppc/mm/Makefile	Sat Dec 30 15:48:22 1995
@@ -24,6 +24,9 @@
 dep:
 	$(CPP) -M *.c > .depend
 
+fastdep:
+	$(CPP) -M *.c > .depend
+
 #
 # include a dependency file if one exists
 #
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v1.3.52/linux/arch/ppc/mm/fault.c	Mon Nov 27 12:48:27 1995
+++ linux/arch/ppc/mm/fault.c	Sat Dec 30 15:48:22 1995
@@ -1,3 +1,4 @@
+/* * Last edited: Nov 29 18:14 1995 (cort) */
 /*
  *  ARCH/ppc/mm/fault.c
  *
@@ -5,6 +6,9 @@
  *  Ported to PPC by Gary Thomas
  */
 
+/*#define NOISY_DATAFAULT*/
+/*#define NOISY_INSTRFAULT*/
+
 #include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -37,19 +41,24 @@
   if (user_mode(regs)) mode |= 0x04;
   if (regs->dsisr & 0x02000000) mode |= 0x02;  /* Load/store */
   if (regs->dsisr & 0x08000000) mode |= 0x01;  /* Protection violation */
-#if 0
-  /*#ifdef SHOW_FAULTS*/
-  printk("Data Access Fault - Loc: %x, DSISR: %x, PC: %x", regs->dar, regs->dsisr, regs->nip);
-  printk(" PR: %d\n", regs->msr &&(1<<14));
+#ifdef NOISY_DATAFAULT
+  printk("Data fault on %x\n",regs->dar);
 #endif
   if (mode & 0x01)
   {
 #if 0
     printk("Write Protect Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip);
 #endif
+#ifdef NOISY_DATAFAULT
+    printk("Write Protect fault\n ");
+#endif
     do_page_fault(regs, regs->dar, mode);
+#ifdef NOISY_DATAFAULT    
+    printk("Write Protect fault handled\n");
+#endif
     return;
   }
+/*   printk("trying\n"); */
   for (tries = 0;  tries < 1;  tries++)
   {
     dir = pgd_offset(current->mm, regs->dar & PAGE_MASK);
@@ -72,7 +81,15 @@
     {
       printk("No PGD\n");
     }
+#ifdef NOISY_DATAFAULT    
+    printk("fall through page fault addr=%x; ip=%x\n",
+	   regs->dar,regs->nip);
+    printk("beforefault: pgd[0] = %x[%x]\n",current->mm->pgd,*(current->mm->pgd));
+#endif
     do_page_fault(regs, regs->dar, mode);
+#ifdef NOISY_DATAFAULT    
+    printk("handled: pgd[0] = %x[%x]\n",current->mm->pgd,*(current->mm->pgd));
+#endif
   }
 }
 
@@ -83,43 +100,72 @@
   pmd_t *pmd;
   pte_t *pte;
   int tries, mode = 0;
-#if 0
-  panic("Instruction Access Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip);
-#endif	
+  
+#if NOISY_INSTRFAULT
+  printk("Instr fault on %x\n",regs->dar);
+#endif
   if (user_mode(regs)) mode |= 0x04;
   if (regs->dsisr & 0x02000000) mode |= 0x02;  /* Load/store */
   if (regs->dsisr & 0x08000000) mode |= 0x01;  /* Protection violation */
+  
   if (mode & 0x01)
   {
-    do_page_fault(regs, regs->dar, mode);
+    do_page_fault(regs, regs->dar, mode); 
     return;
   }
   for (tries = 0;  tries < 1;  tries++)
   {
+    /*     dir = pgd_offset(current->mm, regs->nip & PAGE_MASK); */
     dir = pgd_offset(current->mm, regs->dar & PAGE_MASK);
+#ifdef NOISY_INSTRFAULT
+/*	printk("regs->dar=%x current=%x current->mm=%x current->mm->pgd=%x current->tss.pg_tables=%x\n",
+	       regs->dar,current,current->mm,current->mm->pgd,current->tss.pg_tables);*/
+#endif
     if (dir)
     {
-      pmd = pmd_offset(dir, regs->dar & PAGE_MASK);
+      pmd = pmd_offset(dir, regs->dar & PAGE_MASK); 
       if (pmd && pmd_present(*pmd))
       {
-	pte = pte_offset(pmd, regs->dar & PAGE_MASK);
-	if (pte && pte_present(*pte))
-	{
+ 	pte = pte_offset(pmd, regs->dar & PAGE_MASK); 
+
+#ifdef NOISY_INSTRFAULT
+/*	printk("dir %x(%x) pmd %x(%x) pte %x\n",dir,*dir,pmd,*pmd,pte);*/
 #if 0
-	  printk("Page mapped - PTE: %x[%x]\n", pte, *(long *)pte);
+	printk("pgd_offset mm=%x mm->pgd=%x dirshouldbe=%x\n",
+	       current->mm, current->mm->pgd,
+	       current->mm->pgd+((regs->dar&PAGE_MASK) >> PGDIR_SHIFT));
+	printk("dir is %x\n", dir);
+	
+	/* 	printk("got pte\n"); */
+	if (pte) {
+	  printk("pgd=%x; dir=%x->%x; pmd=%x->%x; pte=%x; \n",
+		 current->mm->pgd,dir,*dir,pmd,*pmd,pte);
+	  if (pte_present(*pte)) {
+	    printk("pte present\n");
+	  } else {
+	    printk("pte not present\n");
+	  }
+	} else {
+	  printk("pte false\n");
+	}
 #endif
-	  MMU_hash_page(&current->tss, regs->dar & PAGE_MASK, pte);
+#endif
+	if (pte && pte_present(*pte))
+	{
+/* 	  MMU_hash_page(&current->tss, regs->nip & PAGE_MASK, pte); */
+ 	  MMU_hash_page(&current->tss, regs->dar & PAGE_MASK, pte); 
 	  return;
 	}
       }
     } else
     {
-#if 1
-  panic("No PGD Instruction Access Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip);
-#endif	
-      printk("No PGD\n");
+#ifdef NOISY_INSTRFAULT      
+      panic("No PGD Instruction Access Fault - Loc: %x, DSISR: %x, PC: %x current->mm\n",
+	    regs->dar, regs->dsisr, regs->nip, current->mm);
+#endif
     }
-    do_page_fault(regs, regs->dar, mode);
+/*     do_page_fault(regs, regs->nip, mode); */
+     do_page_fault(regs, regs->dar, mode);
   }
 }
 
@@ -138,24 +184,15 @@
 {
   struct vm_area_struct * vma;
   unsigned long page;
-/*  printk("\ndo_page_fault()\n");*/
+
+/*   printk("In do_page_fault()\n"); */
 #if 1
   for (vma = current->mm->mmap ; ; vma = vma->vm_next)
   {
     if (!vma)
     {
-#if 0 /* mfisk */
-        {   struct vm_area_struct * mmp;
-
-          for(mmp=current->mm->mmap; mmp; mmp=mmp->vm_next) {
-            printk("notinmap: current: %x; mm: %x; mmap: %x; vma: %x to %x flags: %x\n",
-                   current, current->mm, mmp, mmp->vm_start, mmp->vm_end, mmp->vm_flags);
-          }
-        }
-#endif
-       panic("do_page_fault()  !vma \n");
-      panic("not in map: ip = %x; current=%x; mm=%x; mmap=%x; address = %x error_code = %x\n",
-	    regs->nip, current, current->mm, current->mm->mmap, address, error_code);
+      panic("!vma: ip = %x; current=%x[%d]; mm=%x; mmap=%x; address = %x error_code = %x\n",
+	    regs->nip, current,current->pid,current->mm,current->mm->mmap, address, error_code);
       goto bad_area;
     }
     if (vma->vm_end > address)
@@ -164,6 +201,8 @@
 #else
   vma = find_vma(current, address);
   if (!vma)
+  {
+  }
     goto bad_area;
 #endif
   if (vma->vm_start <= address){
@@ -171,13 +210,19 @@
   }
   if (!(vma->vm_flags & VM_GROWSDOWN))
   {
+    printk("stack: gpr[1]=%x ip = %x; current=%x[%d]; mm=%x; mmap=%x; address = %x error_code = %x\n",regs->gpr[1],regs->nip, current,current->pid,current->mm,current->mm->mmap, address, error_code);
     panic("stack\n");
     goto bad_area;
   }
   if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
-  {    panic("stack 2\n");
+  {
+    printk("stack2: vma->vm_end-addres %x rlim %x\n", vma->vm_end - address,
+	   current->rlim[RLIMIT_STACK].rlim_cur);
+    printk("stack2: vm_end %x address = %x\n", vma->vm_end,address);
+    printk("stack2: gpr[1]=%x ip = %x; current=%x[%d]; mm=%x; mmap=%x; address = %x error_code = %x\n",regs->gpr[1],regs->nip, current,current->pid,current->mm,current->mm->mmap, address, error_code);
+    panic("stack2\n");
     goto bad_area;
-     }
+  }
   vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
   vma->vm_start = (address & PAGE_MASK);
   
@@ -192,8 +237,8 @@
   if (error_code & 2) {
     if (!(vma->vm_flags & VM_WRITE))
     {
-      panic("\ndo_page_fault()  write\n");
-      panic("\ndo_page_fault() write! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n",
+      panic("do_page_fault()  write\n");
+      panic("do_page_fault() write! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n",
 	    current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end);
       goto bad_area;
     }
@@ -224,7 +269,10 @@
       goto bad_area; 
     }
   }
+/*   printk("premm: pgd[0] = %x[%x]\n",current->mm->pgd,*(current->mm->pgd)); */
   handle_mm_fault(vma, address, error_code & 2); 
+/*   printk("handled fault for %x in %x to %x flags %x\n", */
+/* 	 address,vma->vm_start,vma->vm_end,vma->vm_flags); */
   return;
   
   /*
@@ -233,16 +281,21 @@
    */
 bad_area:
   if (user_mode(regs)) {
-    panic("Task: %x, PC: %x, bad area! - Addr: %x\n", current, regs->nip, address);
+    printk("Task: %x, PC: %x, bad area! - Addr: %x\n", current, regs->nip, address);
     send_sig(SIGSEGV, current, 1);
     return;
   }
 #if 0
-  panic("\nKERNEL! Task: %x, PC: %x, bad area! - Addr: %x, PGDIR: %x\n",
+  panic("KERNEL! Task: %x, PC: %x, bad area! - Addr: %x, PGDIR: %x\n",
 	 current, regs->nip, address, current->tss.pg_tables);
 #else
-  panic("\nKERNELmm! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n",
+  /*  panic("KERNEL mm! current: %x,  address:%x, vm_flags: %x, mm: %x; \nvma(%x) %x to %x swapper_pg_dir %x\n",
+	current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end,
+	swapper_pg_dir);*/
+  printk("KERNEL mm! current: %x,  address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n",
 	current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end);
+  panic("Kernel access of bad area\n");
+	 
 #endif
   
   while (1) ;
diff -u --recursive --new-file v1.3.52/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v1.3.52/linux/arch/ppc/mm/init.c	Mon Nov 27 12:48:27 1995
+++ linux/arch/ppc/mm/init.c	Sat Dec 30 15:48:22 1995
@@ -5,6 +5,7 @@
  *  Ported to PPC by Gary Thomas
  */
 
+
 #include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -27,7 +28,7 @@
    making it 8k for now.  will change later.
       -- Cort
    */
-pgd_t swapper_pg_dir[1024*8];
+pgd_t swapper_pg_dir[1024];
 /*pgd_t *swapper_pg_dir;*/
 
 pte *MMU_get_page(void);
@@ -331,6 +332,7 @@
    };
 BAT BAT2 =
    {
+/* map kernel with bats 0 = yes */
 #if 1
    	{
    		0x00000000>>17, 	/* bepi */
@@ -468,9 +470,9 @@
 {
 	int i, p;
 	SEGREG *segs;
-	_printk("MMU init - started\n");
+/*	_printk("MMU init - started\n");*/
 	find_end_of_memory();
-	_printk("  Start at 0x%08X, End at 0x%08X, Hash at 0x%08X\n", _start, _end, Hash);
+/*	_printk("  Start at 0x%08X, End at 0x%08X, Hash at 0x%08X\n", _start, _end, Hash);*/
 	_SDR1 = ((unsigned long)Hash & 0x00FFFFFF) | Hash_mask;
 	p = (int)mmu_pages;
 	p = (p + (MMU_PAGE_SIZE-1)) & ~(MMU_PAGE_SIZE-1);
@@ -507,7 +509,7 @@
 	{
 		MMU_map_page(&init_task.tss, i, i & 0x00FFFFFF, PAGE_KERNEL);
 	}
-	_printk("MMU init - done!\n");
+/*	_printk("MMU init - done!\n");*/
 }
 
 pte *
@@ -518,7 +520,7 @@
 	{
 		bzero((char *)pg, MMU_PAGE_SIZE);
 	}
-	_printk("MMU Allocate Page at %08X\n", pg);
+/*	_printk("MMU Allocate Page at %08X\n", pg);*/
 	return(pg);
 }
 
diff -u --recursive --new-file v1.3.52/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v1.3.52/linux/drivers/block/Config.in	Tue Dec 26 04:45:35 1995
+++ linux/drivers/block/Config.in	Sun Dec 31 14:32:44 1995
@@ -5,7 +5,7 @@
 comment 'block devices'
 
 tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD
-bool 'RAM disk support' CONFIG_BLK_DEV_RAM
+tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
 bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506
 if [ "$CONFIG_ST506" = "y" ]; then
   comment 'Please see drivers/block/README.ide for help/info on IDE drives'
diff -u --recursive --new-file v1.3.52/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v1.3.52/linux/drivers/block/Makefile	Tue Dec 26 04:45:35 1995
+++ linux/drivers/block/Makefile	Sun Dec 31 14:32:44 1995
@@ -30,6 +30,10 @@
 
 ifeq ($(CONFIG_BLK_DEV_RAM),y)
 L_OBJS += rd.o
+else
+  ifeq ($(CONFIG_BLK_DEV_RAM),m)
+  M_OBJS += rd.o
+  endif
 endif
 
 ifeq ($(CONFIG_BLK_DEV_HD),y)
diff -u --recursive --new-file v1.3.52/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v1.3.52/linux/drivers/block/rd.c	Tue Dec 26 04:45:36 1995
+++ linux/drivers/block/rd.c	Sun Dec 31 14:32:44 1995
@@ -23,6 +23,8 @@
  * 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.
+ *
+ * Loadable module support added by Tom Dyas.
  */
 
 #include <linux/sched.h>
@@ -35,6 +37,7 @@
 #include <linux/mman.h>
 #include <linux/malloc.h>
 #include <linux/ioctl.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/segment.h>
@@ -52,8 +55,10 @@
 #define BUILD_CRAMDISK
 #define NUM_RAMDISKS 8
 
+#ifndef MODULE
 void rd_load(void);
 static int crd_load(struct file *fp, struct file *outfp);
+#endif
 
 /* Various static variables go here... mostly used within the ramdisk code only. */
 
@@ -66,9 +71,11 @@
  * architecture-specific setup routine (from the stored bootsector
  * information). 
  */
+#ifndef MODULE
 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 */
+#endif
 
 /*
  *  Basically, my strategy here is to set up a buffer-head which can't be
@@ -143,9 +150,18 @@
 	if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
 		return -ENODEV;
 
+	MOD_INC_USE_COUNT;
+
 	return 0;
 }
 
+#ifdef MODULE
+static void rd_release(struct inode * inode, struct file * filp)
+{
+	MOD_DEC_USE_COUNT;
+}
+#endif
+
 static struct file_operations fd_fops = {
 	NULL,		/* lseek - default */
 	block_read,	/* read - block dev write */
@@ -155,7 +171,11 @@
 	rd_ioctl, 	/* ioctl */
 	NULL,		/* mmap */
 	rd_open,	/* open */
+#ifndef MODULE
 	NULL,		/* no special release code... */
+#else
+	rd_release,	/* module needs to decrement use count */
+#endif
 	block_fsync		/* fsync */ 
 };
 
@@ -165,7 +185,7 @@
 	int		i;
 
 	if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
-		printk("RAMDISK2 : Could not get major %d", MAJOR_NR);
+		printk("RAMDISK: Could not get major %d", MAJOR_NR);
 		return -EIO;
 	}
 
@@ -181,6 +201,7 @@
 	return 0;
 }
 
+#ifndef MODULE
 /*
  * 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
@@ -523,7 +544,27 @@
 	return result;
 }
 
-#endif
+#endif  /* BUILD_CRAMDISK */
+
+#endif  /* MODULE */
+
 
+/* loadable module support */
 
+#ifdef MODULE
+
+int init_module(void)
+{
+	int error = rd_init();
+	if (!error)
+		printk(KERN_INFO "RAMDISK: Loaded as module.\n");
+	return error;
+}
+
+void cleanup_module(void)
+{
+	unregister_blkdev( MAJOR_NR, "ramdisk" );
+	blk_dev[MAJOR_NR].request_fn = 0;
+}
 
+#endif  /* MODULE */
diff -u --recursive --new-file v1.3.52/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v1.3.52/linux/drivers/cdrom/sonycd535.c	Thu Nov  9 11:23:48 1995
+++ linux/drivers/cdrom/sonycd535.c	Sat Dec 30 21:00:40 1995
@@ -286,7 +286,8 @@
 enable_interrupts(void)
 {
 #ifdef USE_IRQ
-	/* this code snarfed from cdu31a.c; it will not
+	/*
+	 * This code was taken from cdu31a.c; it will not
 	 * directly work for the cdu535 as written...
 	 */
 	curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
@@ -300,7 +301,8 @@
 disable_interrupts(void)
 {
 #ifdef USE_IRQ
-	/* this code snarfed from cdu31a.c; it will not
+	/*
+	 * This code was taken from cdu31a.c; it will not
 	 * directly work for the cdu535 as written...
 	 */
 	curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
diff -u --recursive --new-file v1.3.52/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c
--- v1.3.52/linux/drivers/net/ac3200.c	Fri Nov 17 08:42:25 1995
+++ linux/drivers/net/ac3200.c	Sat Dec 30 21:00:40 1995
@@ -158,7 +158,7 @@
 		   inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
 #endif
 
-	/* Assign and snarf the interrupt now. */
+	/* Assign and allocate the interrupt now. */
 	if (dev->irq == 0)
 		dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
 	else if (dev->irq == 2)
diff -u --recursive --new-file v1.3.52/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v1.3.52/linux/drivers/net/depca.c	Tue Dec 26 04:45:36 1995
+++ linux/drivers/net/depca.c	Sat Dec 30 15:59:11 1995
@@ -37,8 +37,9 @@
     I have benchmarked the driver with a  DE100 at 595kB/s to (542kB/s from)
     a DECstation 5000/200.
 
-    The author may be reached as davies@wanton.lkg.dec.com or
-    Digital Equipment Corporation, 550 King Street, Littleton MA 01460.
+    The   author   may    be   reached  at    davies@wanton.lkg.dec.com   or
+    davies@maniac.ultranet.com  or Digital  Equipment Corporation, 550  King
+    Street, Littleton MA 01460.
 
     =========================================================================
 
@@ -132,8 +133,10 @@
     that the correct bits are compiled (see end of source code).
     4) if you are wanting to add a new  card, goto 5. Otherwise, recompile a
     kernel with the depca configuration turned off and reboot.
-    5) insmod depca.o [irq=7] [io=0x200]
+    5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100]
        [Alan Cox: Changed the code to allow command line irq/io assignments]
+       [Dave Davies: Changed the code to allow command line mem/name
+                                                                assignments]
     6) run the net startup bits for your eth?? interface manually 
     (usually /etc/rc.inet[12] at boot time). 
     7) enjoy!
@@ -144,6 +147,15 @@
     To unload a module, turn off the associated interface 
     'ifconfig eth?? down' then 'rmmod depca'.
 
+    To assign a base memory address for the shared memory  when running as a
+    loadable module, see 5 above.  To include the adapter  name (if you have
+    no PROM  but know the card name)  also see 5  above. Note that this last
+    option  will not work  with kernel  built-in  depca's. 
+
+    The shared memory assignment for a loadable module  makes sense to avoid
+    the 'memory autoprobe' picking the wrong shared memory  (for the case of
+    2 depca's in a PC).
+
 
     TO DO:
     ------
@@ -182,15 +194,20 @@
                           ALPHA support from <jestabro@amt.tay1.dec.com>
       0.41    26-Jun-95   Added verify_area() calls in depca_ioctl() from
                           suggestion by <heiko@colossus.escape.de>
+      0.42    27-Dec-95   Add 'mem' shared memory assigment for loadable 
+                          modules.
+                          Add 'adapter_name' for loadable modules when no PROM.
+			  Both above from a suggestion by 
+			  <pchen@woodruffs121.residence.gatech.edu>.
+			  Add new multicasting code.
 
     =========================================================================
 */
 
-static const char *version = "depca.c:v0.41 5/26/95 davies@wanton.lkg.dec.com\n";
+static const char *version = "depca.c:v0.42 95/12/27 davies@wanton.lkg.dec.com\n";
 
 #include <linux/module.h>
 
-#include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -199,6 +216,7 @@
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <asm/segment.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -208,6 +226,10 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
+#include <linux/time.h>
+#include <linux/types.h>
+#include <linux/unistd.h>
+
 #include "depca.h"
 
 #ifdef DEPCA_DEBUG
@@ -384,6 +406,7 @@
 static void   eisa_probe(struct device *dev, u_long iobase);
 static struct device *alloc_device(struct device *dev, u_long iobase);
 static int    load_packet(struct device *dev, struct sk_buff *skb);
+static void   depca_dbg_open(struct device *dev);
 
 #ifdef MODULE
 int           init_module(void);
@@ -399,7 +422,11 @@
 
 static char   name[DEPCA_STRLEN];
 static int    num_depcas = 0, num_eth = 0;
-
+static int    mem=0;                       /* For loadable module assignment
+                                              use insmod mem=0x????? .... */
+static char   *adapter_name = '\0';        /* If no PROM when loadable module
+					      use insmod adapter_name=DE??? ...
+					   */
 /*
 ** Miscellaneous defines...
 */
@@ -454,10 +481,19 @@
   outb(nicsr, DEPCA_NICSR);
 
   if (inw(DEPCA_DATA) == STOP) {
-    for (; mem_base[mem_chkd]; mem_chkd++) {
-      mem_start = mem_base[mem_chkd];
-      DepcaSignature(name, mem_start);
-      if (*name != '\0') break;
+    if (mem == 0) {
+      for (; mem_base[mem_chkd]; mem_chkd++) {
+	mem_start = mem_base[mem_chkd];
+	DepcaSignature(name, mem_start);
+	if (*name != '\0') break;
+      }
+    } else {
+      mem_start = mem;
+      if (adapter_name) {
+	strcpy(name, adapter_name);
+      } else{
+	DepcaSignature(name, mem_start);
+      }
     }
 
     if ((*name != '\0') && mem_start) {           /* found a DEPCA device */
@@ -583,18 +619,18 @@
 	  
 	    irqnum = autoirq_report(1);
 	    if (!irqnum) {
-	      printk("      and failed to detect IRQ line.\n");
+	      printk(" and failed to detect IRQ line.\n");
 	      status = -ENXIO;
 	    } else {
 	      for (dev->irq=0,i=0; (depca_irq[i]) && (!dev->irq); i++) {
 		if (irqnum == depca_irq[i]) {
 		  dev->irq = irqnum;
-		  printk("      and uses IRQ%d.\n", dev->irq);
+		  printk(" and uses IRQ%d.\n", dev->irq);
 		}
 	      }
 	      
 	      if (!dev->irq) {
-		printk("      but incorrect IRQ line detected.\n");
+		printk(" but incorrect IRQ line detected.\n");
 		status = -ENXIO;
 	      }
 	    }
@@ -647,115 +683,52 @@
 static int
 depca_open(struct device *dev)
 {
-    struct depca_private *lp = (struct depca_private *)dev->priv;
-    s16 nicsr;
-    u_long ioaddr = dev->base_addr;
-    int i, status = 0;
-    struct depca_init *p = (struct depca_init *)lp->sh_mem;
-
-    if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name)) {
-        printk("depca_open(): Requested IRQ%d is busy\n",dev->irq);
-	status = -EAGAIN;
-    }
-
-    irq2dev_map[dev->irq] = dev;
-    STOP_DEPCA;
-    nicsr = inb(DEPCA_NICSR);
-
-    /* Make sure the shadow RAM is enabled */
-    if (adapter != DEPCA) {
-      nicsr |= SHE;
-      outb(nicsr, DEPCA_NICSR);
-    }
+  struct depca_private *lp = (struct depca_private *)dev->priv;
+  u_long ioaddr = dev->base_addr;
+  s16 nicsr;
+  int status = 0;
 
-    /* Re-initialize the DEPCA... */
-    depca_init_ring(dev);
-    LoadCSRs(dev);
+  irq2dev_map[dev->irq] = dev;
+  STOP_DEPCA;
+  nicsr = inb(DEPCA_NICSR);
 
-    if (depca_debug > 1){
-      /* Copy the shadow init_block to shared memory */
-      memcpy_toio((char *)lp->sh_mem, &lp->init_block, sizeof(struct depca_init));
+  /* Make sure the shadow RAM is enabled */
+  if (adapter != DEPCA) {
+    nicsr |= SHE;
+    outb(nicsr, DEPCA_NICSR);
+  }
 
-      printk("%s: depca open with irq %d\n",dev->name,dev->irq);
-      printk("Descriptor head addresses:\n");
-      printk("\t0x%lx  0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring);
-      printk("Descriptor addresses:\nRX: ");
-      for (i=0;i<lp->rxRingMask;i++){
-	if (i < 3) {
-	  printk("0x%8.8lx ", (long) &lp->rx_ring[i].base);
-	}
-      }
-      printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base);
-      printk("TX: ");
-      for (i=0;i<lp->txRingMask;i++){
-	if (i < 3) {
-	  printk("0x%8.8lx ", (long) &lp->tx_ring[i].base);
-	}
-      }
-      printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base);
-      printk("\nDescriptor buffers:\nRX: ");
-      for (i=0;i<lp->rxRingMask;i++){
-	if (i < 3) {
-	  printk("0x%8.8lx  ", readl(&lp->rx_ring[i].base));
-	}
-      }
-      printk("...0x%8.8lx\n", readl(&lp->rx_ring[i].base));
-      printk("TX: ");
-      for (i=0;i<lp->txRingMask;i++){
-	if (i < 3) {
-	  printk("0x%8.8lx  ", readl(&lp->tx_ring[i].base));
-	}
-      }
-      printk("...0x%8.8lx\n", readl(&lp->tx_ring[i].base));
-      printk("Status:  %d\n", status);
-      printk("Initialisation block at 0x%8.8lx\n",lp->sh_mem);
-      printk("\tmode: 0x%4.4lx\n",readw(&p->mode));
-      printk("\tphysical address: ");
-      for (i=0;i<ETH_ALEN-1;i++){
-	printk("%2.2x:",(u_char)readb(&p->phys_addr[i]));
-      }
-      printk("%2.2x\n",(u_char)readb(&p->phys_addr[i]));
-      printk("\tmulticast hash table: ");
-      for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){
-	printk("%2.2x:",(u_char)readb(&p->mcast_table[i]));
-      }
-      printk("%2.2x\n",(u_char)readb(&p->mcast_table[i]));
-      printk("\trx_ring at: 0x%8.8lx\n",readl(&p->rx_ring));
-      printk("\ttx_ring at: 0x%8.8lx\n",readl(&p->tx_ring));
-      printk("dma_buffs: 0x%8.8lx\n",lp->dma_buffs);
-      printk("Ring size:\nRX: %d  Log2(rxRingMask): 0x%8.8x\n", 
-                                          (int)lp->rxRingMask + 1, 
-                                          lp->rx_rlen);
-      printk("TX: %d  Log2(txRingMask): 0x%8.8x\n", 
-                                          (int)lp->txRingMask + 1, 
-                                          lp->tx_rlen);
-      outw(CSR2,DEPCA_ADDR);
-      printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA));
-      outw(CSR1,DEPCA_ADDR);
-      printk("%4.4x\n",inw(DEPCA_DATA));
-      outw(CSR3,DEPCA_ADDR);
-      printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA));
-    }
+  /* Re-initialize the DEPCA... */
+  depca_init_ring(dev);
+  LoadCSRs(dev);
+
+  depca_dbg_open(dev);
+
+  if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name)) {
+    printk("depca_open(): Requested IRQ%d is busy\n",dev->irq);
+    status = -EAGAIN;
+  } else {
 
     /* Enable DEPCA board interrupts and turn off LED */
     nicsr = ((nicsr & ~IM & ~LED)|IEN);
     outb(nicsr, DEPCA_NICSR);
     outw(CSR0,DEPCA_ADDR);
-
+    
     dev->tbusy = 0;                         
     dev->interrupt = 0;
     dev->start = 1;
-
+    
     status = InitRestartDepca(dev);
 
     if (depca_debug > 1){
       printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA));
       printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR));
     }
+  }
 
-    MOD_INC_USE_COUNT;
-
-    return status;
+  MOD_INC_USE_COUNT;
+  
+  return status;
 }
 
 /* Initialize the lance Rx and Tx descriptor rings. */
@@ -940,8 +913,8 @@
 
 	skb = dev_alloc_skb(pkt_len+2);
 	if (skb != NULL) {
-	  unsigned char * buf;
-	  skb_reserve(skb,2);	/* 16 byte align the IP header */
+	  unsigned char *buf;
+	  skb_reserve(skb,2);               /* 16 byte align the IP header */
 	  buf = skb_put(skb,pkt_len);
 	  skb->dev = dev;
 	  if (entry < lp->rx_old) {         /* Wrapped buffer */
@@ -1166,15 +1139,13 @@
     STOP_DEPCA;                       /* Temporarily stop the depca.  */
     depca_init_ring(dev);             /* Initialize the descriptor rings */
 
-    if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) 
-    {
-	lp->init_block.mode |= PROM;    /* Set promiscuous mode */
-    }
-    else
-    {
-    	SetMulticastFilter(dev);
-    	lp->init_block.mode &= ~PROM;   /* Unset promiscuous mode */
+    if (dev->flags & IFF_PROMISC) {   /* Set promiscuous mode */
+      lp->init_block.mode |= PROM;
+    } else {
+      SetMulticastFilter(dev);
+      lp->init_block.mode &= ~PROM;   /* Unset promiscuous mode */
     }
+
     LoadCSRs(dev);                    /* Reload CSR3 */
     InitRestartDepca(dev);            /* Resume normal operation. */
     dev->tbusy = 0;                   /* Unlock the TX ring */
@@ -1190,32 +1161,28 @@
 static void SetMulticastFilter(struct device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
+  struct dev_mc_list *dmi=dev->mc_list;
+  char *addrs;
   int i, j, bit, byte;
   u16 hashcode;
   s32 crc, poly = CRC_POLYNOMIAL_BE;
-  struct dev_mc_list *dmi=dev->mc_list;
 
-  if (dev->mc_count >= HASH_TABLE_LEN) 
-  {       /* Set all multicast bits */
-  	for (i=0; i<(HASH_TABLE_LEN>>3); i++) 
-  	{
-		lp->init_block.mcast_table[i] = (char)0xff;
-	}
-  }
-  else {
-    /* Clear the multicast table first */
-    for (i=0; i<(HASH_TABLE_LEN>>3); i++){
+  if (dev->flags & IFF_ALLMULTI) {         /* Set all multicast bits */
+    for (i=0; i<(HASH_TABLE_LEN>>3); i++) {
+      lp->init_block.mcast_table[i] = (char)0xff;
+    }
+  } else {
+    for (i=0; i<(HASH_TABLE_LEN>>3); i++){ /* Clear the multicast table */
       lp->init_block.mcast_table[i]=0;
     }
-
-    /* Add multicast addresses */
-    for (i=0;i<dev->mc_count;i++) {            /* for each address in the list */
-      unsigned char *addrs=dmi->dmi_addr;
+                                           /* Add multicast addresses */
+    for (i=0;i<dev->mc_count;i++) {        /* for each address in the list */
+      addrs=dmi->dmi_addr;
       dmi=dmi->next;
       if ((*addrs & 0x01) == 1) {          /* multicast address? */ 
 	crc = 0xffffffff;                  /* init CRC for each address */
 	for (byte=0;byte<ETH_ALEN;byte++) {/* for each address byte */
-	  /* process each address bit */ 
+	                                   /* process each address bit */ 
 	  for (bit = *addrs++,j=0;j<8;j++, bit>>=1) {
 	    crc = (crc << 1) ^ ((((crc<0?1:0) ^ bit) & 0x01) ? poly : 0);
 	  }
@@ -1229,8 +1196,6 @@
 	byte = hashcode >> 3;              /* bit[3-5] -> byte in filter */
 	bit = 1 << (hashcode & 0x07);      /* bit[0-2] -> bit in byte */
 	lp->init_block.mcast_table[byte] |= bit;
-      } else {                             /* skip this address */
-	addrs += ETH_ALEN;
       }
     }
   }
@@ -1586,14 +1551,14 @@
     for (i = entry; i != end; i = (++i) & lp->txRingMask) {
                                                /* clean out flags */
       writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base);
-      writew(0x0000, &lp->tx_ring[i].misc);       /* clears other error flags */
+      writew(0x0000, &lp->tx_ring[i].misc);    /* clears other error flags */
       writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);/* packet length in buffer */
       len -= TX_BUFF_SZ;
     }
                                                /* clean out flags */
     writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base);
-    writew(0x0000, &lp->tx_ring[end].misc);       /* clears other error flags */
-    writew(-len, &lp->tx_ring[end].length);       /* packet length in last buff */
+    writew(0x0000, &lp->tx_ring[end].misc);    /* clears other error flags */
+    writew(-len, &lp->tx_ring[end].length);    /* packet length in last buff */
 
                                                /* start of packet */
     writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base);
@@ -1635,7 +1600,7 @@
   ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40);
   ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40);
   ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30);
-  ManCode[3]=((Eisa.Id[2]&0x0f)+0x30);
+  ManCode[3]=(( Eisa.Id[2]&0x0f)+0x30);
   ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30);
   ManCode[5]='\0';
 
@@ -1649,9 +1614,84 @@
   return status;
 }
 
+static void depca_dbg_open(struct device *dev)
+{
+  struct depca_private *lp = (struct depca_private *)dev->priv;
+  u_long ioaddr = dev->base_addr;
+  struct depca_init *p = (struct depca_init *)lp->sh_mem;
+  int i; 
+
+  if (depca_debug > 1){
+    /* Copy the shadow init_block to shared memory */
+    memcpy_toio((char *)lp->sh_mem,&lp->init_block,sizeof(struct depca_init));
+
+    printk("%s: depca open with irq %d\n",dev->name,dev->irq);
+    printk("Descriptor head addresses:\n");
+    printk("\t0x%lx  0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring);
+    printk("Descriptor addresses:\nRX: ");
+    for (i=0;i<lp->rxRingMask;i++){
+      if (i < 3) {
+	printk("0x%8.8lx ", (long) &lp->rx_ring[i].base);
+      }
+    }
+    printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base);
+    printk("TX: ");
+    for (i=0;i<lp->txRingMask;i++){
+      if (i < 3) {
+	printk("0x%8.8lx ", (long) &lp->tx_ring[i].base);
+      }
+    }
+    printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base);
+    printk("\nDescriptor buffers:\nRX: ");
+    for (i=0;i<lp->rxRingMask;i++){
+      if (i < 3) {
+	printk("0x%8.8x  ", readl(&lp->rx_ring[i].base));
+      }
+    }
+    printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base));
+    printk("TX: ");
+    for (i=0;i<lp->txRingMask;i++){
+      if (i < 3) {
+	printk("0x%8.8x  ", readl(&lp->tx_ring[i].base));
+      }
+    }
+    printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));
+    printk("Initialisation block at 0x%8.8lx\n",lp->sh_mem);
+    printk("\tmode: 0x%4.4x\n",readw(&p->mode));
+    printk("\tphysical address: ");
+    for (i=0;i<ETH_ALEN-1;i++){
+      printk("%2.2x:",(u_char)readb(&p->phys_addr[i]));
+    }
+    printk("%2.2x\n",(u_char)readb(&p->phys_addr[i]));
+    printk("\tmulticast hash table: ");
+    for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){
+      printk("%2.2x:",(u_char)readb(&p->mcast_table[i]));
+    }
+    printk("%2.2x\n",(u_char)readb(&p->mcast_table[i]));
+    printk("\trx_ring at: 0x%8.8x\n",readl(&p->rx_ring));
+    printk("\ttx_ring at: 0x%8.8x\n",readl(&p->tx_ring));
+    printk("dma_buffs: 0x%8.8lx\n",lp->dma_buffs);
+    printk("Ring size:\nRX: %d  Log2(rxRingMask): 0x%8.8x\n", 
+	   (int)lp->rxRingMask + 1, 
+	   lp->rx_rlen);
+    printk("TX: %d  Log2(txRingMask): 0x%8.8x\n", 
+	   (int)lp->txRingMask + 1, 
+	   lp->tx_rlen);
+    outw(CSR2,DEPCA_ADDR);
+    printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA));
+    outw(CSR1,DEPCA_ADDR);
+    printk("%4.4x\n",inw(DEPCA_DATA));
+    outw(CSR3,DEPCA_ADDR);
+    printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA));
+  }
+
+  return;
+}
+
 /*
 ** Perform IOCTL call functions here. Some are privileged operations and the
 ** effective uid is checked in those cases.
+** All MCA IOCTLs will not work here and are for testing purposes only.
 */
 static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 {
@@ -1745,16 +1785,11 @@
     }
 
     break;
-#if 0    
   case DEPCA_SET_MCA:                /* Set a multicast address */
     if (suser()) {
-      if (ioc->len != HASH_TABLE_LEN) {         /* MCA changes */
-	if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) {
-	  memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
-	  set_multicast_list(dev, ioc->len, tmp.addr);
-	}
-      } else {
-	set_multicast_list(dev, ioc->len, NULL);
+      if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) {
+	memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
+	set_multicast_list(dev);
       }
     } else {
       status = -EPERM;
@@ -1763,7 +1798,7 @@
     break;
   case DEPCA_CLR_MCA:                /* Clear all multicast addresses */
     if (suser()) {
-      set_multicast_list(dev, 0, NULL);
+      set_multicast_list(dev);
     } else {
       status = -EPERM;
     }
@@ -1771,13 +1806,12 @@
     break;
   case DEPCA_MCA_EN:                 /* Enable pass all multicast addressing */
     if (suser()) {
-      set_multicast_list(dev, HASH_TABLE_LEN, NULL);
+      set_multicast_list(dev);
     } else {
       status = -EPERM;
     }
 
     break;
-#endif    
   case DEPCA_GET_STATS:              /* Get the driver statistics */
     cli();
     ioc->len = sizeof(lp->pktStats);
@@ -1819,21 +1853,21 @@
 #ifdef MODULE
 static char devicename[9] = { 0, };
 static struct device thisDepca = {
-  devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+  devicename,  /* device name is inserted by /linux/drivers/net/net_init.c */
   0, 0, 0, 0,
-  0x200, 7,   /* I/O address, IRQ */
+  0x200, 7,    /* I/O address, IRQ */
   0, 0, 0, NULL, depca_probe };
 
 static int irq=7;	/* EDIT THESE LINE FOR YOUR CONFIGURATION */
 static int io=0x200;    /* Or use the irq= io= options to insmod */
-	
+
+/* See depca_probe() for autoprobe messages when a module */	
 int
 init_module(void)
 {
-  if (io == 0)
-    printk("depca: You should not use auto-probing with insmod!\n");
   thisDepca.irq=irq;
   thisDepca.base_addr=io;
+
   if (register_netdev(&thisDepca) != 0)
     return -EIO;
 
@@ -1843,13 +1877,14 @@
 void
 cleanup_module(void)
 {
-    release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE);
-    if (thisDepca.priv) {
-      kfree_s(thisDepca.priv, sizeof(struct depca_private));
-      thisDepca.priv = NULL;
-    }
+  release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE);
+  if (thisDepca.priv) {
+    kfree(thisDepca.priv);
+    thisDepca.priv = NULL;
+  }
+  thisDepca.irq=0;
 
-    unregister_netdev(&thisDepca);
+  unregister_netdev(&thisDepca);
 }
 #endif /* MODULE */
 
diff -u --recursive --new-file v1.3.52/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v1.3.52/linux/drivers/net/ewrk3.c	Sun Dec 17 11:43:18 1995
+++ linux/drivers/net/ewrk3.c	Sat Dec 30 21:01:43 1995
@@ -1,4 +1,4 @@
-/*  ewrk3.c: A DIGITAL EtherWORKS 3 ethernet driver for linux.
+/*  ewrk3.c: A DIGITAL EtherWORKS 3 ethernet driver for Linux.
 
     Written 1994 by David C. Davies.
 
@@ -18,8 +18,9 @@
     card and benchmarked with 'ttcp': it transferred 16M  of data at 975kB/s
     (7.8Mb/s) to a DECstation 5000/200.
 
-    The author may    be  reached as davies@wanton.lkg.dec.com  or   Digital
-    Equipment Corporation, 550 King Street, Littleton MA 01460.
+    The     author  may  be    reached    at  davies@wanton.lkg.dec.com   or
+    davies@maniac.ultranet.com or  Digital  Equipment Corporation,  550 King
+    Street, Littleton MA 01460.
 
     =========================================================================
     This driver has been written  substantially  from scratch, although  its
@@ -48,9 +49,10 @@
     base  address, thus leaving more  room to clutter  your  system box with
     other memory hungry boards.
 
-    Upto 21 ISA and 7 EISA cards can be supported under this driver, limited
-    primarily by the  available  IRQ   lines.   I have   checked   different
-    configurations  of multiple depca  cards and  ewrk3 cards  and  have not
+    As many ISA  and EISA cards  can be supported  under this driver  as you
+    wish, limited primarily  by the available IRQ lines,  rather than by the
+    available I/O addresses  (24 ISA,  16 EISA).   I have  checked different
+    configurations of  multiple  depca cards and  ewrk3 cards  and have  not
     found a problem yet (provided you have at least depca.c v0.38) ...
 
     The board IRQ setting   must be at  an unused  IRQ which is  auto-probed
@@ -68,19 +70,18 @@
     0) have a copy of the loadable modules code installed on your system.
     1) copy ewrk3.c from the  /linux/drivers/net directory to your favourite
     temporary directory.
-    2) edit the  source code near  line 1830 to reflect  the I/O address and
+    2) edit the  source code near  line 1880 to reflect  the I/O address and
     IRQ you're using.
     3) compile  ewrk3.c, but include -DMODULE in  the command line to ensure
     that the correct bits are compiled (see end of source code).
     4) if you are wanting to add a new  card, goto 5. Otherwise, recompile a
     kernel with the ewrk3 configuration turned off and reboot.
     5) insmod ewrk3.o
+          [Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y]
     6) run the net startup bits for your new eth?? interface manually 
     (usually /etc/rc.inet[12] at boot time). 
     7) enjoy!
 
-    [Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y]
-
     Note that autoprobing is not allowed in loadable modules - the system is
     already up and running and you're messing with interrupts.
 
@@ -115,23 +116,28 @@
                           Fixed up MCA hash table algorithm.
       0.20     4-sep-94   Added IOCTL functionality.
       0.21    14-sep-94   Added I/O mode.
-      0.21axp 15-sep-94   Special version for ALPHA AXP Linux V1.0
+      0.21axp 15-sep-94   Special version for ALPHA AXP Linux V1.0.
       0.22    16-sep-94   Added more IOCTLs & tidied up.
-      0.23    21-sep-94   Added transmit cut through
-      0.24    31-oct-94   Added uid checks in some ioctls
-      0.30     1-nov-94   BETA code release
-      0.31     5-dec-94   Added check/snarf_region code.
-      0.32    16-jan-95   Broadcast packet fix
+      0.23    21-sep-94   Added transmit cut through.
+      0.24    31-oct-94   Added uid checks in some ioctls.
+      0.30     1-nov-94   BETA code release.
+      0.31     5-dec-94   Added check/allocate region code.
+      0.32    16-jan-95   Broadcast packet fix.
+      0.33    10-Feb-95   Fix recognition bug reported by <bkm@star.rl.ac.uk>.
+      0.40    27-Dec-95   Rationalise MODULE and autoprobe code.
+                          Rewrite for portability & updated.
+                          ALPHA support from <jestabro@amt.tay1.dec.com>
+                          Added verify_area() calls in depca_ioctl() from
+                          suggestion by <heiko@colossus.escape.de>.
+			  Add new multicasting code.
 
     =========================================================================
 */
 
-static const char *version = "ewrk3.c:v0.32 1/16/95 davies@wanton.lkg.dec.com\n";
+static const char *version = "ewrk3.c:v0.40 95/12/27 davies@wanton.lkg.dec.com\n";
 
 #include <linux/module.h>
 
-#include <stdarg.h>
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -140,18 +146,20 @@
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/segment.h>
+
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+
 #include <linux/time.h>
 #include <linux/types.h>
 #include <linux/unistd.h>
 
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/segment.h>
-
 #include "ewrk3.h"
 
 #ifdef EWRK3_DEBUG
@@ -160,17 +168,14 @@
 static int ewrk3_debug = 1;
 #endif
 
-#ifndef PROBE_LENGTH
-#define PROBE_LENGTH    32
-#endif
+#define EWRK3_NDA 0xffe0            /* No Device Address */
 
-#ifndef PROBE_SEQUENCE
-#define PROBE_SEQUENCE "FF0055AAFF0055AA"
-#endif
+#define PROBE_LENGTH    32
+#define ETH_PROM_SIG    0xAA5500FFUL
 
 #ifndef EWRK3_SIGNATURE
 #define EWRK3_SIGNATURE {"DE203","DE204","DE205",""}
-#define EWRK3_NAME_LENGTH 8
+#define EWRK3_STRLEN 8
 #endif
 
 #ifndef EWRK3_RAM_BASE_ADDRESSES
@@ -178,25 +183,11 @@
 #endif
 
 /*
-** Sets up the search areas for the autoprobe. You can disable an area
-** by writing a zero into the corresponding bit position in EWRK3_IO_SEARCH.
-** The LSb -> I/O 0x100. Each bit increments the I/O location searched by 0x20.
-** Bit 24 -> I/O 0x400.
-**
-** By default, probes at locations:
-**             0x1e0   (may conflict with hard disk)
-**             0x320   (may conflict with hard disk)
-**             0x3e0   (may conflict with floppy disk)
-**
-** are disabled.
+** Sets up the I/O area for the autoprobe.
 */
-
 #define EWRK3_IO_BASE 0x100             /* Start address for probe search */
 #define EWRK3_IOP_INC 0x20              /* I/O address increment */
-#define EWRK3_TOTAL_SIZE 0x20           /* required I/O address space */
-#define EWRK3_IO_SEARCH 0x007dff7f      /* probe search mask */
-static long mem_chkd = EWRK3_IO_SEARCH; /* holds which I/O addrs should be */
-				        /* checked, for multi-EWRK3 case */
+#define EWRK3_TOTAL_SIZE 0x20           /* required I/O address length */
 
 #ifndef MAX_NUM_EWRK3S
 #define MAX_NUM_EWRK3S 21
@@ -207,13 +198,15 @@
 #endif
 
 #ifndef MAX_EISA_SLOTS
-#define MAX_EISA_SLOTS 8
+#define MAX_EISA_SLOTS 16
 #define EISA_SLOT_INC 0x1000
 #endif
 
 #define CRC_POLYNOMIAL_BE 0x04c11db7UL   /* Ethernet CRC, big endian */
 #define CRC_POLYNOMIAL_LE 0xedb88320UL   /* Ethernet CRC, little endian */
 
+#define QUEUE_PKT_TIMEOUT (100)          /* Jiffies */
+
 /*
 ** EtherWORKS 3 shared memory window sizes
 */
@@ -225,28 +218,30 @@
 /*
 ** EtherWORKS 3 IRQ ENABLE/DISABLE
 */
-static unsigned char irq_mask = TNEM|TXDM|RNEM|RXDM;
-
-#define ENABLE_IRQs \
-  icr |= irq_mask;\
-  outb(icr, EWRK3_ICR)                      /* Enable the IRQs */
+#define ENABLE_IRQs { \
+  icr |= lp->irq_mask;\
+  outb(icr, EWRK3_ICR);                     /* Enable the IRQs */\
+}
 
-#define DISABLE_IRQs \
+#define DISABLE_IRQs { \
   icr = inb(EWRK3_ICR);\
-  icr &= ~irq_mask;\
-  outb(icr, EWRK3_ICR)                      /* Disable the IRQs */
+  icr &= ~lp->irq_mask;\
+  outb(icr, EWRK3_ICR);                     /* Disable the IRQs */\
+}
 
 /*
 ** EtherWORKS 3 START/STOP
 */
-#define START_EWRK3 \
+#define START_EWRK3 { \
   csr = inb(EWRK3_CSR);\
-  csr &= ~(TXD|RXD);\
-  outb(csr, EWRK3_CSR)                      /* Enable the TX and/or RX */
+  csr &= ~(CSR_TXD|CSR_RXD);\
+  outb(csr, EWRK3_CSR);                     /* Enable the TX and/or RX */\
+}
 
-#define STOP_EWRK3 \
-  csr = (TXD|RXD);\
-  outb(csr, EWRK3_CSR)                      /* Disable the TX and/or RX */
+#define STOP_EWRK3 { \
+  csr = (CSR_TXD|CSR_RXD);\
+  outb(csr, EWRK3_CSR);                     /* Disable the TX and/or RX */\
+}
 
 /*
 ** The EtherWORKS 3 private structure
@@ -256,149 +251,133 @@
                                            increase EWRK3_PKT_STAT_SZ */
 
 struct ewrk3_private {
-    long shmem_base;                    /* Shared memory start address */
-    long shmem_length;                  /* Shared memory window length */
+    char adapter_name[80];              /* Name exported to /proc/ioports */
+    u_long shmem_base;                  /* Shared memory start address */
+    u_long shmem_length;                /* Shared memory window length */
     struct enet_statistics stats;       /* Public stats */
     struct {
-      unsigned long bins[EWRK3_PKT_STAT_SZ]; /* Private stats counters */
-      unsigned long unicast;
-      unsigned long multicast;
-      unsigned long broadcast;
-      unsigned long excessive_collisions;
-      unsigned long tx_underruns;
-      unsigned long excessive_underruns;
+      u32 bins[EWRK3_PKT_STAT_SZ]; /* Private stats counters */
+      u32 unicast;
+      u32 multicast;
+      u32 broadcast;
+      u32 excessive_collisions;
+      u32 tx_underruns;
+      u32 excessive_underruns;
     } pktStats;
-    short mPage;                        /* Maximum 2kB Page number */
-    unsigned char lemac;                /* Chip rev. level */
-    unsigned char hard_strapped;        /* Don't allow a full open */
-    unsigned char lock;                 /* Lock the page register */
-    unsigned char txc;                  /* Transmit cut through */
+    u_char irq_mask;                    /* Adapter IRQ mask bits */
+    u_char mPage;                       /* Maximum 2kB Page number */
+    u_char lemac;                       /* Chip rev. level */
+    u_char hard_strapped;               /* Don't allow a full open */
+    u_char lock;                        /* Lock the page register */
+    u_char txc;                         /* Transmit cut through */
+    u_char *mctbl;                      /* Pointer to the multicast table */
 };
 
 /*
 ** Force the EtherWORKS 3 card to be in 2kB MODE
 */
-#define FORCE_2K_MODE \
+#define FORCE_2K_MODE { \
   shmem_length = SHMEM_2K;\
-  outb(((mem_start - 0x80000) >> 11), EWRK3_MBR)
+  outb(((mem_start - 0x80000) >> 11), EWRK3_MBR);\
+}
 
 /*
 ** Public Functions
 */
-static int ewrk3_open(struct device *dev);
-static int ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev);
-static void ewrk3_interrupt(int irq, struct pt_regs *regs);
-static int ewrk3_close(struct device *dev);
+static int    ewrk3_open(struct device *dev);
+static int    ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev);
+static void   ewrk3_interrupt(int irq, struct pt_regs *regs);
+static int    ewrk3_close(struct device *dev);
 static struct enet_statistics *ewrk3_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
-static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+static void   set_multicast_list(struct device *dev);
+static int    ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd);
 
 /*
 ** Private functions
 */
-static int  ewrk3_hw_init(struct device *dev, short iobase);
-static void ewrk3_init(struct device *dev);
-static int  ewrk3_rx(struct device *dev);
-static int  ewrk3_tx(struct device *dev);
-
-static void EthwrkSignature(char * name, char *eeprom_image);
-static int  DevicePresent(short iobase);
-static void SetMulticastFilter(struct device *dev, int num_addr, char *multicast_table);
-
-static int  Read_EEPROM(short iobase, unsigned char eaddr);
-static int  Write_EEPROM(short data, short iobase, unsigned char eaddr);
-static unsigned char aprom_crc (struct device *dev, unsigned char *eeprom_image, char chipType);
-
-#ifndef MODULE
-static struct device *isa_probe(struct device *dev);
-static struct device *eisa_probe(struct device *dev);
-static struct device *alloc_device(struct device *dev, int iobase);
+static int    ewrk3_hw_init(struct device *dev, u_long iobase);
+static void   ewrk3_init(struct device *dev);
+static int    ewrk3_rx(struct device *dev);
+static int    ewrk3_tx(struct device *dev);
+
+static void   EthwrkSignature(char * name, char *eeprom_image);
+static int    DevicePresent(u_long iobase);
+static void   SetMulticastFilter(struct device *dev);
+static int    EISA_signature(char *name, s32 eisa_id);
+
+static int    Read_EEPROM(u_long iobase, u_char eaddr);
+static int    Write_EEPROM(short data, u_long iobase, u_char eaddr);
+static u_char get_hw_addr (struct device *dev, u_char *eeprom_image, char chipType);
+
+static void   isa_probe(struct device *dev, u_long iobase);
+static void   eisa_probe(struct device *dev, u_long iobase);
+static struct device *alloc_device(struct device *dev, u_long iobase);
 
-static int num_ewrk3s = 0, num_eth = 0;
-static unsigned char irq[] = {5,0,10,3,11,9,15,12};
 
-#else
+#ifdef MODULE
 int  init_module(void);
 void cleanup_module(void);
+static int autoprobed = 1, loading_module = 1;
+
+# else
+static u_char irq[] = {5,0,10,3,11,9,15,12};
+static int autoprobed = 0, loading_module = 0;
 
 #endif /* MODULE */
 
-static int autoprobed = 0;
+static char name[EWRK3_STRLEN + 1];
+static int num_ewrk3s = 0, num_eth = 0;
 
 /*
 ** Miscellaneous defines...
 */
 #define INIT_EWRK3 {\
-    int i;\
     outb(EEPROM_INIT, EWRK3_IOPR);\
-    for (i=0;i<5000;i++) inb(EWRK3_CSR);\
-		   }
+    udelay(1000);\
+}
 
 
 
 
 int ewrk3_probe(struct device *dev)
 {
-  int base_addr = dev->base_addr;
-  int status = -ENODEV;
-#ifndef MODULE
-  struct device *eth0;
-#endif
+  int tmp = num_ewrk3s, status = -ENODEV;
+  u_long iobase = dev->base_addr;
 
-  if (base_addr > 0x0ff) {	      /* Check a single specified location. */
-    if (!autoprobed) {                /* Module or fixed location */
-      if (!check_region(base_addr, EWRK3_TOTAL_SIZE)) {
-	if (((mem_chkd >> ((base_addr - EWRK3_IO_BASE)/ EWRK3_IOP_INC))&0x01)==1) {
-	  if (DevicePresent(base_addr) == 0) {      /* Is EWRK3 really here? */
-	                                            /* Register I/O Region */
-	    request_region(base_addr, EWRK3_IOP_INC, "ewrk3");
-	    status = ewrk3_hw_init(dev, base_addr);
-	  } else {
-	    printk("ewrk3_probe(): No device found\n");
-	    mem_chkd &= ~(0x01 << ((base_addr - EWRK3_IO_BASE)/EWRK3_IOP_INC));
-	  }
-	}
-      } else {
-	printk("%s: ewrk3_probe(): Detected a device already registered at 0x%02x\n", dev->name, base_addr);
-	mem_chkd &= ~(0x01 << ((base_addr - EWRK3_IO_BASE)/EWRK3_IOP_INC));
-      }
-    } else {                          /* already know what ewrk3 h/w is here */
-      status = ewrk3_hw_init(dev, base_addr);
-    }
-  } else if (base_addr > 0) {         /* Don't probe at all. */
-    status = -ENXIO;
-
-#ifdef MODULE
-  } else {
+  if ((iobase == 0) && loading_module){
     printk("Autoprobing is not supported when loading a module based driver.\n");
     status = -EIO;
-#else
-  } else if (!autoprobed) {           /* First probe for the EWRK3 test */
-                                      /* pattern in ROM */
-    eth0=isa_probe(dev);
-    eth0=eisa_probe(eth0);
-    if (dev->priv) status=0;
-    autoprobed = 1;
-  } else {
-    status = -ENXIO;
-#endif /* MODULE */
-    
-  }
+  } else {                              /* First probe for the Ethernet */
+	                                /* Address PROM pattern */
+    isa_probe(dev, iobase);
+    eisa_probe(dev, iobase);
+
+    if ((tmp == num_ewrk3s) && (iobase != 0) && loading_module) {
+      printk("%s: ewrk3_probe() cannot find device at 0x%04lx.\n", dev->name, 
+	                                                               iobase);
+    }
 
-  if (status) dev->base_addr = base_addr;
+    /*
+    ** Walk the device list to check that at least one device
+    ** initialised OK
+    */
+    for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next);
+
+    if (dev->priv) status = 0;
+    if (iobase == 0) autoprobed = 1;
+  }
 
   return status;
 }
 
 static int
-ewrk3_hw_init(struct device *dev, short iobase)
+ewrk3_hw_init(struct device *dev, u_long iobase)
 {
   struct ewrk3_private *lp;
   int i, status=0;
-  unsigned long mem_start, shmem_length;
-  char name[EWRK3_NAME_LENGTH + 1];
-  unsigned char cr, cmr, icr, nicsr, lemac, hard_strapped = 0;
-  unsigned char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0;
+  u_long mem_start, shmem_length;
+  u_char cr, cmr, icr, nicsr, lemac, hard_strapped = 0;
+  u_char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0;
 
   /*
   ** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot.
@@ -409,16 +388,13 @@
 
   nicsr = inb(EWRK3_CSR);
 
-  /*
-  ** Disable & mask all board interrupts
-  */
-  DISABLE_IRQs;
+  icr = inb(EWRK3_ICR);
+  icr |= 0xf0;
+  outb(icr, EWRK3_ICR);                           /* Disable all the IRQs */
 
-  if (nicsr == (TXD|RXD)) {
+  if (nicsr == CSR_TXD|CSR_RXD) {
 
-    /*
-    ** Check that the EEPROM is alive and well and not living on Pluto...
-    */
+    /* Check that the EEPROM is alive and well and not living on Pluto... */
     for (chksum=0, i=0; i<EEPROM_MAX; i+=2) {
       union {
 	short val;
@@ -428,7 +404,6 @@
       tmp.val = (short)Read_EEPROM(iobase, (i>>1));
       eeprom_image[i] = tmp.c[0];
       eeprom_image[i+1] = tmp.c[1];
-
       chksum += eeprom_image[i] + eeprom_image[i+1];
     }
 
@@ -436,11 +411,7 @@
       printk("%s: Device has a bad on-board EEPROM.\n", dev->name);
       status = -ENXIO;
     } else {
-      /* 
-      ** Now find out what kind of EWRK3 we have.
-      */
       EthwrkSignature(name, eeprom_image);
-
       if (*name != '\0') {                         /* found a EWRK3 device */
 	dev->base_addr = iobase;
       
@@ -451,51 +422,40 @@
 	lemac = eeprom_image[EEPROM_CHIPVER];
 	cmr = inb(EWRK3_CMR);
 
-	if (((lemac == LeMAC) && ((cmr & NO_EEPROM) != NO_EEPROM)) ||
-	    ((lemac == LeMAC2) && !(cmr & HS))) {
-	  printk("%s: %s at %#3x", dev->name, name, iobase);
+	if (((lemac == LeMAC) && ((cmr & CMR_NO_EEPROM) != CMR_NO_EEPROM)) ||
+	    ((lemac == LeMAC2) && !(cmr & CMR_HS))) {
+	  printk("%s: %s at %#4lx", dev->name, name, iobase);
 	  hard_strapped = 1;
 	} else if ((iobase&0x0fff)==EWRK3_EISA_IO_PORTS) {
 	                                           /* EISA slot address */
-	  printk("%s: %s at %#3x (EISA slot %d)", 
+	  printk("%s: %s at %#4lx (EISA slot %ld)", 
 	                         dev->name, name, iobase, ((iobase>>12)&0x0f));
 	} else {                                   /* ISA port address */
-	  printk("%s: %s at %#3x", dev->name, name, iobase);
+	  printk("%s: %s at %#4lx", dev->name, name, iobase);
 	}
 	
 	if (!status) {
 	  printk(", h/w address ");
-	  if (lemac == LeMAC2) {
-	    for (i = 0;i < ETH_ALEN - 1;i++) { /* get the ethernet address */
-	      printk("%2.2x:", dev->dev_addr[i] = 
-		                              eeprom_image[EEPROM_PADDR0 + i]);
-	      outb(eeprom_image[EEPROM_PADDR0 + i], EWRK3_PAR0 + i);
-	    }
-	    printk("%2.2x,\n",dev->dev_addr[i] = eeprom_image[EEPROM_PADDR0 + i]);
-	    outb(eeprom_image[EEPROM_PADDR0 + i], EWRK3_PAR0 + i);
-	  } else {
-	    DevicePresent(iobase);          /* needed after the EWRK3_INIT */
-	    for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */
-	      printk("%2.2x:", dev->dev_addr[i] = inb(EWRK3_APROM));
-	      outb(dev->dev_addr[i], EWRK3_PAR0 + i);
-	    }
-	    printk("%2.2x,\n", dev->dev_addr[i] = inb(EWRK3_APROM));
-	    outb(dev->dev_addr[i], EWRK3_PAR0 + i);
+	  if (lemac!=LeMAC2) DevicePresent(iobase);/* need after EWRK3_INIT */
+	  status = get_hw_addr(dev, eeprom_image, lemac);
+	  for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */
+	    printk("%2.2x:", dev->dev_addr[i]);
 	  }
+	  printk("%2.2x,\n", dev->dev_addr[i]);
 
-	  if (aprom_crc(dev, eeprom_image, lemac)) {
+	  if (status) {
 	    printk("      which has an EEPROM CRC error.\n");
 	    status = -ENXIO;
 	  } else {
 	    if (lemac == LeMAC2) {            /* Special LeMAC2 CMR things */
-	      cmr &= ~(RA | WB | LINK | POLARITY | _0WS);         
-	      if (eeprom_image[EEPROM_MISC0] & READ_AHEAD)    cmr |= RA;
-	      if (eeprom_image[EEPROM_MISC0] & WRITE_BEHIND)  cmr |= WB;
-	      if (eeprom_image[EEPROM_NETMAN0] & NETMAN_POL)  cmr |= POLARITY;
-	      if (eeprom_image[EEPROM_NETMAN0] & NETMAN_LINK) cmr |= LINK;
-	      if (eeprom_image[EEPROM_MISC0] & _0WS_ENA)      cmr |= _0WS;
+	      cmr &= ~(CMR_RA | CMR_WB | CMR_LINK | CMR_POLARITY | CMR_0WS);
+	      if (eeprom_image[EEPROM_MISC0] & READ_AHEAD)    cmr |= CMR_RA;
+	      if (eeprom_image[EEPROM_MISC0] & WRITE_BEHIND)  cmr |= CMR_WB;
+	      if (eeprom_image[EEPROM_NETMAN0] & NETMAN_POL)  cmr |= CMR_POLARITY;
+	      if (eeprom_image[EEPROM_NETMAN0] & NETMAN_LINK) cmr |= CMR_LINK;
+	      if (eeprom_image[EEPROM_MISC0] & _0WS_ENA)      cmr |= CMR_0WS;
 	    }
-	    if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM)      cmr |= DRAM;
+	    if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM)      cmr |= CMR_DRAM;
 	    outb(cmr, EWRK3_CMR);
 
 	    cr = inb(EWRK3_CR);               /* Set up the Control Register */
@@ -545,8 +505,9 @@
 	      /* private area & initialise */
 	      dev->priv = (void *) kmalloc(sizeof(struct ewrk3_private), 
 					                           GFP_KERNEL);
-	      if (dev->priv == NULL)
-		  return -ENOMEM;
+	      if (dev->priv == NULL) {
+		return -ENOMEM;
+	      }
 	      lp = (struct ewrk3_private *)dev->priv;
 	      memset(dev->priv, 0, sizeof(struct ewrk3_private));
 	      lp->shmem_base = mem_start;
@@ -555,13 +516,18 @@
 	      lp->hard_strapped = hard_strapped;
 
 	      lp->mPage = 64;
-	      if (cmr & DRAM) lp->mPage <<= 1 ;     /* 2 DRAMS on module */ 
+	      if (cmr & CMR_DRAM) lp->mPage <<= 1 ;/* 2 DRAMS on module */ 
 
+	      sprintf(lp->adapter_name,"%s (%s)", name, dev->name);
+	      request_region(iobase, EWRK3_TOTAL_SIZE, lp->adapter_name);
+
+	      lp->irq_mask = ICR_TNEM|ICR_TXDM|ICR_RNEM|ICR_RXDM;
+	      
 	      if (!hard_strapped) {
 		/*
 		** Enable EWRK3 board interrupts for autoprobing
 		*/
-		icr |= IE;	                   /* Enable interrupts */
+		icr |= ICR_IE;	                   /* Enable interrupts */
 		outb(icr, EWRK3_ICR);
 	    
 		/* The DMA channel may be passed in on this parameter. */
@@ -571,14 +537,14 @@
 		   interrupts. For now we will always get a DMA error. */
 		if (dev->irq < 2) {
 #ifndef MODULE
-		  unsigned char irqnum;
+		  u_char irqnum;
 	      
 		  autoirq_setup(0);
 
 		  /* 
 		  ** Trigger a TNE interrupt.
 		  */
-		  icr |=TNEM;
+		  icr |=ICR_TNEM;
 		  outb(1,EWRK3_TDQ);          /* Write to the TX done queue */
 		  outb(icr, EWRK3_ICR);       /* Unmask the TXD interrupt */
 	      
@@ -605,6 +571,7 @@
 		  printk(" and requires IRQ%d.\n", dev->irq);
 		}
 	      }
+	      if (status) release_region(iobase, EWRK3_TOTAL_SIZE);
 	    } else {
 	      status = -ENXIO;
 	    }
@@ -645,9 +612,9 @@
 ewrk3_open(struct device *dev)
 {
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
-  int i, iobase = dev->base_addr;
-  int status = 0;
-  unsigned char icr, csr;
+  u_long iobase = dev->base_addr;
+  int i, status = 0;
+  u_char icr, csr;
 
   /*
   ** Stop the TX and RX...
@@ -655,13 +622,13 @@
   STOP_EWRK3;
 
   if (!lp->hard_strapped) {
-    if (request_irq(dev->irq, &ewrk3_interrupt, 0, "ewrk3")) {
+    irq2dev_map[dev->irq] = dev;                   /* For latched interrupts */
+
+    if (request_irq(dev->irq, (void *)ewrk3_interrupt, 0, "ewrk3")) {
       printk("ewrk3_open(): Requested IRQ%d is busy\n",dev->irq);
       status = -EAGAIN;
     } else {
 
-      irq2dev_map[dev->irq] = dev;
-
       /* 
       ** Re-initialize the EWRK3... 
       */
@@ -669,24 +636,23 @@
 
       if (ewrk3_debug > 1){
 	printk("%s: ewrk3 open with irq %d\n",dev->name,dev->irq);
-	printk("\tphysical address: ");
-	for (i=0;i<6;i++){
-	  printk("%2.2x:",(short)dev->dev_addr[i]);
+	printk("  physical address: ");
+	for (i=0;i<5;i++){
+	  printk("%2.2x:",(u_char)dev->dev_addr[i]);
 	}
-	printk("\n");
-	printk("\tchecked memory: 0x%08lx\n",mem_chkd);
+	printk("%2.2x\n",(u_char)dev->dev_addr[i]);
 	if (lp->shmem_length == 0) {
-	  printk("\tno shared memory, I/O only mode\n");
+	  printk("  no shared memory, I/O only mode\n");
 	} else {
-	  printk("\tstart of shared memory: 0x%08lx\n",lp->shmem_base);
-	  printk("\twindow length: 0x%04lx\n",lp->shmem_length);
+	  printk("  start of shared memory: 0x%08lx\n",lp->shmem_base);
+	  printk("  window length: 0x%04lx\n",lp->shmem_length);
 	}
-	printk("\t# of DRAMS: %d\n",((inb(EWRK3_CMR) & 0x02) ? 2 : 1));
-	printk("\tcsr:  0x%02x\n", inb(EWRK3_CSR));
-	printk("\tcr:   0x%02x\n", inb(EWRK3_CR));
-	printk("\ticr:  0x%02x\n", inb(EWRK3_ICR));
-	printk("\tcmr:  0x%02x\n", inb(EWRK3_CMR));
-	printk("\tfmqc: 0x%02x\n", inb(EWRK3_FMQC));
+	printk("  # of DRAMS: %d\n",((inb(EWRK3_CMR) & 0x02) ? 2 : 1));
+	printk("  csr:  0x%02x\n", inb(EWRK3_CSR));
+	printk("  cr:   0x%02x\n", inb(EWRK3_CR));
+	printk("  icr:  0x%02x\n", inb(EWRK3_ICR));
+	printk("  cmr:  0x%02x\n", inb(EWRK3_CMR));
+	printk("  fmqc: 0x%02x\n", inb(EWRK3_FMQC));
       }
 
       dev->tbusy = 0;                         
@@ -719,17 +685,13 @@
 ewrk3_init(struct device *dev)
 {
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
-  char csr, page;
-  short iobase = dev->base_addr;
-  int flags=dev->flags;
+  u_char csr, page;
+  u_long iobase = dev->base_addr;
   
   /* 
-  ** Enable all multicasts 
+  ** Enable any multicasts 
   */
-  
-  dev->flags|=IFF_ALLMULTI;
   set_multicast_list(dev);
-  dev->flags=flags;
 
   /*
   ** Clean out any remaining entries in all the queues here
@@ -758,14 +720,14 @@
 ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev)
 {
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
-  int iobase = dev->base_addr;
+  u_long iobase = dev->base_addr;
   int status = 0;
-  unsigned char icr, csr;
+  u_char icr, csr;
 
   /* Transmitter timeout, serious problems. */
   if (dev->tbusy || lp->lock) {
     int tickssofar = jiffies - dev->trans_start;
-    if (tickssofar < 10) {
+    if (tickssofar < QUEUE_PKT_TIMEOUT) {
       status = -1;
     } else if (!lp->hard_strapped) {
       printk("%s: transmit timed/locked out, status %04x, resetting.\n",
@@ -808,12 +770,10 @@
     ** Get a free page from the FMQ when resources are available
     */
     if (inb(EWRK3_FMQC) > 0) {
-      unsigned char *buf;
-      unsigned char page;
+      u_long buf = 0;
+      u_char page;
 
       if ((page = inb(EWRK3_FMQ)) < lp->mPage) {
-	buf = NULL;
-
 	/*
 	** Set up shared memory window and pointer into the window
 	*/
@@ -821,13 +781,13 @@
 	if (lp->shmem_length == IO_ONLY) {
 	  outb(page, EWRK3_IOPR);
 	} else if (lp->shmem_length == SHMEM_2K) {
-	  buf = (char *) lp->shmem_base;
+	  buf = lp->shmem_base;
 	  outb(page, EWRK3_MPR);
 	} else if (lp->shmem_length == SHMEM_32K) {
-	  buf = (char *)((((short)page << 11) & 0x7800) + lp->shmem_base);
+	  buf = ((((short)page << 11) & 0x7800) + lp->shmem_base);
 	  outb((page >> 4), EWRK3_MPR);
 	} else if (lp->shmem_length == SHMEM_64K) {
-	  buf = (char *)((((short)page << 11) & 0xf800) + lp->shmem_base);
+	  buf = ((((short)page << 11) & 0xf800) + lp->shmem_base);
 	  outb((page >> 5), EWRK3_MPR);
 	} else {
 	  status = -1;
@@ -843,9 +803,9 @@
 
 	  if (lp->shmem_length == IO_ONLY) {
 	    int i;
-	    unsigned char *p = skb->data;
+	    u_char *p = skb->data;
 	    
-	    outb((char)(QMODE | PAD | IFC), EWRK3_DATA);
+	    outb((char)(TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA);
 	    outb((char)(skb->len & 0xff), EWRK3_DATA);
 	    outb((char)((skb->len >> 8) & 0xff), EWRK3_DATA);
 	    outb((char)0x04, EWRK3_DATA);
@@ -854,26 +814,31 @@
 	    }
 	    outb(page, EWRK3_TQ);                     /* Start sending pkt */
 	  } else {
-	    *buf++ = (char)(QMODE | PAD | IFC);       /* control byte */
-	    *buf++ = (char)(skb->len & 0xff);         /* length (16 bit xfer)*/
+	    writeb((char)(TCR_QMODE|TCR_PAD|TCR_IFC), (char *)buf);/* ctrl byte*/
+	    buf+=1;
+	    writeb((char)(skb->len & 0xff), (char *)buf);/* length (16 bit xfer)*/
+	    buf+=1;
 	    if (lp->txc) {
-	      *buf++ = (char)(((skb->len >> 8) & 0xff) | XCT);
-	      *buf++ = 0x04;                          /* index byte */
-	      *(buf + skb->len) = 0x00;               /* Write the XCT flag */
-	      memcpy(buf, skb->data, PRELOAD);        /* Write PRELOAD bytes */
+	      writeb((char)(((skb->len >> 8) & 0xff) | XCT), (char *)buf);
+	      buf+=1;
+	      writeb(0x04, (char *)buf);                 /* index byte */
+	      buf+=1;
+	      writeb(0x00, (char *)(buf + skb->len));    /* Write the XCT flag */
+	      memcpy_toio(buf, skb->data, PRELOAD);/* Write PRELOAD bytes*/
 	      outb(page, EWRK3_TQ);                   /* Start sending pkt */
-	      memcpy(buf + PRELOAD, skb->data + PRELOAD, skb->len - PRELOAD);
-	      *(buf + skb->len) = 0xff;               /* Write the XCT flag */
+	      memcpy_toio(buf+PRELOAD, skb->data+PRELOAD, skb->len-PRELOAD);
+	      writeb(0xff, (char *)(buf + skb->len));    /* Write the XCT flag */
 	    } else {
-	      *buf++ = (char)((skb->len >> 8) & 0xff);
-	      *buf++ = 0x04;                          /* index byte */
-	      memcpy(buf, skb->data, skb->len);       /* Write data bytes */
+	      writeb((char)((skb->len >> 8) & 0xff), (char *)buf);
+	      buf+=1;
+	      writeb(0x04, (char *)buf);                 /* index byte */
+	      buf+=1;
+	      memcpy_toio((char *)buf, skb->data, skb->len);/* Write data bytes */
 	      outb(page, EWRK3_TQ);                   /* Start sending pkt */
 	    }
 	  }
 
 	  dev->trans_start = jiffies;
-
 	  dev_kfree_skb (skb, FREE_WRITE);
 
         } else {              /* return unused page to the free memory queue */
@@ -882,7 +847,7 @@
 	lp->lock = 0;         /* unlock the page register */
       } else {
 	printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n",
-	                                                 (unsigned char) page);
+	                                                 (u_char) page);
       }
     } else {
       printk("ewrk3_queue_pkt(): No free resources...\n");
@@ -908,8 +873,8 @@
 {
     struct device *dev = (struct device *)(irq2dev_map[irq]);
     struct ewrk3_private *lp;
-    int iobase;
-    unsigned char icr, cr, csr;
+    u_long iobase;
+    u_char icr, cr, csr;
 
     if (dev == NULL) {
 	printk ("ewrk3_interrupt(): irq %d for unknown device.\n", irq);
@@ -931,13 +896,13 @@
       DISABLE_IRQs;
 
       cr = inb(EWRK3_CR);
-      cr |= LED;
+      cr |= CR_LED;
       outb(cr, EWRK3_CR);
 
-      if (csr & RNE)		  /* Rx interrupt (packet[s] arrived) */
+      if (csr & CSR_RNE)	  /* Rx interrupt (packet[s] arrived) */
 	ewrk3_rx(dev);
 
-      if (csr & TNE) 	          /* Tx interrupt (packet sent) */
+      if (csr & CSR_TNE)          /* Tx interrupt (packet sent) */
         ewrk3_tx(dev);
 
       /*
@@ -947,21 +912,20 @@
       ** in the system hanging in an interrupt loop.
       */
       if (inb(EWRK3_FMQC)) {      /* any resources available? */
-	irq_mask |= TXDM|RXDM;    /* enable the interrupt source */
-	csr &= ~(TXD|RXD);        /* ensure restart of a stalled TX or RX */
+	lp->irq_mask |= ICR_TXDM|ICR_RXDM;/* enable the interrupt source */
+	csr &= ~(CSR_TXD|CSR_RXD);/* ensure restart of a stalled TX or RX */
 	outb(csr, EWRK3_CSR);
 	dev->tbusy = 0;           /* clear TX busy flag */
 	mark_bh(NET_BH);
       } else {
-	irq_mask &= ~(TXDM|RXDM); /* disable the interrupt source */
+	lp->irq_mask &= ~(ICR_TXDM|ICR_RXDM);/* disable the interrupt source */
       }
 
       /* Unmask the EWRK3 board interrupts and turn off the LED */
-      cr &= ~LED;
+      cr &= ~CR_LED;
       outb(cr, EWRK3_CR);
 
       dev->interrupt = UNMASK_INTERRUPTS;
-
       ENABLE_IRQs;
     }
 
@@ -972,14 +936,13 @@
 ewrk3_rx(struct device *dev)
 {
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
-  int i, iobase = dev->base_addr;
-  unsigned char page, tmpPage = 0, tmpLock = 0, *buf;
-  int status = 0;
+  u_long iobase = dev->base_addr;
+  int i, status = 0;
+  u_char page, tmpPage = 0, tmpLock = 0;
+  u_long buf = 0;
 
   while (inb(EWRK3_RQC) && !status) {        /* Whilst there's incoming data */
     if ((page = inb(EWRK3_RQ)) < lp->mPage) {/* Get next entry's buffer page */
-      buf = NULL;
-
       /*
       ** Preempt any process using the current page register. Check for
       ** an existing lock to reduce time taken in I/O transactions.
@@ -998,13 +961,13 @@
       if (lp->shmem_length == IO_ONLY) {
 	outb(page, EWRK3_IOPR);
       } else if (lp->shmem_length == SHMEM_2K) {
-	buf = (char *) lp->shmem_base;
+	buf = lp->shmem_base;
 	outb(page, EWRK3_MPR);
       } else if (lp->shmem_length == SHMEM_32K) {
-	buf = (char *)((((short)page << 11) & 0x7800) + lp->shmem_base);
+	buf = ((((short)page << 11) & 0x7800) + lp->shmem_base);
 	outb((page >> 4), EWRK3_MPR);
       } else if (lp->shmem_length == SHMEM_64K) {
-	buf = (char *)((((short)page << 11) & 0xf800) + lp->shmem_base);
+	buf = ((((short)page << 11) & 0xf800) + lp->shmem_base);
 	outb((page >> 5), EWRK3_MPR);
       } else {
 	status = -1;
@@ -1018,25 +981,26 @@
 	if (lp->shmem_length == IO_ONLY) {
 	  rx_status = inb(EWRK3_DATA);
 	  pkt_len = inb(EWRK3_DATA);
-	  pkt_len |= ((unsigned short)inb(EWRK3_DATA) << 8);
+	  pkt_len |= ((u_short)inb(EWRK3_DATA) << 8);
 	} else {
-	  rx_status = (char)(*buf++);
-	  pkt_len = (short)(*buf+((*(buf+1))<<8));
+	  rx_status = readb(buf);
+	  buf+=1;
+	  pkt_len = readw(buf);
 	  buf+=3;
 	}
 
-	if (!(rx_status & ROK)) {	    /* There was an error. */
+	if (!(rx_status & R_ROK)) {	    /* There was an error. */
 	  lp->stats.rx_errors++;            /* Update the error stats. */
-	  if (rx_status & DBE) lp->stats.rx_frame_errors++;
-	  if (rx_status & CRC) lp->stats.rx_crc_errors++;
-	  if (rx_status & PLL) lp->stats.rx_fifo_errors++;
+	  if (rx_status & R_DBE) lp->stats.rx_frame_errors++;
+	  if (rx_status & R_CRC) lp->stats.rx_crc_errors++;
+	  if (rx_status & R_PLL) lp->stats.rx_fifo_errors++;
 	} else {
 	  struct sk_buff *skb;
 
           if ((skb = dev_alloc_skb(pkt_len+2)) != NULL) {
             unsigned char *p;
 	    skb->dev = dev;
-	    skb_reserve(skb,2);		/* Align to 16 bytes */
+	    skb_reserve(skb,2);             /* Align to 16 bytes */
 	    p = skb_put(skb,pkt_len);
 
 	    if (lp->shmem_length == IO_ONLY) {
@@ -1045,14 +1009,13 @@
 		*p++ = inb(EWRK3_DATA);
 	      }
 	    } else {
-	      memcpy(p, buf, pkt_len);
+	      memcpy_fromio(p, buf, pkt_len);
 	    }
 
 	    /* 
 	    ** Notify the upper protocol layers that there is another 
 	    ** packet to handle
 	    */
-	    
 	    skb->protocol=eth_type_trans(skb,dev);
 	    netif_rx(skb);
 
@@ -1066,15 +1029,15 @@
 		i = EWRK3_PKT_STAT_SZ;
 	      }
 	    }
-	    buf = skb->data;                  /* Look at the dest addr */
-	    if (buf[0] & 0x01) {              /* Multicast/Broadcast */
-	      if ((*(long *)&buf[0] == -1) && (*(short *)&buf[4] == -1)) {
+	    p = skb->data;                  /* Look at the dest addr */
+	    if (p[0] & 0x01) {              /* Multicast/Broadcast */
+	      if ((*(s32 *)&p[0] == -1) && (*(s16 *)&p[4] == -1)) {
 		lp->pktStats.broadcast++;
 	      } else {
 		lp->pktStats.multicast++;
 	      }
-	    } else if ((*(long *)&buf[0] == *(long *)&dev->dev_addr[0]) &&
-		       (*(short *)&buf[4] == *(short *)&dev->dev_addr[4])) {
+	    } else if ((*(s32 *)&p[0] == *(s32 *)&dev->dev_addr[0]) &&
+		       (*(s16 *)&p[4] == *(s16 *)&dev->dev_addr[4])) {
 	      lp->pktStats.unicast++;
 	    }
 
@@ -1117,23 +1080,23 @@
 ewrk3_tx(struct device *dev)
 {
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
-  int iobase = dev->base_addr;
-  unsigned char tx_status;
+  u_long iobase = dev->base_addr;
+  u_char tx_status;
 
   while ((tx_status = inb(EWRK3_TDQ)) > 0) {  /* Whilst there's old buffers */
-    if (tx_status & VSTS) {                   /* The status is valid */
-      if (tx_status & MAC_TXE) {
+    if (tx_status & T_VSTS) {                 /* The status is valid */
+      if (tx_status & T_TXE) {
 	lp->stats.tx_errors++;
-	if (tx_status & MAC_NCL)    lp->stats.tx_carrier_errors++;
-	if (tx_status & MAC_LCL)    lp->stats.tx_window_errors++;
-	if (tx_status & MAC_CTU) {
-	  if ((tx_status & MAC_COLL) ^ MAC_XUR) {
+	if (tx_status & T_NCL)    lp->stats.tx_carrier_errors++;
+	if (tx_status & T_LCL)    lp->stats.tx_window_errors++;
+	if (tx_status & T_CTU) {
+	  if ((tx_status & T_COLL) ^ T_XUR) {
 	    lp->pktStats.tx_underruns++;
 	  } else {
 	    lp->pktStats.excessive_underruns++;
 	  }
-	} else 	if (tx_status & MAC_COLL) {
-	  if ((tx_status & MAC_COLL) ^ MAC_XCOLL) {
+	} else 	if (tx_status & T_COLL) {
+	  if ((tx_status & T_COLL) ^ T_XCOLL) {
 	    lp->stats.collisions++;
 	  } else {
 	    lp->pktStats.excessive_collisions++;
@@ -1152,8 +1115,8 @@
 ewrk3_close(struct device *dev)
 {
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
-  int iobase = dev->base_addr;
-  unsigned char icr, csr;
+  u_long iobase = dev->base_addr;
+  u_char icr, csr;
 
   dev->start = 0;
   dev->tbusy = 1;
@@ -1203,39 +1166,32 @@
 
 /*
 ** Set or clear the multicast filter for this adaptor.
-** num_addrs == -1	Promiscuous mode, receive all packets
-** num_addrs == 0	Normal mode, clear multicast list
-** num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-** 			best-effort filtering.
 */
 static void
 set_multicast_list(struct device *dev)
 {
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
-  int iobase = dev->base_addr;
-  char *multicast_table;
-  unsigned char csr;
-
-  csr = inb(EWRK3_CSR);
-
-  if (lp->shmem_length == IO_ONLY) 
-  {
-    multicast_table = (char *) PAGE0_HTE;
-  } else {
-    multicast_table = (char *)(lp->shmem_base + PAGE0_HTE);
-  }
+  u_long iobase = dev->base_addr;
+  u_char csr;
+
+  if (irq2dev_map[dev->irq] != NULL) {
+    csr = inb(EWRK3_CSR);
+    
+    if (lp->shmem_length == IO_ONLY) {
+      lp->mctbl = (char *) PAGE0_HTE;
+    } else {
+      lp->mctbl = (char *)(lp->shmem_base + PAGE0_HTE);
+    }
 
-  if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) 
-  {
-    csr |= PME;
-    csr &= ~MCE;
-    outb(csr, EWRK3_CSR);
-    dev->flags|=IFF_PROMISC;
-  } else {                             /* set promiscuous mode */
-    SetMulticastFilter(dev, dev->mc_count, multicast_table);
-    csr &= ~PME;
-    csr |= MCE;
-    outb(csr, EWRK3_CSR);
+    csr &= ~(CSR_PME | CSR_MCE);
+    if (dev->flags & IFF_PROMISC) {         /* set promiscuous mode */
+      csr |= CSR_PME;
+      outb(csr, EWRK3_CSR);
+    } else {
+      SetMulticastFilter(dev);
+      csr |= CSR_MCE;
+      outb(csr, EWRK3_CSR);
+    }
   }
 }
 
@@ -1247,242 +1203,281 @@
 ** Note that when clearing the table, the broadcast bit must remain asserted
 ** to receive broadcast messages.
 */
-static void SetMulticastFilter(struct device *dev, int num_addrs, char *multicast_table)
+static void SetMulticastFilter(struct device *dev)
 {
-	struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
-	char *addrs;
-	struct dev_mc_list *dmi=dev->mc_list;
-	int i, iobase = dev->base_addr;
-	char j, bit, byte;
-	short *p = (short *) multicast_table;
-	u_short hashcode;
-	u_long crc, poly = CRC_POLYNOMIAL_LE;
+  struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
+  struct dev_mc_list *dmi=dev->mc_list;
+  u_long iobase = dev->base_addr;
+  int i;
+  char *addrs, j, bit, byte;
+  short *p = (short *) lp->mctbl;
+  u16 hashcode;
+  s32 crc, poly = CRC_POLYNOMIAL_LE;
+
+  while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
+
+  if (lp->shmem_length == IO_ONLY) {
+    outb(0, EWRK3_IOPR);
+    outw(EEPROM_OFFSET(lp->mctbl), EWRK3_PIR1);
+  } else {
+    outb(0, EWRK3_MPR);
+  }
 
-	while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
+  if (dev->flags & IFF_ALLMULTI) {
+    for (i=0; i<(HASH_TABLE_LEN >> 3); i++) {
+      if (lp->shmem_length == IO_ONLY) {
+	outb(0xff, EWRK3_DATA);
+      } else {                /* memset didn't work here */
+	writew(0xffff, p);
+	p++; i++;
+      }
+    }
+  } else {
+    /* Clear table except for broadcast bit */
+    if (lp->shmem_length == IO_ONLY) {
+      for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++) {
+	outb(0x00, EWRK3_DATA);
+      } 
+      outb(0x80, EWRK3_DATA); i++;           /* insert the broadcast bit */
+      for (; i<(HASH_TABLE_LEN >> 3); i++) {
+	outb(0x00, EWRK3_DATA);
+      } 
+    } else {
+      memset_io(lp->mctbl, 0, (HASH_TABLE_LEN >> 3));
+      writeb(0x80, (char *)(lp->mctbl + (HASH_TABLE_LEN >> 4) - 1));
+    }
 
-	if (lp->shmem_length == IO_ONLY) 
-	{
-		outb(0, EWRK3_IOPR);
-		outw((short)((long)multicast_table), EWRK3_PIR1);
-	} 
-	else
-	{
-		outb(0, EWRK3_MPR);
+    /* Update table */
+    for (i=0;i<dev->mc_count;i++) {          /* for each address in the list */
+      addrs=dmi->dmi_addr;
+      dmi=dmi->next;
+      if ((*addrs & 0x01) == 1) {            /* multicast address? */ 
+	crc = 0xffffffff;                    /* init CRC for each address */
+	for (byte=0;byte<ETH_ALEN;byte++) {  /* for each address byte */
+	                                     /* process each address bit */ 
+	  for (bit = *addrs++,j=0;j<8;j++, bit>>=1) {
+	    crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);
+	  }
 	}
+	hashcode = crc & ((1 << 9) - 1);     /* hashcode is 9 LSb of CRC */
 
-	if (num_addrs >= HASH_TABLE_LEN) 
-	{
-		for (i=0; i<(HASH_TABLE_LEN >> 3); i++) 
-		{
-			if (lp->shmem_length == IO_ONLY) 
-			{
-				outb(0xff, EWRK3_DATA);
-			}
-			else
-			{                /* memset didn't work here */
-				*p++ = 0xffff;
-				i++;
-			}
-		}
-	}
-	else
-	{
-		/* Clear table except for broadcast bit */
-		if (lp->shmem_length == IO_ONLY) 
-		{
-			for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++) 
-			{
-				outb(0x00, EWRK3_DATA);
-			} 
-			outb(0x80, EWRK3_DATA); i++;           /* insert the broadcast bit */
-			for (; i<(HASH_TABLE_LEN >> 3); i++) 
-			{
-				outb(0x00, EWRK3_DATA);
-			} 
-		}
-		else
-		{
-			memset(multicast_table, 0, (HASH_TABLE_LEN >> 3));
-			*(multicast_table + (HASH_TABLE_LEN >> 4) - 1) = 0x80;
-		}
+	byte = hashcode >> 3;                /* bit[3-8] -> byte in filter */
+	bit = 1 << (hashcode & 0x07);        /* bit[0-2] -> bit in byte */
 
-		/* Update table */
+	if (lp->shmem_length == IO_ONLY) {
+	  u_char tmp;
 
-		for (i=0;i<dev->mc_count;i++) 
-		{
-		        /* for each address in the list */
-		        addrs=dmi->dmi_addr;
-		        dmi=dmi->next;
-		        
-			if ((*addrs & 0x01) == 1) 
-			{            /* multicast address? */ 
-				crc = 0xffffffff;                    /* init CRC for each address */
-				for (byte=0;byte<ETH_ALEN;byte++) 
-				{  /* for each address byte */
-	                           /* process each address bit */ 
-					for (bit = *addrs++,j=0;j<8;j++, bit>>=1) 
-					{
-						crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);
-					}
-				}
-				hashcode = crc & ((1 << 9) - 1);     /* hashcode is 9 LSb of CRC */
-
-				byte = hashcode >> 3;                /* bit[3-8] -> byte in filter */
-				bit = 1 << (hashcode & 0x07);        /* bit[0-2] -> bit in byte */
-
-				if (lp->shmem_length == IO_ONLY) 
-				{
-					unsigned char tmp;
-
-					outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
-					tmp = inb(EWRK3_DATA);
-					tmp |= bit;
-					outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
-					outb(tmp, EWRK3_DATA); 
-				}
-				else
-				{
-					multicast_table[byte] |= bit;
-				}
-			}
-		}
+	  outw((short)((long)lp->mctbl) + byte, EWRK3_PIR1);
+	  tmp = inb(EWRK3_DATA);
+	  tmp |= bit;
+	  outw((short)((long)lp->mctbl) + byte, EWRK3_PIR1);
+	  outb(tmp, EWRK3_DATA); 
+	} else {
+	  writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
 	}
+      }
+    }
+  }
 
-	lp->lock = 0;                              /* Unlock the page register */
+  lp->lock = 0;                              /* Unlock the page register */
 
-	return;
+  return;
 }
 
-#ifndef MODULE
 /*
 ** ISA bus I/O device probe
 */
-static struct device *isa_probe(struct device *dev)
+static void isa_probe(struct device *dev, u_long ioaddr)
 {
-  int i, iobase, status;
-  unsigned long int tmp = mem_chkd;
+  int i = num_ewrk3s, maxSlots;
+  u_long iobase;
 
-  for (status = -ENODEV, iobase = EWRK3_IO_BASE,i = 0; 
-       i < 24;
-       iobase += EWRK3_IOP_INC, i++) {
-    if (tmp & 0x01) {
-      /* Anything else registered here? */
-      if (!check_region(iobase, EWRK3_TOTAL_SIZE)) {    
-	if (DevicePresent(iobase) == 0) {
-/*
-** Device found. Mark its (I/O) location for future reference. Only 24
-** EtherWORKS devices can exist between 0x100 and 0x3e0.
-*/
-	  request_region(iobase, EWRK3_IOP_INC, "ewrk3");
-	  if (num_ewrk3s > 0) {        /* only gets here in autoprobe */
-	    dev = alloc_device(dev, iobase);
-	  } else {
-	    if ((status = ewrk3_hw_init(dev, iobase)) == 0) {
-	      num_ewrk3s++;
-	    }
+  if (!ioaddr && autoprobed) return ;            /* Been here before ! */
+  if (ioaddr >= 0x400) return;                   /* Not ISA */
+
+  if (ioaddr == 0) {                     /* Autoprobing */
+    iobase = EWRK3_IO_BASE;              /* Get the first slot address */
+    maxSlots = 24;
+  } else {                               /* Probe a specific location */
+    iobase = ioaddr;
+    maxSlots = i + 1;
+  }
+
+  for (; (i<maxSlots) && (dev!=NULL);iobase+=EWRK3_IOP_INC, i++) {
+    if (!check_region(iobase, EWRK3_TOTAL_SIZE)) {    
+      if (DevicePresent(iobase) == 0) {
+	if ((dev = alloc_device(dev, iobase)) != NULL) {
+	  if (ewrk3_hw_init(dev, iobase) == 0) {
+	    num_ewrk3s++;
 	  }
 	  num_eth++;
-	} else {
-	  mem_chkd &= ~(0x01 << ((iobase - EWRK3_IO_BASE)/EWRK3_IOP_INC));
 	}
-      } else {
-	printk("%s: ewrk3_probe(): Detected a device already registered at 0x%02x\n", dev->name, iobase);
-	mem_chkd &= ~(0x01 << ((iobase - EWRK3_IO_BASE)/EWRK3_IOP_INC));
       }
+    } else if (autoprobed) {
+      printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
     }
-    tmp >>= 1;
   }
 
-  return dev;
+  return;
 }
 
 /*
 ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
 ** the motherboard.
 */
-static struct device *eisa_probe(struct device *dev)
+static void eisa_probe(struct device *dev, u_long ioaddr)
 {
-  int i, iobase = EWRK3_EISA_IO_PORTS;
-  int status;
-
-  iobase+=EISA_SLOT_INC;            /* get the first slot address */
-  for (status = -ENODEV, i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
-
-    /* Anything else registered here? */
-    if (!check_region(iobase, EWRK3_TOTAL_SIZE)) {
-      if (DevicePresent(iobase) == 0) {
-/*
-** Device found. Mark its slot location for future reference. Only 7
-** EtherWORKS devices can exist in EISA space....
-*/
-	mem_chkd |= (0x01 << (i + 24));
-	request_region(iobase, EWRK3_IOP_INC, "ewrk3");
-	if (num_ewrk3s > 0) {        /* only gets here in autoprobe */
-	  dev = alloc_device(dev, iobase);
-	} else {
-	  if ((status = ewrk3_hw_init(dev, iobase)) == 0) {
-	    num_ewrk3s++;
+  int i, maxSlots;
+  u_long iobase;
+  char name[EWRK3_STRLEN];
+
+  if (!ioaddr && autoprobed) return ;            /* Been here before ! */
+  if (ioaddr < 0x1000) return;                   /* Not EISA */
+
+  if (ioaddr == 0) {                     /* Autoprobing */
+    iobase = EISA_SLOT_INC;              /* Get the first slot address */
+    i = 1;
+    maxSlots = MAX_EISA_SLOTS;
+  } else {                               /* Probe a specific location */
+    iobase = ioaddr;
+    i = (ioaddr >> 12);
+    maxSlots = i + 1;
+  }
+
+  for (i=1; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) {
+    if (EISA_signature(name, EISA_ID) == 0) {
+      if (!check_region(iobase, EWRK3_TOTAL_SIZE)) {
+	if (DevicePresent(iobase) == 0) {
+	  if ((dev = alloc_device(dev, iobase)) != NULL) {
+	    if (ewrk3_hw_init(dev, iobase) == 0) {
+	      num_ewrk3s++;
+	    }
+	    num_eth++;
 	  }
 	}
-	num_eth++;
+      } else if (autoprobed) {
+	printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
       }
     }
   }
-  return dev;
+
+  return;
 }
 
 /*
 ** Allocate the device by pointing to the next available space in the
 ** device structure. Should one not be available, it is created.
 */
-static struct device *alloc_device(struct device *dev, int iobase)
+static struct device *alloc_device(struct device *dev, u_long iobase)
 {
+  int addAutoProbe = 0;
+  struct device *tmp = NULL, *ret;
+  int (*init)(struct device *) = NULL;
+
   /*
   ** Check the device structures for an end of list or unused device
   */
-  while (dev->next != NULL) {
-    if (dev->next->base_addr == 0xffe0) break;
-    dev = dev->next;         /* walk through eth device list */
-    num_eth++;               /* increment eth device number */
-  }
+  if (!loading_module) {
+    while (dev->next != NULL) {
+      if ((dev->base_addr == EWRK3_NDA) || (dev->base_addr == 0)) break;
+      dev = dev->next;                     /* walk through eth device list */
+      num_eth++;                           /* increment eth device number */
+    }
 
-  /*
-  ** If no more device structures, malloc one up. If memory could
-  ** not be allocated, print an error message.
-  */
-  if (dev->next == NULL) {
-    dev->next = (struct device *)kmalloc(sizeof(struct device) + 8,
-					 GFP_KERNEL);
-    if (dev->next == NULL) {
-      printk("eth%d: Device not initialised, insufficient memory\n",
-	     num_eth);
+    /*
+    ** If an autoprobe is requested for another device, we must re-insert
+    ** the request later in the list. Remember the current position first.
+    */
+    if ((dev->base_addr == 0) && (num_ewrk3s > 0)) {
+      addAutoProbe++;
+      tmp = dev->next;                     /* point to the next device */
+      init = dev->init;                    /* remember the probe function */
     }
-  }
+
+    /*
+    ** If at end of list and can't use current entry, malloc one up. 
+    ** If memory could not be allocated, print an error message.
+    */
+    if ((dev->next == NULL) &&  
+	!((dev->base_addr == EWRK3_NDA) || (dev->base_addr == 0))){
+      dev->next = (struct device *)kmalloc(sizeof(struct device) + 8,
+					   GFP_KERNEL);
+
+      dev = dev->next;                     /* point to the new device */
+      if (dev == NULL) {
+	printk("eth%d: Device not initialised, insufficient memory\n",
+	       num_eth);
+      } else {
+	/*
+	** If the memory was allocated, point to the new memory area
+	** and initialize it (name, I/O address, next device (NULL) and
+	** initialisation probe routine).
+	*/
+	dev->name = (char *)(dev + sizeof(struct device));
+	if (num_eth > 9999) {
+	  sprintf(dev->name,"eth????");    /* New device name */
+	} else {
+	  sprintf(dev->name,"eth%d", num_eth);/* New device name */
+	}
+	dev->base_addr = iobase;           /* assign the io address */
+	dev->next = NULL;                  /* mark the end of list */
+	dev->init = &ewrk3_probe;          /* initialisation routine */
+	num_ewrk3s++;
+      }
+    }
+    ret = dev;                             /* return current struct, or NULL */
   
-  /*
-  ** If the memory was allocated, point to the new memory area
-  ** and initialize it (name, I/O address, next device (NULL) and
-  ** initialisation probe routine).
-  */
-  if ((dev->next != NULL) &&
-      (num_eth > 0) && (num_eth < 9999)) {
-    dev = dev->next;                    /* point to the new device */
-    dev->name = (char *)(dev + sizeof(struct device));
-    sprintf(dev->name,"eth%d", num_eth);/* New device name */
-    dev->base_addr = iobase;            /* assign the io address */
-    dev->next = NULL;                   /* mark the end of list */
-    dev->init = &ewrk3_probe;           /* initialisation routine */
-    num_ewrk3s++;
+    /*
+    ** Now figure out what to do with the autoprobe that has to be inserted.
+    ** Firstly, search the (possibly altered) list for an empty space.
+    */
+    if (ret != NULL) {
+      if (addAutoProbe) {
+	for (;(tmp->next!=NULL) && (tmp->base_addr!=EWRK3_NDA); tmp=tmp->next);
+
+	/*
+	** If no more device structures and can't use the current one, malloc
+	** one up. If memory could not be allocated, print an error message.
+	*/
+	if ((tmp->next == NULL) && !(tmp->base_addr == EWRK3_NDA)) {
+	  tmp->next = (struct device *)kmalloc(sizeof(struct device) + 8,
+					       GFP_KERNEL);
+	  tmp = tmp->next;                     /* point to the new device */
+	  if (tmp == NULL) {
+	    printk("%s: Insufficient memory to extend the device list.\n", 
+		   dev->name);
+	  } else {
+	    /*
+	    ** If the memory was allocated, point to the new memory area
+	    ** and initialize it (name, I/O address, next device (NULL) and
+	    ** initialisation probe routine).
+	    */
+	    tmp->name = (char *)(tmp + sizeof(struct device));
+	    if (num_eth > 9999) {
+	      sprintf(tmp->name,"eth????");       /* New device name */
+	    } else {
+	      sprintf(tmp->name,"eth%d", num_eth);/* New device name */
+	    }
+	    tmp->base_addr = 0;                /* re-insert the io address */
+	    tmp->next = NULL;                  /* mark the end of list */
+	    tmp->init = init;                  /* initialisation routine */
+	  }
+	} else {                               /* structure already exists */
+	  tmp->base_addr = 0;                  /* re-insert the io address */
+	}
+      }
+    }
+  } else {
+    ret = dev;
   }
 
-  return dev;
+  return ret;
 }
-#endif    /* MODULE */
 
 /*
 ** Read the EWRK3 EEPROM using this routine
 */
-static int Read_EEPROM(short iobase, unsigned char eaddr)
+static int Read_EEPROM(u_long iobase, u_char eaddr)
 {
   int i;
 
@@ -1496,7 +1491,7 @@
 /*
 ** Write the EWRK3 EEPROM using this routine
 */
-static int Write_EEPROM(short data, short iobase, unsigned char eaddr)
+static int Write_EEPROM(short data, u_long iobase, u_char eaddr)
 {
   int i;
 
@@ -1517,8 +1512,8 @@
 */
 static void EthwrkSignature(char *name, char *eeprom_image)
 {
-  unsigned long i,j,k;
-  char signatures[][EWRK3_NAME_LENGTH] = EWRK3_SIGNATURE;
+  u_long i,j,k;
+  char *signatures[] = EWRK3_SIGNATURE;
 
   strcpy(name, "");
   for (i=0;*signatures[i] != '\0' && *name == '\0';i++) {
@@ -1530,9 +1525,9 @@
       }
     }
     if (k == strlen(signatures[i])) {
-      for (k=0; k<EWRK3_NAME_LENGTH; k++) {
+      for (k=0; k<EWRK3_STRLEN; k++) {
 	name[k] = eeprom_image[EEPROM_PNAME7 + k];
-	name[EWRK3_NAME_LENGTH] = '\0';
+	name[EWRK3_STRLEN] = '\0';
       }
     }
   }
@@ -1543,37 +1538,7 @@
 /*
 ** Look for a special sequence in the Ethernet station address PROM that
 ** is common across all EWRK3 products.
-*/
-
-static int DevicePresent(short iobase)
-{
-  static short fp=1,sigLength=0;
-  static char devSig[] = PROBE_SEQUENCE;
-  char data;
-  int i, j, status = 0;
-  static char asc2hex(char value);
-
-/* 
-** Convert the ascii signature to a hex equivalent & pack in place 
-*/
-  if (fp) {                               /* only do this once!... */
-    for (i=0,j=0;devSig[i] != '\0' && !status;i+=2,j++) {
-      if ((devSig[i]=asc2hex(devSig[i]))>=0) {
-	devSig[i]<<=4;
-	if((devSig[i+1]=asc2hex(devSig[i+1]))>=0){
-	  devSig[j]=devSig[i]+devSig[i+1];
-	} else {
-	  status= -1;
-	}
-      } else {
-	status= -1;
-      }
-    }
-    sigLength=j;
-    fp = 0;
-  }
-
-/* 
+** 
 ** Search the Ethernet address ROM for the signature. Since the ROM address
 ** counter can start at an arbitrary point, the search must include the entire
 ** probe sequence length plus the (length_of_the_signature - 1).
@@ -1581,44 +1546,76 @@
 ** PROM address counter is correctly positioned at the start of the
 ** ethernet address for later read out.
 */
-  if (!status) {
-    for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
-      data = inb(EWRK3_APROM);
-      if (devSig[j] == data) {    /* track signature */
-	j++;
-      } else {                    /* lost signature; begin search again */
+
+static int DevicePresent(u_long iobase)
+{
+  union {
+    struct {
+      u32 a;
+      u32 b;
+    } llsig;
+    char Sig[sizeof(u32) << 1];
+  } dev;
+  short sigLength;
+  char data;
+  int i, j, status = 0;
+
+  dev.llsig.a = ETH_PROM_SIG;
+  dev.llsig.b = ETH_PROM_SIG;
+  sigLength = sizeof(u32) << 1;
+
+  for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
+    data = inb(EWRK3_APROM);
+    if (dev.Sig[j] == data) {   /* track signature */
+      j++;
+    } else {                    /* lost signature; begin search again */
+      if (data == dev.Sig[0]) {
+	j=1;
+      } else {
 	j=0;
       }
     }
+  }
 
-    if (j!=sigLength) {
-      status = -ENODEV;           /* search failed */
-    }
+  if (j!=sigLength) {
+    status = -ENODEV;           /* search failed */
   }
 
   return status;
 }
 
-static unsigned char aprom_crc(struct device *dev, unsigned char *eeprom_image, char chipType)
+static u_char get_hw_addr(struct device *dev, u_char *eeprom_image, char chipType)
 {
-  long k;
-  unsigned short j,chksum;
-  unsigned char crc, lfsr, sd, status = 0;
-  int iobase = dev->base_addr;
+  int i, j, k;
+  u_short chksum;
+  u_char crc, lfsr, sd, status = 0;
+  u_long iobase = dev->base_addr;
+  u16 tmp;
 
   if (chipType == LeMAC2) {
     for (crc=0x6a, j=0; j<ETH_ALEN; j++) {
-      for (sd=inb(EWRK3_PAR0+j), k=0; k<8; k++, sd >>= 1) {
+      sd = dev->dev_addr[j] = eeprom_image[EEPROM_PADDR0 + j];
+      outb(dev->dev_addr[j], EWRK3_PAR0 + j);
+      for (k=0; k<8; k++, sd >>= 1) {
 	lfsr = ((((crc & 0x02) >> 1) ^ (crc & 0x01)) ^ (sd & 0x01)) << 7;
 	crc = (crc >> 1) + lfsr;
       }
     }
     if (crc != eeprom_image[EEPROM_PA_CRC]) status = -1;
   } else {
-    for (k=0,j=0;j<3;j++) {
+    for (i=0,k=0;i<ETH_ALEN;) {
       k <<= 1 ;
       if (k > 0xffff) k-=0xffff;
-      k += inw(EWRK3_PAR0 + (j<<1));
+
+      k += (u_char) (tmp = inb(EWRK3_APROM));
+      dev->dev_addr[i] = (u_char) tmp;
+      outb(dev->dev_addr[i], EWRK3_PAR0 + i);
+      i++;
+      k += (u_short) ((tmp = inb(EWRK3_APROM)) << 8);
+      dev->dev_addr[i] = (u_char) tmp;
+      outb(dev->dev_addr[i], EWRK3_PAR0 + i);
+      i++;
+
       if (k > 0xffff) k-=0xffff;
     }
     if (k == 0xffff) k=0;
@@ -1631,6 +1628,42 @@
 }
 
 /*
+** Look for a particular board name in the EISA configuration space
+*/
+static int EISA_signature(char *name, s32 eisa_id)
+{
+  u_long i;
+  char *signatures[] = EWRK3_SIGNATURE;
+  char ManCode[EWRK3_STRLEN];
+  union {
+    s32 ID;
+    char Id[4];
+  } Eisa;
+  int status = 0;
+
+  *name = '\0';
+  for (i=0; i<4; i++) {
+    Eisa.Id[i] = inb(eisa_id + i);
+  }
+
+  ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40);
+  ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40);
+  ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30);
+  ManCode[3]=((Eisa.Id[2]&0x0f)+0x30);
+  ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30);
+  ManCode[5]='\0';
+
+  for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) {
+    if (strstr(ManCode, signatures[i]) != NULL) {
+      strcpy(name,ManCode);
+      status = 1;
+    }
+  }
+
+  return status;                           /* return the device name string */
+}
+
+/*
 ** Perform IOCTL call functions here. Some are privileged operations and the
 ** effective uid is checked in those cases.
 */
@@ -1638,13 +1671,13 @@
 {
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
   struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_data;
-  int i, j, iobase = dev->base_addr, status = 0;
-  unsigned char csr;
+  u_long iobase = dev->base_addr;
+  int i, j, status = 0;
+  u_char csr;
   union {
-    unsigned char addr[HASH_TABLE_LEN * ETH_ALEN];
-    unsigned short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1];
+    u_char addr[HASH_TABLE_LEN * ETH_ALEN];
+    u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1];
   } tmp;
-  int err;
 
   switch(ioc->cmd) {
   case EWRK3_GET_HWADDR:             /* Get the hardware address */
@@ -1652,28 +1685,27 @@
       tmp.addr[i] = dev->dev_addr[i];
     }
     ioc->len = ETH_ALEN;
-
-    err = verify_area(VERIFY_WRITE, (void *)ioc->data, ETH_ALEN);
-    if (err) return err;
-    memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+    if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) {
+      memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+    }
 
     break;
   case EWRK3_SET_HWADDR:             /* Set the hardware address */
     if (suser()) {
-      csr = inb(EWRK3_CSR);
-      csr |= (TXD|RXD);
-      outb(csr, EWRK3_CSR);                  /* Disable the TX and RX */
+      if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN))) {
+	csr = inb(EWRK3_CSR);
+	csr |= (CSR_TXD|CSR_RXD);
+	outb(csr, EWRK3_CSR);                  /* Disable the TX and RX */
+
+	memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN);
+	for (i=0; i<ETH_ALEN; i++) {
+	  dev->dev_addr[i] = tmp.addr[i];
+	  outb(tmp.addr[i], EWRK3_PAR0 + i);
+	}
 
-      err = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN);
-      if (err) return err;
-      memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN);
-      for (i=0; i<ETH_ALEN; i++) {
-	dev->dev_addr[i] = tmp.addr[i];
-	outb(tmp.addr[i], EWRK3_PAR0 + i);
+	csr &= ~(CSR_TXD|CSR_RXD);             /* Enable the TX and RX */
+	outb(csr, EWRK3_CSR);
       }
-
-      csr &= ~(TXD|RXD);                       /* Enable the TX and RX */
-      outb(csr, EWRK3_CSR);
     } else {
       status = -EPERM;
     }
@@ -1682,8 +1714,8 @@
   case EWRK3_SET_PROM:               /* Set Promiscuous Mode */
     if (suser()) {
       csr = inb(EWRK3_CSR);
-      csr |= PME;
-      csr &= ~MCE;
+      csr |= CSR_PME;
+      csr &= ~CSR_MCE;
       outb(csr, EWRK3_CSR);
     } else {
       status = -EPERM;
@@ -1693,7 +1725,7 @@
   case EWRK3_CLR_PROM:               /* Clear Promiscuous Mode */
     if (suser()) {
       csr = inb(EWRK3_CSR);
-      csr &= ~PME;
+      csr &= ~CSR_PME;
       outb(csr, EWRK3_CSR);
     } else {
       status = -EPERM;
@@ -1701,41 +1733,34 @@
 
     break;
   case EWRK3_SAY_BOO:                /* Say "Boo!" to the kernel log file */
-    if(suser())
-    	printk("%s: Boo!\n", dev->name);
+    printk("%s: Boo!\n", dev->name);
 
     break;
   case EWRK3_GET_MCA:                /* Get the multicast address table */
-    err = verify_area(VERIFY_WRITE, (void *)ioc->data, HASH_TABLE_LEN >> 3);
-    if (err) return err;
-
-    while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
-    if (lp->shmem_length == IO_ONLY) {
-      outb(0, EWRK3_IOPR);
-      outw(PAGE0_HTE, EWRK3_PIR1);
-      for (i=0; i<(HASH_TABLE_LEN >> 3); i++) {
-	tmp.addr[i] = inb(EWRK3_DATA);
+    if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
+      while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
+      if (lp->shmem_length == IO_ONLY) {
+	outb(0, EWRK3_IOPR);
+	outw(PAGE0_HTE, EWRK3_PIR1);
+	for (i=0; i<(HASH_TABLE_LEN >> 3); i++) {
+	  tmp.addr[i] = inb(EWRK3_DATA);
+	}
+      } else {
+	outb(0, EWRK3_MPR);
+	memcpy_fromio(tmp.addr, (char *)(lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3));
       }
-    } else {
-      outb(0, EWRK3_MPR);
-      memcpy(tmp.addr, (char *)(lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3));
+      ioc->len = (HASH_TABLE_LEN >> 3);
+      memcpy_tofs(ioc->data, tmp.addr, ioc->len); 
     }
-    ioc->len = (HASH_TABLE_LEN >> 3);
-    memcpy_tofs(ioc->data, tmp.addr, ioc->len); 
     lp->lock = 0;                               /* Unlock the page register */
 
     break;
-    
-#if 0    
   case EWRK3_SET_MCA:                /* Set a multicast address */
     if (suser()) {
-      err = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN * ioc->len);
-      if (err) return err;
-
-      if (ioc->len != HASH_TABLE_LEN) {         /* MCA changes */
+      if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) {
 	memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
+	set_multicast_list(dev);
       }
-      set_multicast_list(dev, ioc->len, tmp.addr);
     } else {
       status = -EPERM;
     }
@@ -1743,7 +1768,7 @@
     break;
   case EWRK3_CLR_MCA:                /* Clear all multicast addresses */
     if (suser()) {
-      set_multicast_list(dev, 0, NULL);
+      set_multicast_list(dev);
     } else {
       status = -EPERM;
     }
@@ -1752,22 +1777,20 @@
   case EWRK3_MCA_EN:                 /* Enable multicast addressing */
     if (suser()) {
       csr = inb(EWRK3_CSR);
-      csr |= MCE;
-      csr &= ~PME;
+      csr |= CSR_MCE;
+      csr &= ~CSR_PME;
       outb(csr, EWRK3_CSR);
     } else {
       status = -EPERM;
     }
 
     break;
-#endif
   case EWRK3_GET_STATS:              /* Get the driver statistics */
-    err = verify_area(VERIFY_WRITE, (void *)ioc->data, sizeof(lp->pktStats));
-    if (err) return err;
-
     cli();
-    memcpy_tofs(ioc->data, &lp->pktStats, sizeof(lp->pktStats)); 
-    ioc->len = EWRK3_PKT_STAT_SZ;
+    ioc->len = sizeof(lp->pktStats);
+    if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
+      memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); 
+    }
     sti();
 
     break;
@@ -1782,20 +1805,19 @@
 
     break;
   case EWRK3_GET_CSR:                /* Get the CSR Register contents */
-    err = verify_area(VERIFY_WRITE, (void *)ioc->data, 1);
-    if (err) return err;
-
     tmp.addr[0] = inb(EWRK3_CSR);
-    memcpy_tofs(ioc->data, tmp.addr, 1);
+    ioc->len = 1;
+    if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
+      memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+    }
 
     break;
   case EWRK3_SET_CSR:                /* Set the CSR Register contents */
-    err = verify_area(VERIFY_READ, (void *)ioc->data, 1);
-    if (err) return err;
-
     if (suser()) {
-      memcpy_fromfs(tmp.addr, ioc->data, 1);
-      outb(tmp.addr[0], EWRK3_CSR);
+      if (!(status=verify_area(VERIFY_READ, ioc->data, 1))) {
+	memcpy_fromfs(tmp.addr, ioc->data, 1);
+	outb(tmp.addr[0], EWRK3_CSR);
+      }
     } else {
       status = -EPERM;
     }
@@ -1803,9 +1825,6 @@
     break;
   case EWRK3_GET_EEPROM:             /* Get the EEPROM contents */
     if (suser()) {
-      err = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len);
-      if (err) return err;
-
       for (i=0; i<(EEPROM_MAX>>1); i++) {
 	tmp.val[i] = (short)Read_EEPROM(iobase, i);
       }
@@ -1815,7 +1834,9 @@
 	tmp.addr[i++] = inb(EWRK3_PAR0 + j);
       }
       ioc->len = EEPROM_MAX + 1 + ETH_ALEN;
-      memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+      if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
+	memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+      }
     } else {
       status = -EPERM;
     }
@@ -1823,12 +1844,11 @@
     break;
   case EWRK3_SET_EEPROM:             /* Set the EEPROM contents */
     if (suser()) {
-      err = verify_area(VERIFY_READ, (void *)ioc->data, EEPROM_MAX);
-      if (err) return err;
-
-      memcpy_fromfs(tmp.addr, ioc->data, EEPROM_MAX);
-      for (i=0; i<(EEPROM_MAX>>1); i++) {
-	Write_EEPROM(tmp.val[i], iobase, i);
+      if (!(status=verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) {
+	memcpy_fromfs(tmp.addr, ioc->data, EEPROM_MAX);
+	for (i=0; i<(EEPROM_MAX>>1); i++) {
+	  Write_EEPROM(tmp.val[i], iobase, i);
+	}
       }
     } else {
       status = -EPERM;
@@ -1836,11 +1856,11 @@
 
     break;
   case EWRK3_GET_CMR:                /* Get the CMR Register contents */
-    err = verify_area(VERIFY_WRITE, (void *)ioc->data, 1);
-    if (err) return err;
-
     tmp.addr[0] = inb(EWRK3_CMR);
-    memcpy_tofs(ioc->data, tmp.addr, 1);
+    ioc->len = 1;
+    if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
+      memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+    }
 
     break;
   case EWRK3_SET_TX_CUT_THRU:        /* Set TX cut through mode */
@@ -1866,29 +1886,12 @@
   return status;
 }
 
-static char asc2hex(char value)
-{
-  value -= 0x30;                  /* normalise to 0..9 range */
-  if (value >= 0) {
-    if (value > 9) {              /* but may not be 10..15 */
-      value &= 0x1f;              /* make A..F & a..f be the same */
-      value -= 0x07;              /* normalise to 10..15 range */
-      if ((value < 0x0a) || (value > 0x0f)) { /* if outside range then... */
-	value = -1;               /* ...signal error */
-      }
-    }
-  } else {                        /* outside 0..9 range... */
-    value = -1;                   /* ...signal error */
-  }
-  return value;                   /* return hex char or error */
-}
-
 #ifdef MODULE
 static char devicename[9] = { 0, };
 static struct device thisEthwrk = {
-  devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+  devicename, /* device name is inserted by /linux/drivers/net/net_init.c */
   0, 0, 0, 0,
-  0x300, 5,  /* I/O address, IRQ */
+  0x300, 5,   /* I/O address, IRQ */
   0, 0, 0, NULL, ewrk3_probe };
 	
 static int io=0x300;	/* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
@@ -1907,10 +1910,15 @@
 void
 cleanup_module(void)
 {
-    release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE);
-    unregister_netdev(&thisEthwrk);
+  release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE);
+
+  if (thisEthwrk.priv) {
     kfree(thisEthwrk.priv);
     thisEthwrk.priv = NULL;
+  }
+  thisEthwrk.irq = 0;
+
+  unregister_netdev(&thisEthwrk);
 }
 #endif /* MODULE */
 
@@ -1922,6 +1930,4 @@
  *  module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c ewrk3.c"
  * End:
  */
-
-
 
diff -u --recursive --new-file v1.3.52/linux/drivers/net/ewrk3.h linux/drivers/net/ewrk3.h
--- v1.3.52/linux/drivers/net/ewrk3.h	Sun Nov 20 21:50:46 1994
+++ linux/drivers/net/ewrk3.h	Sat Dec 30 15:57:20 1995
@@ -61,43 +61,43 @@
 /*
 ** Control and Status Register bit definitions (EWRK3_CSR)
 */
-#define RA		0x80	    /* Runt Accept */
-#define PME		0x40	    /* Promiscuous Mode Enable */
-#define MCE		0x20	    /* Multicast Enable */ 
-#define TNE		0x08	    /* TX Done Queue Not Empty */
-#define RNE		0x04	    /* RX Queue Not Empty */
-#define TXD		0x02	    /* TX Disable */
-#define RXD		0x01	    /* RX Disable */
+#define CSR_RA		0x80	    /* Runt Accept */
+#define CSR_PME		0x40	    /* Promiscuous Mode Enable */
+#define CSR_MCE		0x20	    /* Multicast Enable */ 
+#define CSR_TNE		0x08	    /* TX Done Queue Not Empty */
+#define CSR_RNE		0x04	    /* RX Queue Not Empty */
+#define CSR_TXD		0x02	    /* TX Disable */
+#define CSR_RXD		0x01	    /* RX Disable */
 
 /*
 ** Control Register bit definitions (EWRK3_CR)
 */
-#define APD		0x80	/* Auto Port Disable */
-#define PSEL		0x40	/* Port Select (0->TP port) */
-#define LBCK		0x20	/* LoopBaCK enable */
-#define FDUP		0x10	/* Full DUPlex enable */
-#define FBUS		0x08	/* Fast BUS enable (ISA clk > 8.33MHz) */
-#define EN_16		0x04	/* ENable 16 bit memory accesses */
-#define LED		0x02	/* LED (1-> turn on) */
+#define CR_APD		0x80	/* Auto Port Disable */
+#define CR_PSEL		0x40	/* Port Select (0->TP port) */
+#define CR_LBCK		0x20	/* LoopBaCK enable */
+#define CR_FDUP		0x10	/* Full DUPlex enable */
+#define CR_FBUS		0x08	/* Fast BUS enable (ISA clk > 8.33MHz) */
+#define CR_EN_16	0x04	/* ENable 16 bit memory accesses */
+#define CR_LED		0x02	/* LED (1-> turn on) */
 
 /*
 ** Interrupt Control Register bit definitions (EWRK3_ICR)
 */
-#define IE		0x80	/* Interrupt Enable */
-#define IS		0x60	/* Interrupt Selected */
-#define TNEM		0x08	/* TNE Mask (0->mask) */
-#define RNEM		0x04	/* RNE Mask (0->mask) */
-#define TXDM		0x02	/* TXD Mask (0->mask) */
-#define RXDM		0x01	/* RXD Mask (0->mask) */
+#define ICR_IE		0x80	/* Interrupt Enable */
+#define ICR_IS		0x60	/* Interrupt Selected */
+#define ICR_TNEM	0x08	/* TNE Mask (0->mask) */
+#define ICR_RNEM	0x04	/* RNE Mask (0->mask) */
+#define ICR_TXDM	0x02	/* TXD Mask (0->mask) */
+#define ICR_RXDM	0x01	/* RXD Mask (0->mask) */
 
 /*
 ** Transmit Status Register bit definitions (EWRK3_TSR)
 */
-#define NCL		0x80	/* No Carrier Loopback */
-#define ID		0x40	/* Initially Deferred */
-#define LCL		0x20	/* Late CoLlision */
-#define ECL		0x10	/* Excessive CoLlisions */
-#define RCNTR		0x0f	/* Retries CouNTeR */
+#define TSR_NCL		0x80	/* No Carrier Loopback */
+#define TSR_ID		0x40	/* Initially Deferred */
+#define TSR_LCL		0x20	/* Late CoLlision */
+#define TSR_ECL		0x10	/* Excessive CoLlisions */
+#define TSR_RCNTR	0x0f	/* Retries CouNTeR */
 
 /*
 ** I/O Page Register bit definitions (EWRK3_IOPR)
@@ -111,67 +111,68 @@
 /*
 ** I/O Base Register bit definitions (EWRK3_IOBR)
 */
-#define EISA		0x20	/* Enable EISA ID and Control Registers */
-#define IOB		0x1f	/* Compare bits for I/O Base Address */
+#define EISA_REGS_EN	0x20	/* Enable EISA ID and Control Registers */
+#define EISA_IOB        0x1f	/* Compare bits for I/O Base Address */
 
 /*
-** I/O Configuration/Management Register bit definitions (EWRK3_CMR)
+** I/O Congiguration/Management Register bit definitions (EWRK3_CMR)
 */
-#define RA              0x80    /* Read Ahead */
-#define WB              0x40    /* Write Behind */
-#define LINK		0x20	/* 0->TP */
-#define POLARITY	0x10	/* Informational */
-#define NO_EEPROM	0x0c	/* NO_EEPROM<1:0> pin status */
-#define HS	        0x08	/* Hard Strapped pin status (LeMAC2) */
-#define PNP             0x04    /* Plug 'n Play */
-#define DRAM		0x02	/* 0-> 1DRAM, 1-> 2 DRAM on board */
-#define _0WS            0x01    /* Zero Wait State */
+#define CMR_RA          0x80    /* Read Ahead */
+#define CMR_WB          0x40    /* Write Behind */
+#define CMR_LINK        0x20	/* 0->TP */
+#define CMR_POLARITY    0x10	/* Informational */
+#define CMR_NO_EEPROM	0x0c	/* NO_EEPROM<1:0> pin status */
+#define CMR_HS          0x08	/* Hard Strapped pin status (LeMAC2) */
+#define CMR_PNP         0x04    /* Plug 'n Play */
+#define CMR_DRAM        0x02	/* 0-> 1DRAM, 1-> 2 DRAM on board */
+#define CMR_0WS         0x01    /* Zero Wait State */
 
 /* 
 ** MAC Receive Status Register bit definitions
 */
 
-#define ROK     	0x80 	/* Receive OK summary */
-#define IAM     	0x10 	/* Individual Address Match */
-#define MCM     	0x08 	/* MultiCast Match */
-#define DBE     	0x04 	/* Dribble Bit Error */
-#define CRC     	0x02 	/* CRC error */
-#define PLL     	0x01 	/* Phase Lock Lost */
+#define R_ROK     	0x80 	/* Receive OK summary */
+#define R_IAM     	0x10 	/* Individual Address Match */
+#define R_MCM     	0x08 	/* MultiCast Match */
+#define R_DBE     	0x04 	/* Dribble Bit Error */
+#define R_CRC     	0x02 	/* CRC error */
+#define R_PLL     	0x01 	/* Phase Lock Lost */
 
 /* 
 ** MAC Transmit Control Register bit definitions
 */
 
-#define SQEE    	0x40 	/* SQE Enable - look for heartbeat  */
-#define SED     	0x20 	/* Stop when Error Detected */
-#define QMODE     	0x10 	/* Q_MODE */
-#define LAB             0x08 	/* Less Aggressive Backoff */
-#define PAD     	0x04 	/* PAD Runt Packets */
-#define IFC     	0x02 	/* Insert Frame Check */
-#define ISA     	0x01 	/* Insert Source Address */
+#define TCR_SQEE    	0x40 	/* SQE Enable - look for heartbeat  */
+#define TCR_SED     	0x20 	/* Stop when Error Detected */
+#define TCR_QMODE     	0x10 	/* Q_MODE */
+#define TCR_LAB         0x08 	/* Less Aggressive Backoff */
+#define TCR_PAD     	0x04 	/* PAD Runt Packets */
+#define TCR_IFC     	0x02 	/* Insert Frame Check */
+#define TCR_ISA     	0x01 	/* Insert Source Address */
 
 /* 
 ** MAC Transmit Status Register bit definitions
 */
 
-#define VSTS    	0x80 	/* Valid STatuS */
-#define MAC_CTU     	0x40 	/* Cut Through Used */
-#define MAC_SQE     	0x20 	/* Signal Quality Error */
-#define MAC_NCL     	0x10 	/* No Carrier Loopback */
-#define MAC_LCL         0x08 	/* Late Collision */
-#define MAC_ID      	0x04 	/* Initially Deferred */
-#define MAC_COLL     	0x03 	/* COLLision status */
-#define MAC_XCOLL       0x03    /* Excessive Collisions */
-#define MAC_MCOLL       0x02    /* Multiple Collisions */
-#define MAC_OCOLL       0x01    /* One Collision */
-#define MAC_NOCOLL      0x00    /* No Collisions */
-#define MAC_XUR         0x03    /* Excessive Underruns */
-#define MAC_TXE         0x7f    /* TX Errors */
+#define T_VSTS    	0x80 	/* Valid STatuS */
+#define T_CTU     	0x40 	/* Cut Through Used */
+#define T_SQE     	0x20 	/* Signal Quality Error */
+#define T_NCL     	0x10 	/* No Carrier Loopback */
+#define T_LCL           0x08 	/* Late Collision */
+#define T_ID      	0x04 	/* Initially Deferred */
+#define T_COLL     	0x03 	/* COLLision status */
+#define T_XCOLL         0x03    /* Excessive Collisions */
+#define T_MCOLL         0x02    /* Multiple Collisions */
+#define T_OCOLL         0x01    /* One Collision */
+#define T_NOCOLL        0x00    /* No Collisions */
+#define T_XUR           0x03    /* Excessive Underruns */
+#define T_TXE           0x7f    /* TX Errors */
 
 /* 
 ** EISA Configuration Register bit definitions 
 */
 
+#define EISA_ID       iobase + 0x0c80  /* EISA ID Registers */ 
 #define EISA_ID0      iobase + 0x0c80  /* EISA ID Register 0 */ 
 #define EISA_ID1      iobase + 0x0c81  /* EISA ID Register 1 */ 
 #define EISA_ID2      iobase + 0x0c82  /* EISA ID Register 2 */ 
@@ -282,6 +283,8 @@
 
 #define MASK_INTERRUPTS   1
 #define UNMASK_INTERRUPTS 0
+
+#define EEPROM_OFFSET(a) ((u_short)((u_long)(a)))
 
 /*
 ** Include the IOCTL stuff
diff -u --recursive --new-file v1.3.52/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v1.3.52/linux/drivers/net/lance.c	Mon Nov 27 12:48:30 1995
+++ linux/drivers/net/lance.c	Sat Dec 30 21:00:40 1995
@@ -569,7 +569,7 @@
 	}
 
 	/* We used to allocate DMA here, but that was silly.
-	   DMA lines can't be shared!  We now permanently snarf them. */
+	   DMA lines can't be shared!  We now permanently allocate them. */
 
 	irq2dev_map[dev->irq] = dev;
 
diff -u --recursive --new-file v1.3.52/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v1.3.52/linux/drivers/net/net_init.c	Sat Dec 30 15:50:53 1995
+++ linux/drivers/net/net_init.c	Sun Dec 31 14:32:45 1995
@@ -237,7 +237,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_MODULES
 int register_netdev(struct device *dev)
 {
 	struct device *d = dev_base;
@@ -357,8 +356,6 @@
 
 	restore_flags(flags);
 }
-#endif		/* CONFIG_MODULES */
-
 
 
 /*
diff -u --recursive --new-file v1.3.52/linux/drivers/net/pi2.c linux/drivers/net/pi2.c
--- v1.3.52/linux/drivers/net/pi2.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/pi2.c	Sat Dec 30 21:00:40 1995
@@ -1407,7 +1407,7 @@
 	}
 
 	/* Grab the region */
-	snarf_region(ioaddr & 0x3f0, PI_TOTAL_SIZE);
+	request_region(ioaddr & 0x3f0, PI_TOTAL_SIZE, "pi2" );
 
 
     }				/* Only for A port */
diff -u --recursive --new-file v1.3.52/linux/drivers/net/pt.c linux/drivers/net/pt.c
--- v1.3.52/linux/drivers/net/pt.c	Wed Dec 27 09:12:13 1995
+++ linux/drivers/net/pt.c	Sat Dec 30 21:00:40 1995
@@ -877,7 +877,7 @@
         }
 
         /* Grab the region */
-        snarf_region(ioaddr & 0x3f0, PT_TOTAL_SIZE);
+        request_region(ioaddr & 0x3f0, PT_TOTAL_SIZE, "pt" );
     } /* A port */
     dev->open = pt_open;
     dev->stop = pt_close;
diff -u --recursive --new-file v1.3.52/linux/drivers/net/skeleton.c linux/drivers/net/skeleton.c
--- v1.3.52/linux/drivers/net/skeleton.c	Sat Nov 25 19:04:46 1995
+++ linux/drivers/net/skeleton.c	Sat Dec 30 21:00:40 1995
@@ -1,43 +1,43 @@
-/* skeleton.c: A network driver outline for linux. */
-/*
-	Written 1993-94 by Donald Becker.
-
-	Copyright 1993 United States Government as represented by the
-	Director, National Security Agency.
-
-	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
-
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-
-	This file is an outline for writing a network device driver for the
-	the Linux operating system.
-
-	To write (or understand) a driver, have a look at the "loopback.c" file to
-	get a feel of what is going on, and then use the code below as a skeleton
-	for the new driver.
-
-*/
+/* skeleton.c: A network driver outline for linux.
+ *
+ *	Written 1993-94 by Donald Becker.
+ *
+ *	Copyright 1993 United States Government as represented by the
+ *	Director, National Security Agency.
+ *
+ *	This software may be used and distributed according to the terms
+ *	of the GNU Public License, incorporated herein by reference.
+ *
+ *	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+ *	Center of Excellence in Space Data and Information Sciences
+ *	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+ *
+ *	This file is an outline for writing a network device driver for the
+ *	the Linux operating system.
+ *
+ *	To write (or understand) a driver, have a look at the "loopback.c" file to
+ *	get a feel of what is going on, and then use the code below as a skeleton
+ *	for the new driver.
+ *
+ */
 
 static const char *version =
 	"skeleton.c:v1.51 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 /*
-  Sources:
-	List your sources of programming information to document that
-	the driver is your own creation, and give due credit to others
-	that contributed to the work.  Remember that GNU project code
-	cannot use proprietary or trade secret information.	 Interface
-	definitions are generally considered non-copyrightable to the
-	extent that the same names and structures must be used to be
-	compatible.
-
-	Finally, keep in mind that the Linux kernel is has an API, not
-	ABI.  Proprietary object-code-only distributions are not permitted
-	under the GPL.
-*/
+ *  Sources:
+ *	List your sources of programming information to document that
+ *	the driver is your own creation, and give due credit to others
+ *	that contributed to the work. Remember that GNU project code
+ *	cannot use proprietary or trade secret information. Interface
+ *	definitions are generally considered non-copyrightable to the
+ *	extent that the same names and structures must be used to be
+ *	compatible.
+ *
+ *	Finally, keep in mind that the Linux kernel is has an API, not
+ *	ABI. Proprietary object-code-only distributions are not permitted
+ *	under the GPL.
+ */
 
 #include <linux/module.h>
 
@@ -61,12 +61,14 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-/* The name of the card. Is used for messages and in the requests for
+/*
+ * The name of the card. Is used for messages and in the requests for
  * io regions, irqs and dma channels
  */
 static const char* cardname = "netcard";
 
 /* First, a few definitions that the brave might change. */
+
 /* A zero-terminated list of I/O addresses to be probed. */
 static unsigned int netcard_portlist[] =
    { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
@@ -83,7 +85,7 @@
 /* Information that need to be kept for each board. */
 struct net_local {
 	struct enet_statistics stats;
-	long open_time;				/* Useless example local info. */
+	long open_time;			/* Useless example local info. */
 };
 
 /* The station (ethernet) address prefix, used for IDing the board. */
@@ -109,16 +111,18 @@
 extern void	hardware_send_packet(short ioaddr, char *buf, int length);
 extern void chipset_init(struct device *dev, int startp);
 
-
-/* Check for a network adaptor of this type, and return '0' iff one exists.
-   If dev->base_addr == 0, probe all likely locations.
-   If dev->base_addr == 1, always return failure.
-   If dev->base_addr == 2, allocate space for the device and return success
-   (detachable devices only).
-   */
+/*
+ * Check for a network adaptor of this type, and return '0' iff one exists.
+ * If dev->base_addr == 0, probe all likely locations.
+ * If dev->base_addr == 1, always return failure.
+ * If dev->base_addr == 2, allocate space for the device and return success
+ * (detachable devices only).
+ */
 #ifdef HAVE_DEVLIST
-/* Support for a alternate probe manager, which will eliminate the
-   boilerplate below. */
+/*
+ * Support for a alternate probe manager,
+ * which will eliminate the boilerplate below.
+ */
 struct netdev_entry netcard_drv =
 {cardname, netcard_probe1, NETCARD_IO_EXTENT, netcard_portlist};
 #else
@@ -128,9 +132,9 @@
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
 
-	if (base_addr > 0x1ff)		/* Check a single specified location. */
+	if (base_addr > 0x1ff)    /* Check a single specified location. */
 		return netcard_probe1(dev, base_addr);
-	else if (base_addr != 0)	/* Don't probe at all. */
+	else if (base_addr != 0)  /* Don't probe at all. */
 		return -ENXIO;
 
 	for (i = 0; netcard_portlist[i]; i++) {
@@ -145,18 +149,21 @@
 }
 #endif
 
-/* This is the real probe routine.  Linux has a history of friendly device
-   probes on the ISA bus.  A good device probes avoids doing writes, and
-   verifies that the correct device exists and functions.  */
-
+/*
+ * This is the real probe routine. Linux has a history of friendly device
+ * probes on the ISA bus. A good device probes avoids doing writes, and
+ * verifies that the correct device exists and functions.
+ */
 static int netcard_probe1(struct device *dev, int ioaddr)
 {
 	static unsigned version_printed = 0;
 	int i;
 
-	/* For ethernet adaptors the first three octets of the station address 
-	   contains the manufacturer's unique code.  That might be a good probe
-	   method. Ideally you would add additional checks.  */ 
+	/*
+	 * For ethernet adaptors the first three octets of the station address 
+	 * contains the manufacturer's unique code. That might be a good probe
+	 * method. Ideally you would add additional checks.
+	 */ 
 	if (inb(ioaddr + 0) != SA_ADDR0
 		||	 inb(ioaddr + 1) != SA_ADDR1
 		||	 inb(ioaddr + 2) != SA_ADDR2) {
@@ -165,7 +172,8 @@
 
 	/* Allocate a new 'dev' if needed. */
 	if (dev == NULL) {
-		/* Don't allocate the private data here, it is done later
+		/*
+		 * Don't allocate the private data here, it is done later
 		 * This makes it easier to free the memory when this driver
 		 * is used as a module.
 		 */
@@ -187,14 +195,16 @@
 		printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
 
 #ifdef jumpered_interrupts
-	/* If this board has jumpered interrupts, snarf the interrupt vector
-	   now.	 There is no point in waiting since no other device can use
-	   the interrupt, and this marks the irq as busy.
-	   Jumpered interrupts are typically not reported by the boards, and
-	   we must used autoIRQ to find them. */
+	/*
+	 * If this board has jumpered interrupts, allocate the interrupt
+	 * vector now. There is no point in waiting since no other device
+	 * can use the interrupt, and this marks the irq as busy. Jumpered
+	 * interrupts are typically not reported by the boards, and we must
+	 * used autoIRQ to find them.
+	 */
 
 	if (dev->irq == -1)
-		;			/* Do nothing: a user-level program will set it. */
+		;	/* Do nothing: a user-level program will set it. */
 	else if (dev->irq < 2) {	/* "Auto-IRQ" */
 		autoirq_setup(0);
 		/* Trigger an interrupt here. */
@@ -203,8 +213,9 @@
 		if (net_debug >= 2)
 			printk(" autoirq is %d", dev->irq);
 	} else if (dev->irq == 2)
-		/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
-		 * or don't know which one to set.
+		/*
+		 * Fixup for users that don't know that IRQ 2 is really
+		 * IRQ9, or don't know which one to set.
 		 */
 		dev->irq = 9;
 
@@ -218,8 +229,10 @@
 	}
 #endif	/* jumpered interrupt */
 #ifdef jumpered_dma
-	/* If we use a jumpered DMA channel, that should be probed for and
-	   allocated here as well.  See lance.c for an example. */
+	/*
+	 * If we use a jumpered DMA channel, that should be probed for and
+	 * allocated here as well. See lance.c for an example.
+	 */
 	if (dev->dma == 0) {
 		if (request_dma(dev->dma, cardname)) {
 			printk("DMA %d allocation failed.\n", dev->dma);
@@ -237,7 +250,10 @@
 		/* Re-read the DMA status registers. */
 		new_dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) |
 			(inb(DMA2_STAT_REG) & 0xf0);
-		/* Eliminate the old and floating requests and DMA4, the cascade. */
+		/*
+		 * Eliminate the old and floating requests,
+		 * and DMA4 the cascade.
+		 */
 		new_dma_status ^= dma_status;
 		new_dma_status &= ~0x10;
 		for (i = 7; i > 0; i--)
@@ -280,34 +296,37 @@
 	return 0;
 }
 
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
-
-   This routine should set everything up anew at each open, even
-   registers that "should" only need to be set once at boot, so that
-   there is non-reboot way to recover if something goes wrong.
-   */
+/*
+ * Open/initialize the board. This is called (in the current kernel)
+ * sometime after booting when the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+ * registers that "should" only need to be set once at boot, so that
+ * there is non-reboot way to recover if something goes wrong.
+ */
 static int
 net_open(struct device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
-
-	/* This is used if the interrupt line can turned off (shared).
-	   See 3c503.c for an example of selecting the IRQ at config-time. */
+	/*
+	 * This is used if the interrupt line can turned off (shared).
+	 * See 3c503.c for an example of selecting the IRQ at config-time.
+	 */
 	if (request_irq(dev->irq, &net_interrupt, 0, cardname)) {
 		return -EAGAIN;
 	}
-
-	/* Always snarf the DMA channel after the IRQ, and clean up on failure. */
+	/*
+	 * Always allocate the DMA channel after the IRQ,
+	 * and clean up on failure.
+	 */
 	if (request_dma(dev->dma, cardname)) {
 		free_irq(dev->irq);
 		return -EAGAIN;
 	}
 	irq2dev_map[dev->irq] = dev;
 
-	/* Reset the hardware here.  Don't forget to set the station address. */
+	/* Reset the hardware here. Don't forget to set the station address. */
 	/*chipset_init(dev, 1);*/
 	outb(0x00, ioaddr);
 	lp->open_time = jiffies;
@@ -328,8 +347,10 @@
 	int ioaddr = dev->base_addr;
 
 	if (dev->tbusy) {
-		/* If we get here, some higher level has decided we are broken.
-		   There should really be a "kick me" function call instead. */
+		/*
+		 * If we get here, some higher level has decided we are broken.
+		 * There should really be a "kick me" function call instead.
+		 */
 		int tickssofar = jiffies - dev->trans_start;
 		if (tickssofar < 5)
 			return 1;
@@ -340,17 +361,19 @@
 		dev->tbusy=0;
 		dev->trans_start = jiffies;
 	}
-
-	/* If some higher layer thinks we've missed an tx-done interrupt
-	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
-	   itself. */
+	/*
+	 * If some higher layer thinks we've missed an tx-done interrupt
+	 * we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+	 * itself.
+	 */
 	if (skb == NULL) {
 		dev_tint(dev);
 		return 0;
 	}
-
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+	/*
+	 * Block a timer-based transmit from overlapping. This could better be
+	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+	 */
 	if (set_bit(0, (void*)&dev->tbusy) != 0)
 		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
 	else {
@@ -368,9 +391,11 @@
 
 	return 0;
 }
-
-/* The typical workload of the driver:
-   Handle the network interface interrupts. */
+
+/*
+ * The typical workload of the driver:
+ *   Handle the network interface interrupts.
+ */
 static void
 net_interrupt(int irq, struct pt_regs * regs)
 {
@@ -453,9 +478,11 @@
 		}
 	} while (--boguscount);
 
-	/* If any worth-while packets have been received, dev_rint()
-	   has done a mark_bh(NET_BH) for us and will work on them
-	   when we get to the bottom-half routine. */
+	/*
+	 * If any worth-while packets have been received, dev_rint()
+	 * has done a mark_bh(NET_BH) for us and will work on them
+	 * when we get to the bottom-half routine.
+	 */
 	return;
 }
 
@@ -476,7 +503,7 @@
 	disable_dma(dev->dma);
 
 	/* If not IRQ or DMA jumpered, free up the line. */
-	outw(0x00, ioaddr+0);		/* Release the physical interrupt line. */
+	outw(0x00, ioaddr+0);	/* Release the physical interrupt line. */
 
 	free_irq(dev->irq);
 	free_dma(dev->dma);
@@ -491,8 +518,10 @@
 
 }
 
-/* Get the current statistics.	This may be called with the card open or
-   closed. */
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
 static struct enet_statistics *
 net_get_stats(struct device *dev)
 {
@@ -507,38 +536,45 @@
 	return &lp->stats;
 }
 
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
+/*
+ * Set or clear the multicast filter for this adaptor.
+ * num_addrs == -1	Promiscuous mode, receive all packets
+ * num_addrs == 0	Normal mode, clear multicast list
+ * num_addrs > 0	Multicast mode, receive normal and MC packets,
+ *			and do best-effort filtering.
  */
 static void
 set_multicast_list(struct device *dev)
 {
 	short ioaddr = dev->base_addr;
-	if (dev->flags&IFF_PROMISC) {
-		outw(MULTICAST|PROMISC, ioaddr);		/* Enable promiscuous mode */
+	if (dev->flags&IFF_PROMISC)
+	{
+		/* Enable promiscuous mode */
+		outw(MULTICAST|PROMISC, ioaddr);
 	}
 	else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS)
 	{
+		/* Disable promiscuous mode, use normal mode. */
 		hardware_set_filter(NULL);
-		outw(MULTICAST, ioaddr);		/* Disable promiscuous mode, use normal mode */
+
+		outw(MULTICAST, ioaddr);
 	}
 	else if(dev->mc_count)
 	{
-		hardware_set_filter(dev->mc_list);	/* Walk the address list and load the filter */
+		/* Walk the address list, and load the filter */
+		hardware_set_filter(dev->mc_list);
+
 		outw(MULTICAST, ioaddr);
 	}
 	else 
 		outw(0, ioaddr);
 }
-
+
 #ifdef MODULE
 
 static char devicename[9] = { 0, };
 static struct device this_device = {
-	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+	devicename, /* will be inserted by linux/drivers/net/net_init.c */
 	0, 0, 0, 0,
 	0, 0,  /* I/O address, IRQ */
 	0, 0, 0, NULL, netcard_probe };
@@ -556,7 +592,7 @@
 		printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n",
 			   cardname);
 
-	/* copy the parameters from insmod into the device structure */
+	/* Copy the parameters from insmod into the device structure. */
 	this_device.base_addr = io;
 	this_device.irq       = irq;
 	this_device.dma       = dma;
@@ -572,12 +608,11 @@
 cleanup_module(void)
 {
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
 	unregister_netdev(&this_device);
-
-	/* If we don't do this, we can't re-insmod it later. */
-	/* Release irq/dma here, when you have jumpered versions and snarfed
-	 * them in net_probe1().
+	/*
+	 * If we don't do this, we can't re-insmod it later.
+	 * Release irq/dma here, when you have jumpered versions and
+	 * allocate them in net_probe1().
 	 */
 	/*
 	   free_irq(this_device.irq);
@@ -590,10 +625,12 @@
 }
 
 #endif /* MODULE */
-
+
 /*
  * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -Wwrite-strings -Wredundant-decls -O2 -m486 -c skeleton.c"
+ *  compile-command:
+ *	gcc -D__KERNEL__ -Wall -Wstrict-prototypes -Wwrite-strings
+ *	-Wredundant-decls -O2 -m486 -c skeleton.c
  *  version-control: t
  *  kept-new-versions: 5
  *  tab-width: 4
diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c
--- v1.3.52/linux/drivers/scsi/aha1740.c	Mon Oct 23 18:02:07 1995
+++ linux/drivers/scsi/aha1740.c	Sat Dec 30 21:00:40 1995
@@ -448,11 +448,11 @@
     for ( slot=MINEISA; slot <= MAXEISA; slot++ )
     {
 	base = SLOTBASE(slot);
-
-	/* The ioports for eisa boards are generally beyond that used in the
-	   check,snarf_region code, but this may change at some point, so we
-	   go through the motions. */
-
+	/*
+	 * The ioports for eisa boards are generally beyond that used in the
+	 * check/allocate region code, but this may change at some point,
+	 * so we go through the motions.
+	 */
 	if(check_region(base, 0x5c)) continue;  /* See if in use */
 	if ( aha1740_test_port())  break;
     }
diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.3.52/linux/drivers/scsi/scsi.c	Sat Dec 30 15:50:53 1995
+++ linux/drivers/scsi/scsi.c	Sat Dec 30 22:38:29 1995
@@ -58,6 +58,21 @@
 
 #define INTERNAL_ERROR (panic ("Internal error in file %s, line %d.\n", __FILE__, __LINE__))
 
+/*
+ * PAGE_SIZE must be a multiple of the sector size (512).  True
+ * for all reasonably recent architectures (even the VAX...).
+ */
+#define SECTOR_SIZE		512
+#define SECTORS_PER_PAGE	(PAGE_SIZE/SECTOR_SIZE)
+
+#if SECTORS_PER_PAGE <= 8
+ typedef unsigned char	FreeSectorBitmap;
+#elif SECTORS_PER_PAGE <= 32
+ typedef unsigned int	FreeSectorBitmap;
+#else
+# error You lose.
+#endif
+
 static void scsi_done (Scsi_Cmnd *SCpnt);
 static int update_timeout (Scsi_Cmnd *, int);
 static void print_inquiry(unsigned char *data);
@@ -68,7 +83,7 @@
 void scsi_build_commandblocks(Scsi_Device * SDpnt);
 
 
-static unsigned char * dma_malloc_freelist = NULL;
+static FreeSectorBitmap * dma_malloc_freelist = NULL;
 static int scsi_need_isa_bounce_buffers;
 static unsigned int dma_sectors = 0;
 unsigned int dma_free_sectors = 0;
@@ -2145,8 +2160,6 @@
     return oldto;
 }
 
-#define MALLOC_PAGEBITS 12
-
 #ifdef CONFIG_MODULES
 static int scsi_register_host(Scsi_Host_Template *);
 static void scsi_unregister_host(Scsi_Host_Template *);
@@ -2157,7 +2170,7 @@
     unsigned int nbits, mask;
     unsigned long flags;
     int i, j;
-    if((len & 0x1ff) || len > (1<<MALLOC_PAGEBITS))
+    if(len % SECTOR_SIZE != 0 || len > PAGE_SIZE)
 	return NULL;
     
     save_flags(flags);
@@ -2165,8 +2178,8 @@
     nbits = len >> 9;
     mask = (1 << nbits) - 1;
     
-    for(i=0;i < (dma_sectors >> (MALLOC_PAGEBITS - 9)); i++)
-	for(j=0; j<=(sizeof(*dma_malloc_freelist) * 8) - nbits; j++){
+    for(i=0;i < dma_sectors / SECTORS_PER_PAGE; i++)
+	for(j=0; j<=SECTORS_PER_PAGE - nbits; j++){
 	    if ((dma_malloc_freelist[i] & (mask << j)) == 0){
 		dma_malloc_freelist[i] |= (mask << j);
 		restore_flags(flags);
@@ -2183,43 +2196,38 @@
 
 int scsi_free(void *obj, unsigned int len)
 {
-    int page, sector, nbits, mask;
-    long offset;
+    unsigned int page, sector, nbits, mask;
     unsigned long flags;
     
 #ifdef DEBUG
     printk("scsi_free %p %d\n",obj, len);
 #endif
     
-    offset = -1;
-    for (page = 0; page < (dma_sectors >> 3); page++)
-	if ((unsigned long) obj >= (unsigned long) dma_malloc_pages[page] &&
-	    (unsigned long) obj < (unsigned long) dma_malloc_pages[page] 
-	    + (1 << MALLOC_PAGEBITS))
+    for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) {
+        unsigned long page_addr = (unsigned long) dma_malloc_pages[page];
+        if ((unsigned long) obj >= page_addr &&
+	    (unsigned long) obj <  page_addr + PAGE_SIZE)
 	{
-	    offset = ((unsigned long) obj) - ((unsigned long)dma_malloc_pages[page]);
-	    break;
+	    sector = (((unsigned long) obj) - page_addr) >> 9;
+
+            nbits = len >> 9;
+            mask = (1 << nbits) - 1;
+
+            if ((mask << sector) >= (1 << SECTORS_PER_PAGE))
+                panic ("scsi_free:Bad memory alignment");
+
+            save_flags(flags);
+            cli();
+            if((dma_malloc_freelist[page] & (mask << sector)) != (mask<<sector))
+                panic("scsi_free:Trying to free unused memory");
+
+            dma_free_sectors += nbits;
+            dma_malloc_freelist[page] &= ~(mask << sector);
+            restore_flags(flags);
+            return 0;
 	}
-    
-    if (page == (dma_sectors >> 3)) panic("scsi_free:Bad offset");
-    sector = offset >> 9;
-    if(sector >= dma_sectors) panic ("scsi_free:Bad page");
-    
-    sector = (offset >> 9) & (sizeof(*dma_malloc_freelist) * 8 - 1);
-    nbits = len >> 9;
-    mask = (1 << nbits) - 1;
-    
-    if ((mask << sector) > 0xffff) panic ("scsi_free:Bad memory alignment");
-    
-    save_flags(flags);
-    cli();
-    if((dma_malloc_freelist[page] & (mask << sector)) != (mask<<sector))
-	panic("scsi_free:Trying to free unused memory");
-    
-    dma_free_sectors += nbits;
-    dma_malloc_freelist[page] &= ~(mask << sector);
-    restore_flags(flags);
-    return 0;
+    }
+    panic("scsi_free:Bad offset");
 }
 
 
@@ -2521,11 +2529,12 @@
 static void resize_dma_pool(void)
 {
     int i;
+    unsigned long size;
     struct Scsi_Host * shpnt;
     struct Scsi_Host * host = NULL;
     Scsi_Device * SDpnt;
     unsigned long flags;
-    unsigned char * new_dma_malloc_freelist = NULL;
+    FreeSectorBitmap * new_dma_malloc_freelist = NULL;
     unsigned int new_dma_sectors = 0;
     unsigned int new_need_isa_buffer = 0;
     unsigned char ** new_dma_malloc_pages = NULL;
@@ -2538,14 +2547,15 @@
 	if( dma_free_sectors != dma_sectors )
 	    panic("SCSI DMA pool memory leak %d %d\n",dma_free_sectors,dma_sectors);
 
-	for(i=0; i < dma_sectors >> 3; i++)
+	for(i=0; i < dma_sectors / SECTORS_PER_PAGE; i++)
 	    scsi_init_free(dma_malloc_pages[i], PAGE_SIZE);
 	if (dma_malloc_pages)
 	    scsi_init_free((char *) dma_malloc_pages,
-                           (dma_sectors>>3)*sizeof(*dma_malloc_pages));
+                           (dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages));
 	dma_malloc_pages = NULL;
 	if (dma_malloc_freelist)
-	    scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
+	    scsi_init_free((char *) dma_malloc_freelist,
+                           (dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_freelist));
 	dma_malloc_freelist = NULL;
 	dma_sectors = 0;
 	dma_free_sectors = 0;
@@ -2553,7 +2563,7 @@
     }
     /* Next, check to see if we need to extend the DMA buffer pool */
 	
-    new_dma_sectors = 16;  /* Base value we use */
+    new_dma_sectors = 2*SECTORS_PER_PAGE;		/* Base value we use */
 
     if (high_memory-1 > ISA_DMA_THRESHOLD)
 	scsi_need_isa_bounce_buffers = 1;
@@ -2562,7 +2572,7 @@
     
     if (scsi_devicelist)
 	for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next)
-	    new_dma_sectors += 8;  /* Increment for each host */
+	    new_dma_sectors += SECTORS_PER_PAGE;	/* Increment for each host */
     
     for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
 	host = SDpnt->host;
@@ -2581,6 +2591,7 @@
 	}
     }
     
+    /* limit DMA memory to 32MB: */
     new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
     
     /*
@@ -2593,22 +2604,20 @@
     
     if (new_dma_sectors)
     {
-	new_dma_malloc_freelist = (unsigned char *)
-	    scsi_init_malloc(new_dma_sectors >> 3, GFP_ATOMIC);
-	memset(new_dma_malloc_freelist, 0, new_dma_sectors >> 3);
-	
-	new_dma_malloc_pages = (unsigned char **)
-	    scsi_init_malloc((new_dma_sectors>>3)*sizeof(*new_dma_malloc_pages),
-                             GFP_ATOMIC);
-	memset(new_dma_malloc_pages, 0,
-               (new_dma_sectors>>3)*sizeof(*new_dma_malloc_pages));
+        size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap);
+	new_dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC);
+	memset(new_dma_malloc_freelist, 0, size);
+
+        size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(*new_dma_malloc_pages);
+	new_dma_malloc_pages = (unsigned char **) scsi_init_malloc(size, GFP_ATOMIC);
+	memset(new_dma_malloc_pages, 0, size);
     }
     
     /*
      * If we need more buffers, expand the list.
      */
     if( new_dma_sectors > dma_sectors ) { 
-	for(i=dma_sectors >> 3; i< new_dma_sectors >> 3; i++)
+	for(i=dma_sectors / SECTORS_PER_PAGE; i< new_dma_sectors / SECTORS_PER_PAGE; i++)
 	    new_dma_malloc_pages[i] = (unsigned char *)
 	        scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
     }
@@ -2620,17 +2629,17 @@
     cli();
     if (dma_malloc_freelist)
     {
-	memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3);
-	scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
+        size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap);
+	memcpy(new_dma_malloc_freelist, dma_malloc_freelist, size);
+	scsi_init_free((char *) dma_malloc_freelist, size);
     }
     dma_malloc_freelist = new_dma_malloc_freelist;
     
     if (dma_malloc_pages)
     {
-	memcpy(new_dma_malloc_pages, dma_malloc_pages,
-               (dma_sectors>>3)*sizeof(*dma_malloc_pages));
-	scsi_init_free((char *) dma_malloc_pages,
-                       (dma_sectors>>3)*sizeof(*dma_malloc_pages));
+        size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages);
+	memcpy(new_dma_malloc_pages, dma_malloc_pages, size);
+	scsi_init_free((char *) dma_malloc_pages, size);
     }
     
     dma_free_sectors += new_dma_sectors - dma_sectors;
@@ -3111,6 +3120,8 @@
 extern struct symbol_table scsi_symbol_table;
 
 int init_module(void) {
+    unsigned long size;
+
     /*
      * This makes /proc/scsi visible.
      */
@@ -3127,7 +3138,7 @@
 #endif
 
     
-    dma_sectors = PAGE_SIZE / 512;
+    dma_sectors = PAGE_SIZE / SECTOR_SIZE;
     dma_free_sectors= dma_sectors;
     /*
      * Set up a minimal DMA buffer list - this will be used during scan_scsis
@@ -3135,13 +3146,13 @@
      */
     
     /* One bit per sector to indicate free/busy */
-    dma_malloc_freelist = (unsigned char *)
-	scsi_init_malloc(dma_sectors >> 3, GFP_ATOMIC);
-    memset(dma_malloc_freelist, 0, dma_sectors >> 3);
-    
+    size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap);
+    dma_malloc_freelist = (unsigned char *) scsi_init_malloc(size, GFP_ATOMIC);
+    memset(dma_malloc_freelist, 0, size);
+
     /* One pointer per page for the page list */
     dma_malloc_pages = (unsigned char **)
-	scsi_init_malloc((dma_sectors >> 3)*sizeof(*dma_malloc_pages), GFP_ATOMIC);
+	scsi_init_malloc((dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages), GFP_ATOMIC);
     dma_malloc_pages[0] = (unsigned char *)
 	scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
     return 0;
diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v1.3.52/linux/drivers/scsi/scsi_ioctl.c	Sat Nov 11 17:41:33 1995
+++ linux/drivers/scsi/scsi_ioctl.c	Sat Dec 30 11:59:29 1995
@@ -124,14 +124,14 @@
 	    break;
 	case NOT_READY: /* This happens if there is no disc in drive */
 	    if(dev->removable){
-		printk("Device not ready.  Make sure there is a disc in the drive.\n");
+		printk(KERN_INFO "Device not ready.  Make sure there is a disc in the drive.\n");
 		break;
 	    };
 	case UNIT_ATTENTION:
 	    if (dev->removable){
 		dev->changed = 1;
 		SCpnt->result = 0; /* This is no longer considered an error */
-		printk("Disc change detected.\n");
+		printk(KERN_INFO "Disc change detected.\n");
 		break;
 	    };
 	default: /* Fall through for non-removable media */
diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- v1.3.52/linux/drivers/scsi/seagate.c	Tue Dec 26 04:45:37 1995
+++ linux/drivers/scsi/seagate.c	Sat Dec 30 21:00:40 1995
@@ -11,7 +11,7 @@
  *		the status register flipped, I'll fix this "RSN"
  *
  *      This card does all the I/O via memory mapped I/O, so there is no need
- *      to check or snarf a region of the I/O address space.
+ *      to check or allocate a region of the I/O address space.
  */
 
 /*
diff -u --recursive --new-file v1.3.52/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c
--- v1.3.52/linux/drivers/scsi/ultrastor.c	Mon Oct 23 18:02:13 1995
+++ linux/drivers/scsi/ultrastor.c	Sat Dec 30 21:00:40 1995
@@ -63,7 +63,7 @@
  * the 24F, cause the SCSI bus to do odd things and generally lead to
  * kernel panics and machine hangs.  This is like the Adaptec code.
  *
- * Use check/snarf_region for 14f, 34f to avoid I/O space address conflicts.
+ * Check I/O ports 14f, and 34f before allocating them to avoid conflicts.
  */
 
 /* Changes from version 1.8 to version 1.9
diff -u --recursive --new-file v1.3.52/linux/fs/Config.in linux/fs/Config.in
--- v1.3.52/linux/fs/Config.in	Wed Dec 27 09:12:13 1995
+++ linux/fs/Config.in	Tue Jan  2 14:23:34 1996
@@ -19,10 +19,11 @@
   if [ "$CONFIG_NFS_FS" = "y" ]; then
     bool 'Root file system on NFS' CONFIG_ROOT_NFS
   fi
+  tristate 'SMB filesystem support (to mount WfW shares etc..)' CONFIG_SMB_FS
+fi
+if [ "$CONFIG_IPX" = "y" ]; then
+  tristate 'NCP filesystem support (to mount NetWare volumes)' CONFIG_NCP_FS
 fi
 tristate 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS
 tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS
 tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
-if [ "$CONFIG_INET" = "y" ]; then
-  tristate 'SMB filesystem (to mount WfW shares etc..) support' CONFIG_SMB_FS
-fi
diff -u --recursive --new-file v1.3.52/linux/fs/Makefile linux/fs/Makefile
--- v1.3.52/linux/fs/Makefile	Wed Dec 27 09:12:13 1995
+++ linux/fs/Makefile	Tue Jan  2 14:18:43 1996
@@ -16,7 +16,8 @@
 		dcache.o $(BINFMTS) 
 
 MOD_LIST_NAME := FS_MODULES
-ALL_SUB_DIRS = minix ext ext2 msdos proc isofs nfs xiafs umsdos hpfs sysv smbfs
+ALL_SUB_DIRS = minix ext ext2 msdos proc isofs nfs xiafs umsdos hpfs sysv \
+		smbfs ncpfs
 
 ifeq ($(CONFIG_QUOTA),y)
 O_OBJS += dquot.o
@@ -105,6 +106,14 @@
 else
   ifeq ($(CONFIG_SMB_FS),m)
   MOD_SUB_DIRS += smbfs
+  endif
+endif
+
+ifeq ($(CONFIG_NCP_FS),y)
+SUB_DIRS += ncpfs
+else
+  ifeq ($(CONFIG_NCP_FS),m)
+  MOD_SUB_DIRS += ncpfs
   endif
 endif
 
diff -u --recursive --new-file v1.3.52/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v1.3.52/linux/fs/ext2/file.c	Tue Dec 26 04:45:37 1995
+++ linux/fs/ext2/file.c	Tue Jan  2 08:14:43 1996
@@ -25,6 +25,8 @@
 #include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/locks.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
 
 #define	NBUF	32
 
@@ -34,6 +36,7 @@
 #include <linux/fs.h>
 #include <linux/ext2_fs.h>
 
+static int ext2_readpage(struct inode *, unsigned long, char *);
 static int ext2_file_read (struct inode *, struct file *, char *, int);
 static int ext2_file_write (struct inode *, struct file *, const char *, int);
 static void ext2_release_file (struct inode *, struct file *);
@@ -71,7 +74,7 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* readpage */
+	ext2_readpage,		/* readpage */
 	NULL,			/* writepage */
 	ext2_bmap,		/* bmap */
 	ext2_truncate,		/* truncate */
@@ -79,150 +82,101 @@
 	NULL			/* smap */
 };
 
-static int ext2_file_read (struct inode * inode, struct file * filp,
-		    char * buf, int count)
+static int ext2_readpage(struct inode * inode, unsigned long offset, char * page)
 {
-	int read, left, chars;
-	int block, blocks, offset;
-	int bhrequest, uptodate;
-	int clusterblocks;
-	struct buffer_head ** bhb, ** bhe;
-	struct buffer_head * bhreq[NBUF];
-	struct buffer_head * buflist[NBUF];
-	struct super_block * sb;
-	unsigned int size;
-	int err;
-
-	if (!inode) {
-		printk ("ext2_file_read: inode = NULL\n");
-		return -EINVAL;
-	}
-	sb = inode->i_sb;
-	if (!S_ISREG(inode->i_mode)) {
-		ext2_warning (sb, "ext2_file_read", "mode = %07o",
-			      inode->i_mode);
-		return -EINVAL;
-	}
-	offset = filp->f_pos;
-	size = inode->i_size;
-	if (offset > size)
-		left = 0;
-	else
-		left = size - offset;
-	if (left > count)
-		left = count;
-	if (left <= 0)
-		return 0;
-	read = 0;
-	block = offset >> EXT2_BLOCK_SIZE_BITS(sb);
-	offset &= (sb->s_blocksize - 1);
-	chars = sb->s_blocksize - offset;
-	size = (size + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb);
-	blocks = (left + offset + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb);
-	bhb = bhe = buflist;
-	if (filp->f_reada) {
-	        if (blocks < read_ahead[MAJOR(inode->i_dev)] >> (EXT2_BLOCK_SIZE_BITS(sb) - 9))
-	            blocks = read_ahead[MAJOR(inode->i_dev)] >> (EXT2_BLOCK_SIZE_BITS(sb) - 9);
-		if (block + blocks > size)
-			blocks = size - block;
-	}
-
-	/*
-	 * We do this in a two stage process.  We first try and request
-	 * as many blocks as we can, then we wait for the first one to
-	 * complete, and then we try and wrap up as many as are actually
-	 * done.  This routine is rather generic, in that it can be used
-	 * in a filesystem by substituting the appropriate function in
-	 * for getblk
-	 *
-	 * This routine is optimized to make maximum use of the various
-	 * buffers and caches.
-	 */
-
-	clusterblocks = 0;
+	int *p, nr[PAGE_SIZE/512];
+	int i;
 
+	i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
+	offset >>= inode->i_sb->s_blocksize_bits;
+	p = nr;
 	do {
-		bhrequest = 0;
-		uptodate = 1;
-		while (blocks) {
-			--blocks;
-#if 1
-			if(!clusterblocks) clusterblocks = ext2_getcluster(inode, block);
-			if(clusterblocks) clusterblocks--;
-#endif
-
-			*bhb = ext2_getblk (inode, block++, 0, &err);
-			if (*bhb && !buffer_uptodate(*bhb)) {
-				uptodate = 0;
-				bhreq[bhrequest++] = *bhb;
-			}
+		*p = ext2_bmap(inode, offset);
+		i--;
+		offset++;
+		p++;
+	} while (i > 0);
+	return bread_page((unsigned long) page, inode->i_dev, nr, inode->i_sb->s_blocksize);
+}
 
-			if (++bhb == &buflist[NBUF])
-				bhb = buflist;
+/*
+ * This is a generic file read routine, and uses the
+ * inode->i_op->readpage() function for the actual low-level
+ * stuff. We can put this into the other filesystems too
+ * once we've debugged it a bit more.
+ */
+static int ext2_file_read (struct inode * inode, struct file * filp,   
+		char * buf, int count)
+{
+	int read = 0;
+	unsigned long pos;
+	unsigned long addr;
+	unsigned long cached_page = 0;
+	struct page *page;
 
-			/*
-			 * If the block we have on hand is uptodate, go ahead
-			 * and complete processing
-			 */
-			if (uptodate)
-				break;
+	if (count <= 0)
+		return 0;
 
-			if (bhb == bhe)
-				break;
-		}
+	pos = filp->f_pos;
+	
+	for (;;) {
+		unsigned long offset, nr;
 
-		/*
-		 * Now request them all
-		 */
-		if (bhrequest)
-			ll_rw_block (READ, bhrequest, bhreq);
+		if (pos >= inode->i_size)
+			break;
 
-		do {
-			/*
-			 * Finish off all I/O that has actually completed
-			 */
-			if (*bhe) {
-				wait_on_buffer (*bhe);
-				if (!buffer_uptodate(*bhe)) { /* read error? */
-				        brelse(*bhe);
-					if (++bhe == &buflist[NBUF])
-					  bhe = buflist;
-					left = 0;
-					break;
-				}
-			}
-			left -= chars;
-			if (left < 0)
-				chars += left;
-			filp->f_pos += chars;
-			read += chars;
-			if (*bhe) {
-				memcpy_tofs (buf, offset + (*bhe)->b_data,
-					     chars);
-				brelse (*bhe);
-				buf += chars;
-			} else {
-				while (chars-- > 0)
-					put_user (0, buf++);
+		offset = pos & ~PAGE_MASK;
+		nr = PAGE_SIZE - offset;
+		if (nr > count)
+			nr = count;
+
+		/* is it already cached? */
+		page = find_page(inode, pos & PAGE_MASK);
+		if (page)
+			goto found_page;
+
+		/* not cached, have to read it in.. */
+		if (!(addr = cached_page)) {
+			addr = cached_page = __get_free_page(GFP_KERNEL);
+			if (!addr) {
+				if (!read)
+					read = -ENOMEM;
+				break;
 			}
-			offset = 0;
-			chars = sb->s_blocksize;
-			if (++bhe == &buflist[NBUF])
-				bhe = buflist;
-		} while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
-	} while (left > 0);
+		}
+		inode->i_op->readpage(inode, pos & PAGE_MASK, (char *) addr);
 
-	/*
-	 * Release the read-ahead blocks
-	 */
-	while (bhe != bhb) {
-		brelse (*bhe);
-		if (++bhe == &buflist[NBUF])
-			bhe = buflist;
+		/* while we did that, things may have changed.. */
+		if (pos >= inode->i_size)
+			break;
+		page = find_page(inode, pos & PAGE_MASK);
+		if (page)
+			goto found_page;
+
+		/* nope, this is the only copy.. */
+		cached_page = 0;
+		page = mem_map + MAP_NR(addr);
+		page->offset = pos & PAGE_MASK;
+		add_page_to_inode_queue(inode, page);
+		add_page_to_hash_queue(inode, page);
+
+found_page:
+		if (nr > inode->i_size - pos)
+			nr = inode->i_size - pos;
+		page->count++;
+		addr = page_address(page);
+		memcpy_tofs(buf, (void *) (addr + offset), nr);
+		free_page(addr);
+		buf += nr;
+		pos += nr;
+		read += nr;
+		count -= nr;
+		if (!count)
+			break;
 	}
-	if (!read)
-		return -EIO;
-	filp->f_reada = 1;
+	filp->f_pos = pos;
+	if (cached_page)
+		free_page(cached_page);
 	if (!IS_RDONLY(inode)) {
 		inode->i_atime = CURRENT_TIME;
 		inode->i_dirt = 1;
@@ -230,6 +184,18 @@
 	return read;
 }
 
+static inline void update_vm_cache(struct inode * inode, unsigned long pos,
+	char * buf, int count)
+{
+	struct page * page;
+
+	page = find_page(inode, pos & PAGE_MASK);
+	if (page) {
+		pos = (pos & ~PAGE_MASK) + page_address(page);
+		memcpy((void *) pos, buf, count);
+	}
+}
+
 static int ext2_file_write (struct inode * inode, struct file * filp,
 			    const char * buf, int count)
 {
@@ -303,10 +269,11 @@
 				break;
 			}
 		}
+		memcpy_fromfs (bh->b_data + offset, buf, c);
+		update_vm_cache(inode, pos, bh->b_data + offset, c);
 		pos2 += c;
 		pos += c;
 		written += c;
-		memcpy_fromfs (bh->b_data + offset, buf, c);
 		buf += c;
 		mark_buffer_uptodate(bh, 1);
 		mark_buffer_dirty(bh, 0);
diff -u --recursive --new-file v1.3.52/linux/fs/filesystems.c linux/fs/filesystems.c
--- v1.3.52/linux/fs/filesystems.c	Mon Nov 27 12:48:31 1995
+++ linux/fs/filesystems.c	Tue Jan  2 14:18:43 1996
@@ -21,6 +21,7 @@
 #include <linux/sysv_fs.h>
 #include <linux/hpfs_fs.h>
 #include <linux/smb_fs.h>
+#include <linux/ncp_fs.h>
 #include <linux/major.h>
 
 extern void device_setup(void);
@@ -85,6 +86,11 @@
 #ifdef CONFIG_SMB_FS
 	register_filesystem(&(struct file_system_type)
 		{smb_read_super, "smbfs", 0, NULL});
+#endif
+
+#ifdef CONFIG_NCP_FS
+	register_filesystem(&(struct file_system_type)
+		{ncp_read_super, "ncpfs", 0, NULL});
 #endif
 
 #ifdef CONFIG_ISO9660_FS
diff -u --recursive --new-file v1.3.52/linux/fs/inode.c linux/fs/inode.c
--- v1.3.52/linux/fs/inode.c	Wed Dec 27 09:12:13 1995
+++ linux/fs/inode.c	Tue Jan  2 09:31:32 1996
@@ -86,13 +86,13 @@
 	inode->i_next->i_prev = inode;
 }
 
-void grow_inodes(void)
+int grow_inodes(void)
 {
 	struct inode * inode;
 	int i;
 
 	if (!(inode = (struct inode*) get_free_page(GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	i=PAGE_SIZE / sizeof(struct inode);
 	nr_inodes += i;
@@ -103,6 +103,7 @@
 
 	for ( ; i ; i-- )
 		insert_inode_free(inode++);
+	return 0;
 }
 
 unsigned long inode_init(unsigned long start, unsigned long end)
@@ -443,7 +444,7 @@
 {
 	static int ino = 0;
 	struct inode * inode, * best;
-	unsigned long badness = ~0UL;
+	unsigned long badness = 1000;
 	int i;
 
 	if (nr_inodes < NR_INODE && nr_free_inodes < (nr_inodes >> 1))
@@ -461,10 +462,10 @@
 			}
 		}
 	}
-	if (badness > 20)
+	if (badness)
 		if (nr_inodes < NR_INODE) {
-			grow_inodes();
-			goto repeat;
+			if (grow_inodes() == 0)
+				goto repeat;
 		}
 	inode = best;
 	if (!inode) {
diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/Makefile linux/fs/ncpfs/Makefile
--- v1.3.52/linux/fs/ncpfs/Makefile	Thu Jan  1 02:00:00 1970
+++ linux/fs/ncpfs/Makefile	Tue Jan  2 14:18:43 1996
@@ -0,0 +1,17 @@
+#
+# Makefile for the linux ncp-filesystem routines.
+#
+# 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...
+
+O_TARGET := ncpfs.o
+O_OBJS   := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
+
+ncplib_kernel.o: ncplib_kernel.c ncplib_kernel.h
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -finline-functions -c -o $@ $<
diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v1.3.52/linux/fs/ncpfs/dir.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/ncpfs/dir.c	Tue Jan  2 14:18:43 1996
@@ -0,0 +1,1043 @@
+/*
+ *  dir.c
+ *
+ *  Copyright (C) 1995 by Volker Lendecke
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/stat.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/ncp_fs.h>
+#include <asm/segment.h>
+#include <linux/errno.h>
+#include "ncplib_kernel.h"
+
+struct ncp_dirent {
+	struct nw_info_struct i;
+	struct nw_search_sequence s; /* given back for i */
+	unsigned long f_pos;
+};
+
+static int 
+ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count);
+
+static int 
+ncp_readdir(struct inode *inode, struct file *filp,
+            void *dirent, filldir_t filldir);
+
+static int
+ncp_read_volume_list(struct ncp_server *server, int start_with,
+		     int cache_size);
+
+static int
+ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
+	       int cache_size, struct ncp_dirent *entry);
+
+static struct inode *
+ncp_iget(struct inode *dir, struct nw_file_info *finfo);
+
+static struct ncp_inode_info *
+ncp_find_inode(struct inode *dir, const char *name);
+
+static int
+ncp_lookup(struct inode *dir, const char *__name,
+           int len, struct inode **result);
+
+static int 
+ncp_create(struct inode *dir, const char *name, int len, int mode, 
+           struct inode **result);
+
+static int 
+ncp_mkdir(struct inode *dir, const char *name, int len, int mode);
+
+static int 
+ncp_rmdir(struct inode *dir, const char *name, int len);
+
+static int
+ncp_unlink(struct inode *dir, const char *name, int len);
+
+static int
+ncp_rename(struct inode *old_dir, const char *old_name, int old_len, 
+           struct inode *new_dir, const char *new_name, int new_len);
+
+static inline void
+str_upper(char *name)
+{
+	while (*name)
+	{
+		if (*name >= 'a' && *name <= 'z')
+		{
+			*name -= ('a' - 'A');
+		}
+		name++;
+	}
+}
+
+static inline void
+str_lower(char *name)
+{
+	while (*name)
+	{
+		if (*name >= 'A' && *name <= 'Z')
+		{
+			*name += ('a' - 'A');
+		}
+		name ++;
+	}
+}
+
+static struct file_operations ncp_dir_operations = {
+        NULL,			/* lseek - default */
+	ncp_dir_read,		/* read - bad */
+	NULL,			/* write - bad */
+	ncp_readdir,		/* readdir */
+	NULL,			/* select - default */
+	ncp_ioctl,		/* ioctl - default */
+	NULL,			/* mmap */
+	NULL,			/* no special open code */
+	NULL,			/* no special release code */
+	NULL			/* fsync */
+};
+
+struct inode_operations ncp_dir_inode_operations = {
+	&ncp_dir_operations,	/* default directory file ops */
+	ncp_create,		/* create */
+	ncp_lookup,    		/* lookup */
+	NULL,			/* link */
+	ncp_unlink,    		/* unlink */
+	NULL,			/* symlink */
+	ncp_mkdir,     		/* mkdir */
+	ncp_rmdir,     		/* rmdir */
+	NULL,			/* mknod */
+	ncp_rename,    		/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	NULL,			/* bmap */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL                    /* smap */
+};
+
+
+static int 
+ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
+{
+	return -EISDIR;
+}
+
+/* In ncpfs, we have unique inodes across all mounted filesystems, for
+   all inodes that are in memory. That's why it's enough to index the
+   directory cache by the inode number. */
+
+static unsigned long      c_ino = 0;
+static int                c_size;
+static int                c_seen_eof;
+static int                c_last_returned_index;
+static struct ncp_dirent* c_entry = NULL;
+
+static int
+ncp_readdir(struct inode *inode, struct file *filp,
+            void *dirent, filldir_t filldir)
+{
+	int result, i = 0;
+        int index = 0;
+	struct ncp_dirent *entry = NULL;
+        struct ncp_server *server = NCP_SERVER(inode);
+	struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino);
+
+	DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
+	DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
+		 inode->i_ino, c_ino);
+
+	if (!inode || !S_ISDIR(inode->i_mode))
+	{
+		printk("ncp_readdir: inode is NULL or not a directory\n");
+		return -EBADF;
+	}
+
+	if (c_entry == NULL) 
+	{
+		i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
+		c_entry = (struct ncp_dirent *) ncp_kmalloc(i, GFP_KERNEL);
+		if (c_entry == NULL)
+		{
+			printk("ncp_readdir: no MEMORY for cache\n");
+			return -ENOMEM;
+		}
+	}
+
+        if (filp->f_pos == 0)
+	{
+                ncp_invalid_dir_cache(inode->i_ino);
+		if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0)
+		{
+			return 0;
+		}
+		filp->f_pos += 1;
+        }
+
+	if (filp->f_pos == 1)
+	{
+		if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0)
+		{
+			return 0;
+		}
+		filp->f_pos += 1;
+	}
+
+	if (inode->i_ino == c_ino)
+	{
+		for (i = 0; i < c_size; i++)
+		{
+			if (filp->f_pos == c_entry[i].f_pos)
+			{
+                                entry = &c_entry[i];
+                                c_last_returned_index = i;
+                                index = i;
+                                break;
+			}
+		}
+                if ((entry == NULL) && c_seen_eof)
+		{
+                        return 0;
+		}
+	}
+
+	if (entry == NULL)
+	{
+		DDPRINTK("ncp_readdir: Not found in cache.\n");
+
+		if (inode->i_ino == (int)&(server->root))
+		{
+			result = ncp_read_volume_list(server, filp->f_pos,
+						      NCP_READDIR_CACHE_SIZE);
+			DPRINTK("ncp_read_volume_list returned %d\n", result);
+
+		}
+		else
+		{
+			result = ncp_do_readdir(server, inode, filp->f_pos,
+						NCP_READDIR_CACHE_SIZE,
+						c_entry);
+			DPRINTK("ncp_readdir returned %d\n", result);
+		}
+
+		if (result < 0)
+		{
+			c_ino = 0;
+			return result;
+		}
+
+		if (result > 0)
+		{
+                        c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
+			c_ino  = inode->i_ino;
+			c_size = result;
+			entry = c_entry;
+                        c_last_returned_index = 0;
+                        index = 0;
+
+			for (i = 0; i < c_size; i++)
+			{
+				str_lower(c_entry[i].i.entryName);
+			}
+		}
+	}
+
+        if (entry == NULL)
+	{
+                /* Nothing found, even from a ncp call */
+                return 0;
+        }
+
+        while (index < c_size)
+	{
+                /* We found it.  For getwd(), we have to return the
+                   correct inode in d_ino if the inode is currently in
+                   use. Otherwise the inode number does not
+                   matter. (You can argue a lot about this..) */ 
+
+                struct ncp_inode_info *ino_info;
+                ino_info = ncp_find_inode(inode, entry->i.entryName);
+
+                /* Some programs seem to be confused about a zero
+                   inode number, so we set it to one.  Thanks to
+                   Gordon Chaffee for this one. */
+                if (ino_info == NULL)
+		{
+                        ino_info = (struct ncp_inode_info *) 1;
+                }
+
+		DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName);
+		DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
+
+                if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
+                            entry->f_pos, (ino_t)ino_info) < 0)
+		{
+			break;
+                }
+
+		if (   (inode->i_ino != c_ino)
+		    || (entry->f_pos != filp->f_pos))
+		{
+			/* Someone has destroyed the cache while we slept
+			   in filldir */
+			break;
+		}
+                filp->f_pos += 1;
+                index += 1;
+                entry += 1;
+	}
+	return 0;
+}
+
+static int
+ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
+{
+	struct ncp_dirent *entry = c_entry;
+
+	int total_count = 2;
+	int i;
+
+#if 1
+	if (fpos < 2)
+	{
+		printk("OOPS, we expect fpos >= 2");
+		fpos = 2;
+	}
+#endif
+
+	for (i=0; i<NCP_NUMBER_OF_VOLUMES; i++)
+	{
+		struct ncp_volume_info info;
+
+		if (ncp_get_volume_info_with_number(server, i, &info) != 0)
+		{
+			return total_count;
+		}
+
+		if (strlen(info.volume_name) > 0)
+		{
+			if (total_count < fpos)
+			{
+				DPRINTK("ncp_read_volumes: skipped vol: %s\n",
+					info.volume_name);
+			}
+			else if (total_count >= fpos + cache_size)
+			{
+				return (total_count - fpos);
+			}
+			else
+			{
+				DPRINTK("ncp_read_volumes: found vol: %s\n",
+					info.volume_name);
+
+				if (ncp_do_lookup(server, NULL,
+						  info.volume_name,
+						  &(entry->i)) != 0)
+				{
+					printk("ncpfs: could not lookup vol "
+					       "%s\n", info.volume_name);
+					continue;
+				}
+
+				entry->f_pos = total_count;
+				entry += 1;
+			}
+			total_count += 1;
+		}
+	}
+	return (total_count - fpos);
+}
+
+static int
+ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
+	       int cache_size, struct ncp_dirent *entry)
+{
+	static struct nw_search_sequence seq;
+	static struct inode *last_dir;
+	static int total_count;
+
+#if 1
+	if (fpos < 2)
+	{
+		printk("OOPS, we expect fpos >= 2");
+		fpos = 2;
+	}
+#endif
+	DPRINTK("ncp_do_readdir: fpos = %d\n", fpos);
+
+	if (fpos == 2)
+	{
+		last_dir = NULL;
+		total_count = 2;
+	}
+
+	if ((fpos != total_count) || (dir != last_dir))
+	{
+		total_count = 2;
+		last_dir = dir;
+
+		DPRINTK("ncp_do_readdir: re-used seq for %s\n",
+			NCP_ISTRUCT(dir)->entryName);
+
+		if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq)!=0)
+		{
+			DPRINTK("ncp_init_search failed\n");
+			return total_count - fpos;
+		}
+	}
+
+	while (total_count < fpos + cache_size)
+	{
+		if (ncp_search_for_file_or_subdir(server, &seq,
+						  &(entry->i)) != 0)
+		{
+			return total_count - fpos;
+		}
+
+		if (total_count < fpos)
+		{
+			DPRINTK("ncp_do_readdir: skipped file: %s\n",
+				entry->i.entryName);
+		}
+		else
+		{
+			DDPRINTK("ncp_do_r: file: %s, f_pos=%d,total_count=%d",
+				 entry->i.entryName, fpos, total_count);
+			entry->s = seq;
+			entry->f_pos = total_count;
+			entry += 1;
+		}
+		total_count += 1;
+	}
+	return (total_count - fpos);
+}
+
+void
+ncp_init_dir_cache(void)
+{
+        c_ino   = 0;
+        c_entry = NULL;
+}
+
+void
+ncp_invalid_dir_cache(unsigned long ino)
+{
+	if (ino == c_ino)
+	{
+                c_ino = 0;
+                c_seen_eof = 0;
+        }
+}
+
+void
+ncp_free_dir_cache(void)
+{
+        DPRINTK("ncp_free_dir_cache: enter\n");
+        
+        if (c_entry == NULL)
+	{
+                return;
+	}
+
+        ncp_kfree_s(c_entry,
+                    sizeof(struct ncp_dirent) * NCP_READDIR_CACHE_SIZE);
+        c_entry = NULL;
+
+        DPRINTK("ncp_free_dir_cache: exit\n");
+}
+
+
+static struct inode *
+ncp_iget(struct inode *dir, struct nw_file_info *finfo)
+{
+	struct inode *inode;
+        struct ncp_inode_info *new_inode_info;
+        struct ncp_inode_info *root;
+
+	if (dir == NULL)
+	{
+		printk("ncp_iget: dir is NULL\n");
+		return NULL;
+	}
+
+	if (finfo == NULL)
+	{
+		printk("ncp_iget: finfo is NULL\n");
+		return NULL;
+	}
+
+        new_inode_info = ncp_kmalloc(sizeof(struct ncp_inode_info),
+                                     GFP_KERNEL);
+
+        if (new_inode_info == NULL)
+	{
+                printk("ncp_iget: could not alloc mem for %s\n",
+		       finfo->i.entryName);
+                return NULL;
+        }
+
+        new_inode_info->state = NCP_INODE_LOOKED_UP;
+        new_inode_info->nused = 0;
+        new_inode_info->dir   = NCP_INOP(dir);
+        new_inode_info->finfo = *finfo;
+
+        NCP_INOP(dir)->nused += 1;
+
+        /* We have to link the new inode_info into the doubly linked
+           list of inode_infos to make a complete linear search
+           possible. */
+
+        root = &(NCP_SERVER(dir)->root);
+
+        new_inode_info->prev = root;
+        new_inode_info->next = root->next;
+        root->next->prev = new_inode_info;
+        root->next = new_inode_info;
+        
+	if (!(inode = iget(dir->i_sb, (int)new_inode_info)))
+	{
+		printk("ncp_iget: iget failed!");
+		return NULL;
+	}
+
+	return inode;
+}
+
+void
+ncp_free_inode_info(struct ncp_inode_info *i)
+{
+        if (i == NULL)
+	{
+                printk("ncp_free_inode: i == NULL\n");
+                return;
+        }
+
+        i->state = NCP_INODE_CACHED;
+        while ((i->nused == 0) && (i->state == NCP_INODE_CACHED))
+	{
+                struct ncp_inode_info *dir = i->dir;
+
+                i->next->prev = i->prev;
+                i->prev->next = i->next;
+
+		DDPRINTK("ncp_free_inode_info: freeing %s\n",
+			 i->finfo.i.entryName);
+
+                ncp_kfree_s(i, sizeof(struct ncp_inode_info));
+
+                if (dir == i) return;
+
+                (dir->nused)--;
+                i = dir;
+        }
+}
+        
+void
+ncp_init_root(struct ncp_server *server)
+{
+        struct ncp_inode_info *root = &(server->root);
+	struct nw_info_struct *i = &(root->finfo.i);
+	unsigned short dummy;
+
+	DPRINTK("ncp_init_root: server %s\n", server->m.server_name);
+	DPRINTK("ncp_init_root: i = %x\n", (int)i);
+
+        root->finfo.opened = 0;
+	i->attributes  = aDIR;
+	i->dataStreamSize = 1024;
+	ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
+	ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
+	ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate));
+	i->nameLen = 0;
+        i->entryName[0] = '\0';
+
+        root->state = NCP_INODE_LOOKED_UP;
+        root->nused = 1;
+        root->dir   = root;
+        root->next = root->prev = root;
+        return;
+}
+
+void
+ncp_free_all_inodes(struct ncp_server *server)
+{
+        /* Here nothing should be to do. I do not know whether it's
+           better to leave some memory allocated or be stuck in an
+           endless loop */
+#if 1
+        struct ncp_inode_info *root = &(server->root);
+
+        if (root->next != root)
+	{
+                printk("ncp_free_all_inodes: INODES LEFT!!!\n");
+        }
+
+        while (root->next != root)
+	{
+                printk("ncp_free_all_inodes: freeing inode\n");
+                ncp_free_inode_info(root->next);
+                /* In case we have an endless loop.. */
+                schedule();
+        }
+#endif        
+        
+        return;
+}
+
+/* We will search the inode that belongs to this name, currently by a
+   complete linear search through the inodes belonging to this
+   filesystem. This has to be fixed. */
+static struct ncp_inode_info *
+ncp_find_inode(struct inode *dir, const char *name)
+{
+	struct ncp_server *server = NCP_SERVER(dir);
+	struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
+        struct ncp_inode_info *result = &(server->root);
+
+        if (name == NULL)
+	{
+                return NULL;
+	}
+
+        do
+	{
+		if (   (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
+		    && (strcmp(result->finfo.i.entryName, name) == 0))
+		{
+                        return result;
+		}
+                result = result->next;
+
+        }
+	while (result != &(server->root));
+
+        return NULL;
+}
+
+static int 
+ncp_lookup(struct inode *dir, const char *__name, int len,
+           struct inode **result)
+{
+	struct nw_file_info finfo;
+	struct ncp_server *server;
+        struct ncp_inode_info *result_info;
+        int found_in_cache;
+
+	*result = NULL;
+
+	if (!dir || !S_ISDIR(dir->i_mode))
+	{
+		printk("ncp_lookup: inode is NULL or not a directory.\n");
+		iput(dir);
+		return -ENOENT;
+	}
+
+        DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
+
+	server = NCP_SERVER(dir);
+
+	/* Fast cheat for . */
+	if (len == 0 || (len == 1 && __name[0] == '.'))
+	{
+		*result = dir;
+		return 0;
+	}
+
+	/* ..and for .. */
+	if (len == 2 && __name[0] == '.' && __name[1] == '.')
+	{
+		struct ncp_inode_info *parent = NCP_INOP(dir)->dir;
+
+		if (parent->state == NCP_INODE_CACHED)
+		{
+			parent->state = NCP_INODE_LOOKED_UP;
+		}
+
+		*result = iget(dir->i_sb, (int)parent);
+		iput(dir);
+		if (*result == 0)
+		{
+			return -EACCES;
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+        result_info = ncp_find_inode(dir, __name);
+
+        if (result_info != 0)
+	{
+                if (result_info->state == NCP_INODE_CACHED)
+		{
+                        result_info->state = NCP_INODE_LOOKED_UP;
+		}
+
+                /* Here we convert the inode_info address into an
+                   inode number */
+
+                *result = iget(dir->i_sb, (int)result_info);
+                iput(dir);
+
+                if (*result == NULL)
+		{
+                        return -EACCES;
+                }
+
+		return 0;
+        }
+
+        /* If the file is in the dir cache, we do not have to ask the
+           server. */
+
+        found_in_cache = 0;
+        
+        if (dir->i_ino == c_ino)
+	{
+                int first = c_last_returned_index;
+                int i;
+
+                i = first;
+                do
+		{
+                        DDPRINTK("ncp_lookup: trying index: %d, name: %s\n",
+                                i, c_entry[i].i.entryName);
+
+                        if (strcmp(c_entry[i].i.entryName, __name) == 0)
+			{
+                                DPRINTK("ncp_lookup: found in cache!\n");
+				finfo.i = c_entry[i].i;
+				found_in_cache = 1;
+				break;
+                        }
+                        i = (i + 1) % c_size;
+                }
+		while (i != first);
+        }
+
+        if (found_in_cache == 0)
+	{
+		char this_name[len+1];
+
+		memcpy(this_name, __name, len);
+		this_name[len] = 0;
+		str_upper(this_name);
+
+		DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
+			 NCP_ISTRUCT(dir)->entryName, this_name);
+
+		if (ncp_do_lookup(server,
+				  dir->i_ino == (int)&(NCP_SERVER(dir)->root)
+				  ? NULL : NCP_ISTRUCT(dir),
+				  this_name,
+				  &(finfo.i)) != 0)
+		{
+                        iput(dir);
+                        return -ENOENT;
+                }
+        }
+
+	finfo.opened = 0;
+	str_lower(finfo.i.entryName);
+
+	if (!(*result = ncp_iget(dir, &finfo)))
+	{
+		iput(dir);
+		return -EACCES;
+	}
+
+	iput(dir);
+	return 0;
+}
+
+static int 
+ncp_create(struct inode *dir, const char *name, int len, int mode,
+           struct inode **result)
+{
+	struct nw_file_info finfo;
+	__u8 _name[len+1];
+
+	*result = NULL;
+
+	if (!dir || !S_ISDIR(dir->i_mode))
+	{
+		printk("ncp_create: inode is NULL or not a directory\n");
+		iput(dir);
+		return -ENOENT;
+	}
+
+	strncpy(_name, name, len);
+	_name[len] = '\0';
+	str_upper(_name);
+
+	if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
+					   NCP_ISTRUCT(dir), _name,
+					   OC_MODE_CREATE|OC_MODE_OPEN,
+					   0, AR_READ|AR_WRITE,
+					   &finfo) != 0)
+	{
+		iput(dir);
+		return -EACCES;
+	}
+
+        ncp_invalid_dir_cache(dir->i_ino);
+
+	str_lower(finfo.i.entryName);
+	finfo.access = O_RDWR;
+
+	if (!(*result = ncp_iget(dir, &finfo)) < 0)
+	{
+		ncp_close_file(NCP_SERVER(dir), finfo.file_handle);
+		iput(dir);
+		return -EINVAL;
+	}
+
+	iput(dir);
+	return 0;	
+}
+
+static int
+ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
+{
+	int error;
+	struct nw_file_info new_dir;
+	__u8 _name[len+1];
+
+	if (   (name[0] == '.')
+	    && (   (len == 1)
+		|| (   (len == 2)
+		    && (name[1] == '.'))))
+	{
+		return -EEXIST;
+	}
+
+	strncpy(_name, name, len);
+	_name[len] = '\0';
+	str_upper(_name);
+
+	if (!dir || !S_ISDIR(dir->i_mode))
+	{
+		printk("ncp_mkdir: inode is NULL or not a directory\n");
+		iput(dir);
+		return -ENOENT;
+	}
+
+	if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
+					   NCP_ISTRUCT(dir), _name,
+					   OC_MODE_CREATE, aDIR, 0xffff,
+					   &new_dir) != 0)
+	{
+		error = -EACCES;
+	}
+	else
+	{
+		error = 0;
+                ncp_invalid_dir_cache(dir->i_ino);
+        }
+
+	iput(dir);
+	return error;
+}
+
+static int
+ncp_rmdir(struct inode *dir, const char *name, int len)
+{
+	int error;
+	__u8 _name[len+1];
+
+	if (!dir || !S_ISDIR(dir->i_mode))
+	{
+		printk("ncp_rmdir: inode is NULL or not a directory\n");
+		iput(dir);
+		return -ENOENT;
+	}
+        if (ncp_find_inode(dir, name) != NULL)
+	{
+                error = -EBUSY;
+        }
+	else
+	{
+
+		strncpy(_name, name, len);
+		_name[len] = '\0';
+		str_upper(_name);
+
+                if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
+						    NCP_ISTRUCT(dir),
+						    _name)) == 0)
+		{
+                        ncp_invalid_dir_cache(dir->i_ino);
+		}
+		else
+		{
+			error = -EINVAL;
+		}
+        }
+	iput(dir);
+	return error;
+}
+
+static int
+ncp_unlink(struct inode *dir, const char *name, int len)
+{
+	int error;
+	__u8 _name[len+1];
+
+	if (!dir || !S_ISDIR(dir->i_mode))
+	{
+		printk("ncp_unlink: inode is NULL or not a directory\n");
+		iput(dir);
+		return -ENOENT;
+	}
+        if (ncp_find_inode(dir, name) != NULL)
+	{
+                error = -EBUSY;
+        }
+	else
+	{
+		strncpy(_name, name, len);
+		_name[len] = '\0';
+		str_upper(_name);
+
+                if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
+						    NCP_ISTRUCT(dir),
+						    _name)) == 0)
+		{
+                        ncp_invalid_dir_cache(dir->i_ino);
+		}
+		else
+		{
+			error = -EINVAL;
+		}
+        }
+	iput(dir);
+	return error;
+}
+
+static int
+ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
+           struct inode *new_dir, const char *new_name, int new_len)
+{
+	int res;
+	char _old_name[old_len+1];
+	char _new_name[new_len+1];
+
+	if (!old_dir || !S_ISDIR(old_dir->i_mode))
+	{
+		printk("ncp_rename: old inode is NULL or not a directory\n");
+                res = -ENOENT;
+                goto finished;
+	}
+
+	if (!new_dir || !S_ISDIR(new_dir->i_mode))
+	{
+		printk("ncp_rename: new inode is NULL or not a directory\n");
+                res = -ENOENT;
+                goto finished;
+	}
+
+        if (   (ncp_find_inode(old_dir, old_name) != NULL)
+            || (ncp_find_inode(new_dir, new_name) != NULL))
+	{
+                res = -EBUSY;
+                goto finished;
+        }
+
+	strncpy(_old_name, old_name, old_len);
+	_old_name[old_len] = '\0';
+	str_upper(_old_name);
+
+	strncpy(_new_name, new_name, new_len);
+	_new_name[new_len] = '\0';
+	str_upper(_new_name);
+
+	res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
+					    NCP_ISTRUCT(old_dir), _old_name,
+					    NCP_ISTRUCT(new_dir), _new_name);
+
+        if (res == 0)
+	{
+                ncp_invalid_dir_cache(old_dir->i_ino);
+                ncp_invalid_dir_cache(new_dir->i_ino);
+        }
+	else
+	{
+		res = -EACCES;
+	}
+	
+ finished:
+	iput(old_dir); 
+	iput(new_dir);
+	return res;
+}
+
+/* The following routines are taken directly from msdos-fs */
+
+/* Linear day numbers of the respective 1sts in non-leap years. */
+
+static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
+		  /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
+
+
+extern struct timezone sys_tz;
+
+static int
+utc2local(int time)
+{
+        return time - sys_tz.tz_minuteswest*60;
+}
+
+static int
+local2utc(int time)
+{
+        return time + sys_tz.tz_minuteswest*60;
+}
+
+/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
+
+int
+ncp_date_dos2unix(unsigned short time,unsigned short date)
+{
+	int month,year,secs;
+
+	month = ((date >> 5) & 15)-1;
+	year = date >> 9;
+	secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
+	    ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
+	    month < 2 ? 1 : 0)+3653);
+			/* days since 1.1.70 plus 80's leap day */
+	return local2utc(secs);
+}
+
+
+/* Convert linear UNIX date to a MS-DOS time/date pair. */
+void
+ncp_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date)
+{
+	int day,year,nl_day,month;
+
+	unix_date = utc2local(unix_date);
+	*time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
+	    (((unix_date/3600) % 24) << 11);
+	day = unix_date/86400-3652;
+	year = day/365;
+	if ((year+3)/4+365*year > day) year--;
+	day -= (year+3)/4+365*year;
+	if (day == 59 && !(year & 3)) {
+		nl_day = day;
+		month = 2;
+	}
+	else {
+		nl_day = (year & 3) || day <= 59 ? day : day-1;
+		for (month = 0; month < 12; month++)
+			if (day_n[month] > nl_day) break;
+	}
+	*date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
+}
diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c
--- v1.3.52/linux/fs/ncpfs/file.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/ncpfs/file.c	Tue Jan  2 14:18:43 1996
@@ -0,0 +1,284 @@
+/*
+ *  file.c
+ *
+ *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
+ *
+ */
+
+#include <asm/segment.h>
+#include <asm/system.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/mm.h>
+#include <linux/ncp_fs.h>
+#include "ncplib_kernel.h"
+#include <linux/malloc.h>
+
+static inline int min(int a, int b)
+{
+	return a<b ? a : b;
+}
+
+static int 
+ncp_fsync(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+int
+ncp_make_open(struct inode *i, int right)
+{
+        struct nw_file_info *finfo;
+
+        if (i == NULL)
+	{
+                printk("ncp_make_open: got NULL inode\n");
+                return -EINVAL;
+        }
+
+        finfo = NCP_FINFO(i);
+
+        DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
+
+        if (finfo->opened == 0)
+	{
+                /* tries max. rights */
+		if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
+						   NULL, NULL,
+						   OC_MODE_OPEN, 0,
+						   AR_READ | AR_WRITE,
+						   finfo) == 0)
+		{
+			finfo->access = O_RDWR;
+		}
+		else if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
+							NULL, NULL,
+							OC_MODE_OPEN, 0,
+							AR_READ,
+							finfo) == 0)
+		{
+			finfo->access = O_RDONLY;
+		}
+		else
+		{
+			return -EACCES;
+		}
+        }
+
+        if (   ((right == O_RDONLY) && (   (finfo->access == O_RDONLY)
+                                        || (finfo->access == O_RDWR)))
+            || ((right == O_WRONLY) && (   (finfo->access == O_WRONLY)
+                                        || (finfo->access == O_RDWR)))
+            || ((right == O_RDWR)   && (finfo->access == O_RDWR)))
+                return 0;
+
+        return -EACCES;
+}
+
+static int 
+ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
+{
+	int bufsize, to_read, already_read;
+	off_t pos;
+        int errno;
+
+        DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName);
+        
+	if (inode == NULL)
+	{
+		DPRINTK("ncp_file_read: inode = NULL\n");
+		return -EINVAL;
+	}
+
+	if (!S_ISREG(inode->i_mode))
+	{
+		DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
+                        inode->i_mode);
+		return -EINVAL;
+	}
+
+	pos = file->f_pos;
+
+	if (pos + count > inode->i_size)
+	{
+		count = inode->i_size - pos;
+	}
+
+	if (count <= 0)
+	{
+		return 0;
+	}
+
+        if ((errno = ncp_make_open(inode, O_RDONLY)) != 0)
+	{
+                return errno;
+	}
+        
+	bufsize = NCP_SERVER(inode)->buffer_size;
+
+        already_read = 0;
+
+	/* First read in as much as possible for each bufsize. */
+        while (already_read < count)
+	{
+		int read_this_time;
+
+		if ((pos % bufsize) != 0)
+		{
+			to_read = bufsize - (pos % bufsize);
+		}
+		else
+		{
+			to_read = bufsize;
+		}
+
+		to_read = min(to_read, count - already_read);
+
+		if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
+			     pos, to_read, buf, &read_this_time) != 0)
+		{
+			return -EIO; /* This is not exact, i know.. */
+		}
+
+		pos += read_this_time;
+		buf += read_this_time;
+                already_read += read_this_time;
+
+		if (read_this_time < to_read)
+		{
+                        break;
+		}
+	}
+
+        file->f_pos = pos;
+
+	if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME;
+	inode->i_dirt = 1;
+
+        DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName);
+
+        return already_read;
+}
+
+static int 
+ncp_file_write(struct inode *inode, struct file *file, const char *buf,
+	       int count)
+{
+	int bufsize, to_write, already_written;
+        off_t pos;
+        int errno;
+			  
+	if (inode == NULL)
+	{
+		DPRINTK("ncp_file_write: inode = NULL\n");
+		return -EINVAL;
+	}
+
+	if (!S_ISREG(inode->i_mode))
+	{
+		DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
+                       inode->i_mode);
+		return -EINVAL;
+	}
+
+        DPRINTK("ncp_file_write: enter %s\n", NCP_ISTRUCT(inode)->entryName);
+
+	if (count <= 0)
+	{
+		return 0;
+	}
+
+        if ((errno = ncp_make_open(inode, O_RDWR)) != 0)
+	{
+                return errno;
+	}
+        
+	pos = file->f_pos;
+
+	if (file->f_flags & O_APPEND)
+	{
+		pos = inode->i_size;
+	}
+
+	bufsize = NCP_SERVER(inode)->buffer_size;
+
+        already_written = 0;
+
+        while (already_written < count)
+	{
+		int written_this_time;
+
+		if ((pos % bufsize) != 0)
+		{
+			to_write = bufsize - (pos % bufsize);
+		}
+		else
+		{
+			to_write = bufsize;
+		}
+
+		to_write = min(to_write, count - already_written);
+		if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
+			      pos, to_write, buf, &written_this_time) != 0)
+		{
+			return -EIO;
+                }
+
+		pos += written_this_time;
+		buf += written_this_time;
+		already_written += written_this_time;
+
+		if (written_this_time < to_write)
+		{
+			break;
+		}
+	}
+
+	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	inode->i_dirt = 1;
+
+	file->f_pos = pos;
+
+        if (pos > inode->i_size)
+	{
+                inode->i_size = pos;
+        }
+
+        DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName);
+
+	return already_written;
+}
+
+static struct file_operations ncp_file_operations = {
+	NULL,			/* lseek - default */
+	ncp_file_read,		/* read */
+	ncp_file_write,		/* write */
+	NULL,			/* readdir - bad */
+	NULL,			/* select - default */
+	ncp_ioctl,		/* ioctl */
+	ncp_mmap,		/* mmap */
+	NULL,                   /* open */
+	NULL,                   /* release */
+	ncp_fsync,		/* fsync */
+};
+
+struct inode_operations ncp_file_inode_operations = {
+	&ncp_file_operations,	/* default file operations */
+	NULL,			/* create */
+	NULL,			/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	NULL,			/* bmap */
+	NULL			/* truncate */
+};
diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v1.3.52/linux/fs/ncpfs/inode.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/ncpfs/inode.c	Tue Jan  2 14:18:43 1996
@@ -0,0 +1,519 @@
+/*
+ *  inode.c
+ *
+ *  Copyright (C) 1995 by Volker Lendecke
+ *
+ */
+
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+
+#include <linux/sched.h>
+#include <linux/ncp_fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>
+#include <linux/fcntl.h>
+#include <linux/malloc.h>
+#include "ncplib_kernel.h"
+
+extern int close_fp(struct file *filp);
+
+static void ncp_put_inode(struct inode *);
+static void ncp_read_inode(struct inode *);
+static void ncp_put_super(struct super_block *);
+static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int ncp_notify_change(struct inode *inode, struct iattr *attr);
+
+static struct super_operations ncp_sops = {
+	ncp_read_inode,         /* read inode */
+	ncp_notify_change,	/* notify change */
+	NULL,			/* write inode */
+	ncp_put_inode,		/* put inode */
+	ncp_put_super,		/* put superblock */
+	NULL,			/* write superblock */
+	ncp_statfs,		/* stat filesystem */
+	NULL
+};
+
+/* ncp_read_inode: Called from iget, it only traverses the allocated
+   ncp_inode_info's and initializes the inode from the data found
+   there.  It does not allocate or deallocate anything. */
+
+static void
+ncp_read_inode(struct inode *inode)
+{
+        /* Our task should be extremely simple here. We only have to
+           look up the infomation somebody else (ncp_iget) put into
+           the inode tree. The address of this information is the
+           inode->i_ino. Just to make sure everything went well, we
+           check it's there. */
+
+        struct ncp_inode_info *inode_info
+                = (struct ncp_inode_info *)(inode->i_ino);
+
+#if 1
+        struct ncp_inode_info *root = &(NCP_SERVER(inode)->root);
+        struct ncp_inode_info *check_info = root;
+
+        do
+	{
+                if (inode_info == check_info)
+		{
+                        if (check_info->state == NCP_INODE_LOOKED_UP)
+			{
+                                DDPRINTK("ncp_read_inode: found it!\n");
+                                goto good;
+                        }
+                        else
+			{
+                                printk("ncp_read_inode: "
+                                       "state != NCP_INODE_LOOKED_UP\n");
+				goto good;
+                        }
+                }
+                check_info = check_info->next;
+        }
+	while (check_info != root);
+
+        /* Ok, now we're in trouble. The inode info is not there. What
+           should we do now??? */
+        printk("ncp_read_inode: inode info not found\n");
+        return;
+
+ good:
+	DDPRINTK("ncp_read_inode: read entry %s\n",
+		 inode_info->finfo.i.entryName);
+#endif
+        inode_info->state = NCP_INODE_VALID;
+
+        NCP_INOP(inode) = inode_info;
+
+        if (NCP_ISTRUCT(inode)->attributes & aDIR)
+	{
+                inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
+		/* for directories in dataStreamSize seems to be some
+		   Object ID ??? */
+		inode->i_size = 512;
+	}
+	else
+	{
+                inode->i_mode = NCP_SERVER(inode)->m.file_mode;
+		inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
+	}
+
+        DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
+
+        inode->i_nlink   = 1;
+        inode->i_uid     = NCP_SERVER(inode)->m.uid;
+        inode->i_gid     = NCP_SERVER(inode)->m.gid;
+        inode->i_blksize = 1024;
+        inode->i_rdev    = 0;
+
+        if ((inode->i_blksize != 0) && (inode->i_size != 0))
+	{
+                inode->i_blocks =
+                        (inode->i_size - 1) / inode->i_blksize + 1;
+	}
+        else
+	{
+                inode->i_blocks = 0;
+	}
+
+	inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
+					   NCP_ISTRUCT(inode)->modifyDate);
+	inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime,
+					   NCP_ISTRUCT(inode)->creationDate);
+	inode->i_atime = ncp_date_dos2unix(0,
+					   NCP_ISTRUCT(inode)->lastAccessDate);
+
+        if (S_ISREG(inode->i_mode))
+	{
+                inode->i_op = &ncp_file_inode_operations;
+	}
+        else if (S_ISDIR(inode->i_mode))
+	{
+                inode->i_op = &ncp_dir_inode_operations;
+	}
+        else
+	{
+                inode->i_op = NULL;
+	}
+}
+
+static void
+ncp_put_inode(struct inode *inode)
+{
+        struct nw_file_info *finfo = NCP_FINFO(inode);
+
+        if (finfo->opened != 0)
+	{
+                if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0)
+		{
+                        /* We can't do anything but complain. */
+                        printk("ncp_put_inode: could not close\n");
+                }
+        }
+
+	DDPRINTK("ncp_put_inode: put %s\n",
+		finfo->i.entryName);
+
+        ncp_free_inode_info(NCP_INOP(inode));
+
+        if (S_ISDIR(inode->i_mode))
+	{
+                DDPRINTK("ncp_put_inode: put directory %ld\n",
+			 inode->i_ino);
+                ncp_invalid_dir_cache(inode->i_ino);
+        }                
+
+	clear_inode(inode);
+}
+
+struct super_block *
+ncp_read_super(struct super_block *sb, void *raw_data, int silent)
+{
+	struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
+        struct ncp_server *server;
+	struct file *ncp_filp;
+	struct file *wdog_filp;
+	kdev_t dev = sb->s_dev;
+	int error;
+
+	if (data == NULL)
+	{
+		printk("ncp_read_super: missing data argument\n");
+		sb->s_dev = 0;
+		return NULL;
+	}
+
+	if (data->version != NCP_MOUNT_VERSION)
+	{
+		printk("ncp warning: mount version %s than kernel\n",
+		       (data->version < NCP_MOUNT_VERSION) ?
+                       "older" : "newer");
+	}
+
+	if (   (data->ncp_fd >= NR_OPEN)
+	    || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
+	    || (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
+	{
+		printk("ncp_read_super: invalid ncp socket\n");
+		sb->s_dev = 0;
+		return NULL;
+	}
+
+	if (   (data->wdog_fd >= NR_OPEN)
+	    || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
+	    || (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
+	{
+		printk("ncp_read_super: invalid wdog socket\n");
+		sb->s_dev = 0;
+		return NULL;
+	}
+
+        /* We must malloc our own super-block info */
+        server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
+                                                   GFP_KERNEL);
+
+        if (server == NULL)
+	{
+                printk("ncp_read_super: could not alloc ncp_server\n");
+                return NULL;
+        }
+
+	ncp_filp->f_count += 1;
+	wdog_filp->f_count += 1;
+
+	lock_super(sb);
+
+        NCP_SBP(sb) = server;
+        
+	sb->s_blocksize = 1024; /* Eh...  Is this correct? */
+	sb->s_blocksize_bits = 10;
+	sb->s_magic = NCP_SUPER_MAGIC;
+	sb->s_dev = dev;
+	sb->s_op = &ncp_sops;
+
+	server->ncp_filp    = ncp_filp;
+	server->wdog_filp   = wdog_filp;
+	server->lock        = 0;
+	server->wait        = NULL;
+        server->packet      = NULL;
+	server->buffer_size = 0;
+
+        server->m = *data;
+	server->m.file_mode = (server->m.file_mode &
+			       (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
+	server->m.dir_mode  = (server->m.dir_mode &
+			       (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
+
+	server->packet_size = NCP_PACKET_SIZE;
+	server->packet      = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
+
+	if (server->packet == NULL)
+	{
+		printk("ncpfs: could not alloc packet\n");
+		error = -ENOMEM;
+		unlock_super(sb);
+		goto fail;
+	}
+   
+        ncp_init_root(server);
+
+        /*
+         * Make the connection to the server
+         */
+
+	if (ncp_catch_watchdog(server) != 0)
+	{
+		printk("ncp_read_super: Could not catch watchdog\n");
+		error = -EINVAL;
+		unlock_super(sb);
+		goto fail;
+	}
+
+	ncp_lock_server(server);
+	error = ncp_connect(server);
+	ncp_unlock_server(server);
+	unlock_super(sb);
+
+	if (error < 0)
+	{
+		sb->s_dev = 0;
+		printk("ncp_read_super: Failed connection, bailing out "
+                       "(error = %d).\n", -error);
+                ncp_kfree_s(server->packet, server->packet_size);
+		ncp_dont_catch_watchdog(server);
+                goto fail;
+	}
+
+        DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
+
+	if (!(sb->s_mounted = iget(sb, (int)&(server->root))))
+	{
+		sb->s_dev = 0;
+		printk("ncp_read_super: get root inode failed\n");
+                goto disconnect;
+	}
+
+	if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
+				     &(server->buffer_size)) != 0)
+	{
+		sb->s_dev = 0;
+		printk("ncp_read_super: could not get bufsize\n");
+		goto disconnect;
+	}
+
+	DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
+
+        MOD_INC_USE_COUNT;
+	return sb;
+
+ disconnect:
+	ncp_lock_server(server);
+	ncp_disconnect(server);
+	ncp_unlock_server(server);
+	ncp_kfree_s(server->packet, server->packet_size);
+	ncp_dont_catch_watchdog(server);
+ fail:
+	ncp_filp->f_count -= 1;
+	wdog_filp->f_count -= 1;
+        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
+        return NULL;
+}
+
+static void
+ncp_put_super(struct super_block *sb)
+{
+        struct ncp_server *server = NCP_SBP(sb);
+
+	lock_super(sb);
+
+	ncp_lock_server(server);
+        ncp_disconnect(server);
+	ncp_unlock_server(server);
+
+	close_fp(server->ncp_filp);
+
+	ncp_dont_catch_watchdog(server);
+	close_fp(server->wdog_filp);
+
+        ncp_free_all_inodes(server);
+
+        ncp_kfree_s(server->packet, server->packet_size);
+
+	sb->s_dev = 0;
+        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
+	NCP_SBP(sb) = NULL;
+
+	unlock_super(sb);
+
+        MOD_DEC_USE_COUNT;
+}
+
+static void 
+ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+	struct statfs tmp;
+	
+	/* We cannot say how much disk space is left on a mounted
+           NetWare Server, because free space is distributed over
+           volumes, and the current user might have disk quotas. So
+           free space is not that simple to determine. Our decision
+           here is to err conservatively. */
+
+	tmp.f_type = NCP_SUPER_MAGIC;
+	tmp.f_bsize = 512;
+	tmp.f_blocks = 0;
+	tmp.f_bfree = 0;
+	tmp.f_bavail = 0;
+	tmp.f_files = -1;
+	tmp.f_ffree = -1;
+	tmp.f_namelen = 12;
+	memcpy_tofs(buf, &tmp, bufsiz);
+}
+
+static int
+ncp_notify_change(struct inode *inode, struct iattr *attr)
+{
+	int result = 0;
+	int info_mask;
+	struct nw_modify_dos_info info;
+
+	if ((result = inode_change_ok(inode, attr)) < 0)
+		return result;
+
+	if (((attr->ia_valid & ATTR_UID) && 
+	     (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
+		return -EPERM;
+
+	if (((attr->ia_valid & ATTR_GID) && 
+	     (attr->ia_uid != NCP_SERVER(inode)->m.gid)))
+                return -EPERM;
+
+	if (((attr->ia_valid & ATTR_MODE) &&
+	     (attr->ia_mode &
+	      ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
+		return -EPERM;
+
+	info_mask = 0;
+	memset(&info, 0, sizeof(info));
+
+	if ((attr->ia_valid & ATTR_CTIME) != 0)
+	{
+		info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
+		ncp_date_unix2dos(attr->ia_ctime,
+				  &(info.creationTime), &(info.creationDate));
+	}
+	
+	if ((attr->ia_valid & ATTR_MTIME) != 0)
+	{
+		info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
+		ncp_date_unix2dos(attr->ia_mtime,
+				  &(info.modifyTime), &(info.modifyDate));
+	}
+	
+	if ((attr->ia_valid & ATTR_ATIME) != 0)
+	{
+		__u16 dummy;
+		info_mask |= (DM_LAST_ACCESS_DATE);
+		ncp_date_unix2dos(attr->ia_ctime,
+				  &(dummy), &(info.lastAccessDate));
+	}
+
+	if (info_mask != 0)
+	{
+		if ((result =
+		     ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
+							NCP_ISTRUCT(inode),
+							info_mask,
+							&info)) != 0)
+		{
+			result = -EACCES;
+
+			if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
+			{
+				/* NetWare seems not to allow this. I
+                                   do not know why. So, just tell the
+                                   user everything went fine. This is
+                                   a terrible hack, but I do not know
+                                   how to do this correctly. */
+				result = 0;
+			}
+		}
+	}
+
+        if ((attr->ia_valid & ATTR_SIZE) != 0)
+	{
+		int written;
+
+		DPRINTK("ncpfs: trying to change size of %s to %ld\n",
+			NCP_ISTRUCT(inode)->entryName, attr->ia_size);
+
+		if ((result = ncp_make_open(inode, O_RDWR)) < 0)
+		{
+			return -EACCES;
+		}
+
+		ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
+			  attr->ia_size, 0, "", &written);
+
+		/* According to ndir, the changes only take effect after
+		   closing the file */
+		ncp_close_file(NCP_SERVER(inode),
+			       NCP_FINFO(inode)->file_handle);
+		NCP_FINFO(inode)->opened = 0;
+
+		result = 0;
+	}
+
+        ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir));
+
+	return result;
+}
+		
+#ifdef DEBUG_NCP_MALLOC
+int ncp_malloced;
+int ncp_current_malloced;
+#endif
+
+#ifdef MODULE
+
+static struct file_system_type ncp_fs_type = {
+        ncp_read_super, "ncpfs", 0, NULL
+        };
+
+int
+init_module( void)
+{
+        DPRINTK("ncpfs: init_module called\n");
+
+#ifdef DEBUG_NCP_MALLOC
+        ncp_malloced = 0;
+        ncp_current_malloced = 0;
+#endif
+
+        ncp_init_dir_cache();
+        register_filesystem(&ncp_fs_type);
+        return 0;
+}
+
+void
+cleanup_module(void)
+{
+        DPRINTK("ncpfs: cleanup_module called\n");
+        ncp_free_dir_cache();
+        unregister_filesystem(&ncp_fs_type);
+#ifdef DEBUG_NCP_MALLOC
+        printk("ncp_malloced: %d\n", ncp_malloced);
+        printk("ncp_current_malloced: %d\n", ncp_current_malloced);
+#endif
+}
+
+#endif
diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c
--- v1.3.52/linux/fs/ncpfs/ioctl.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/ncpfs/ioctl.c	Tue Jan  2 14:18:43 1996
@@ -0,0 +1,93 @@
+/*
+ *  ioctl.c
+ *
+ *  Copyright (C) 1995 by Volker Lendecke
+ *
+ */
+
+#include <asm/segment.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ncp_fs.h>
+#include <linux/ioctl.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/ncp.h>
+
+int
+ncp_ioctl (struct inode * inode, struct file * filp,
+           unsigned int cmd, unsigned long arg)
+{
+	int result;
+	struct ncp_ioctl_request request;
+	struct ncp_server *server;
+
+	switch(cmd) {
+	case NCP_IOC_NCPREQUEST:
+
+		if (!suser())
+		{
+			return -EPERM;
+		}
+		
+		if ((result = verify_area(VERIFY_READ, (char *)arg,
+					  sizeof(request))) != 0)
+		{
+			return result;
+		}
+
+		memcpy_fromfs(&request, (struct ncp_ioctl_request *)arg,
+			      sizeof(request));
+
+		if (   (request.function > 255)
+		    || (request.size >
+			NCP_PACKET_SIZE - sizeof(struct ncp_request_header)))
+		{
+			return -EINVAL;
+		}
+
+		if ((result = verify_area(VERIFY_WRITE, (char *)request.data,
+					  NCP_PACKET_SIZE)) != 0)
+		{
+			return result;
+		}
+
+		server = NCP_SERVER(inode);
+		ncp_lock_server(server);
+
+		/* FIXME: We hack around in the server's structures
+                   here to be able to use ncp_request */
+
+		server->has_subfunction = 0;
+		server->current_size =
+			request.size + sizeof(struct ncp_request_header);
+		memcpy_fromfs(server->packet, request.data,
+			      request.size+sizeof(struct ncp_request_header));
+
+		
+		ncp_request(server, request.function);
+
+		DPRINTK("ncp_ioctl: copy %d bytes\n",
+			server->reply_size);
+		memcpy_tofs(request.data, server->packet,
+			    server->reply_size);
+
+		ncp_unlock_server(server);
+
+		return server->reply_size;
+
+        case NCP_IOC_GETMOUNTUID:
+                if ((result = verify_area(VERIFY_WRITE, (uid_t*) arg,
+                                          sizeof(uid_t))) != 0)
+		{
+                        return result;
+                }
+                put_fs_word(NCP_SERVER(inode)->m.mounted_uid, (uid_t*) arg);
+                return 0;
+
+	default:
+		return -EINVAL;
+	}
+	
+	return -EINVAL;
+}
diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c
--- v1.3.52/linux/fs/ncpfs/mmap.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/ncpfs/mmap.c	Tue Jan  2 14:18:43 1996
@@ -0,0 +1,146 @@
+/*
+ *  mmap.c
+ *
+ *  Copyright (C) 1995 by Volker Lendecke
+ *
+ */
+
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/shm.h>
+#include <linux/errno.h>
+#include <linux/mman.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/ncp_fs.h>
+
+#include "ncplib_kernel.h"
+#include <asm/segment.h>
+#include <asm/system.h>
+
+static inline int min(int a, int b)
+{
+	return a<b ? a : b;
+}
+
+/*
+ * Fill in the supplied page for mmap
+ */
+static unsigned long 
+ncp_file_mmap_nopage(struct vm_area_struct * area,
+		     unsigned long address, unsigned long page, int no_share)
+{
+	struct inode * inode = area->vm_inode;
+	unsigned int clear;
+	unsigned long tmp;
+	int bufsize;
+	int pos;
+	unsigned short fs;
+
+	address &= PAGE_MASK;
+	pos = address - area->vm_start + area->vm_offset;
+
+	clear = 0;
+	if (address + PAGE_SIZE > area->vm_end)
+	{
+		clear = address + PAGE_SIZE - area->vm_end;
+	}
+
+        /* what we can read in one go */
+	bufsize = NCP_SERVER(inode)->buffer_size;
+
+	fs = get_fs();
+	set_fs(get_ds());
+
+        if (ncp_make_open(inode, O_RDONLY) < 0)
+	{
+                clear = PAGE_SIZE;
+        }
+        else
+        {
+		int already_read = 0;
+		int count = PAGE_SIZE - clear;
+		int to_read;
+
+		while (already_read < count)
+		{
+			int read_this_time;
+
+			if ((pos % bufsize) != 0)
+			{
+				to_read = bufsize - (pos % bufsize);
+			}
+			else
+			{
+				to_read = bufsize;
+			}
+
+			to_read = min(to_read, count - already_read);
+
+			if (ncp_read(NCP_SERVER(inode),
+				     NCP_FINFO(inode)->file_handle,
+				     pos, to_read,
+				     (char *)(page + already_read),
+				     &read_this_time) != 0)
+			{
+			       read_this_time = 0;
+			}
+
+			pos += read_this_time;
+			already_read += read_this_time;
+
+			if (read_this_time < to_read)
+			{
+				break;
+			}
+		}
+
+        }
+
+	set_fs(fs);
+
+	tmp = page + PAGE_SIZE;
+	while (clear--) {
+		*(char *)--tmp = 0;
+	}
+	return page;
+}
+
+struct vm_operations_struct ncp_file_mmap = {
+	NULL,			/* open */
+	NULL,			/* close */
+	NULL,			/* unmap */
+	NULL,			/* protect */
+	NULL,			/* sync */
+	NULL,			/* advise */
+	ncp_file_mmap_nopage,	/* nopage */
+	NULL,			/* wppage */
+	NULL,			/* swapout */
+	NULL,			/* swapin */
+};
+
+
+/* This is used for a general mmap of a ncp file */
+int
+ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
+{
+        DPRINTK("ncp_mmap: called\n");
+
+        /* only PAGE_COW or read-only supported now */
+	if (vma->vm_flags & VM_SHARED)	
+		return -EINVAL;
+	if (!inode->i_sb || !S_ISREG(inode->i_mode))
+		return -EACCES;
+	if (!IS_RDONLY(inode)) {
+		inode->i_atime = CURRENT_TIME;
+		inode->i_dirt = 1;
+	}
+
+	vma->vm_inode = inode;
+	inode->i_count++;
+	vma->vm_ops = &ncp_file_mmap;
+	return 0;
+}
diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c
--- v1.3.52/linux/fs/ncpfs/ncplib_kernel.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/ncpfs/ncplib_kernel.c	Tue Jan  2 14:18:43 1996
@@ -0,0 +1,611 @@
+#include "ncplib_kernel.h"
+
+typedef __u8  byte;
+typedef __u16 word;
+typedef __u32 dword;
+
+static inline int min(int a, int b)
+{
+	return a<b ? a : b;
+}
+
+static void
+assert_server_locked(struct ncp_server *server)
+{
+	if (server->lock == 0)
+	{
+		DPRINTK("ncpfs: server not locked!\n");
+	}
+}
+
+static void
+ncp_add_byte(struct ncp_server *server, byte x)
+{
+	assert_server_locked(server);
+	*(byte *)(&(server->packet[server->current_size])) = x;
+	server->current_size += 1;
+	return;
+}
+
+static void
+ncp_add_word(struct ncp_server *server, word x)
+{
+	assert_server_locked(server);
+	*(word *)(&(server->packet[server->current_size])) = x;
+	server->current_size += 2;
+	return;
+}
+
+static void
+ncp_add_dword(struct ncp_server *server, dword x)
+{
+	assert_server_locked(server);
+	*(dword *)(&(server->packet[server->current_size])) = x;
+	server->current_size += 4;
+	return;
+}
+
+static void
+ncp_add_mem(struct ncp_server *server, const void *source, int size)
+{
+	assert_server_locked(server);
+	memcpy(&(server->packet[server->current_size]), source, size);
+	server->current_size += size;
+	return;
+}
+
+static void
+ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size)
+{
+	assert_server_locked(server);
+	memcpy_fromfs(&(server->packet[server->current_size]), source, size);
+	server->current_size += size;
+	return;
+}
+
+static void
+ncp_add_pstring(struct ncp_server *server, const char *s)
+{
+	int len = strlen(s);
+	assert_server_locked(server);
+	if (len > 255)
+	{
+		DPRINTK("ncpfs: string too long: %s\n", s);
+		len = 255;
+	}
+	ncp_add_byte(server, len);
+	ncp_add_mem(server, s, len);
+	return;
+}
+
+static void
+ncp_init_request(struct ncp_server *server)
+{
+	ncp_lock_server(server);
+
+	server->current_size = sizeof(struct ncp_request_header);
+	server->has_subfunction = 0;
+}
+
+static void
+ncp_init_request_s(struct ncp_server *server, int subfunction)
+{
+	ncp_init_request(server);
+	ncp_add_word(server, 0); /* preliminary size */
+
+	ncp_add_byte(server, subfunction);
+
+	server->has_subfunction = 1;
+}
+
+static char *
+ncp_reply_data(struct ncp_server *server, int offset)
+{
+	return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
+}
+
+static byte
+ncp_reply_byte(struct ncp_server *server, int offset)
+{
+	return *(byte *)(ncp_reply_data(server, offset));
+}
+
+static word
+ncp_reply_word(struct ncp_server *server, int offset)
+{
+	return *(word *)(ncp_reply_data(server, offset));
+}
+
+static dword
+ncp_reply_dword(struct ncp_server *server, int offset)
+{
+	return *(dword *)(ncp_reply_data(server, offset));
+}
+
+int
+ncp_negotiate_buffersize(struct ncp_server *server,
+			 int size, int *target)
+{
+	int result;
+
+	ncp_init_request(server);
+	ncp_add_word(server, htons(size));
+	
+	if ((result = ncp_request(server, 33)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	*target =min(ntohs(ncp_reply_word(server, 0)), size);
+
+	ncp_unlock_server(server);
+	return 0;
+}
+
+int
+ncp_get_volume_info_with_number(struct ncp_server *server, int n,
+				struct ncp_volume_info *target)
+{
+	int result;
+	int len;
+
+	ncp_init_request_s(server, 44);
+	ncp_add_byte(server, n);
+
+	if ((result = ncp_request(server, 22)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	target->total_blocks = ncp_reply_dword(server, 0);
+	target->free_blocks  = ncp_reply_dword(server, 4);
+	target->purgeable_blocks = ncp_reply_dword(server, 8);
+	target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12);
+	target->total_dir_entries = ncp_reply_dword(server, 16);
+	target->available_dir_entries = ncp_reply_dword(server, 20);
+	target->sectors_per_block = ncp_reply_byte(server, 28);
+
+	memset(&(target->volume_name), 0, sizeof(target->volume_name));
+
+	len = ncp_reply_byte(server, 29);
+	if (len > NCP_VOLNAME_LEN)
+	{
+		DPRINTK("ncpfs: volume name too long: %d\n", len);
+		ncp_unlock_server(server);
+		return -EIO;
+	}
+
+	memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
+	ncp_unlock_server(server);
+	return 0;
+}
+
+int
+ncp_get_volume_number(struct ncp_server *server, const char *name, int *target)
+{
+	int result;
+
+	ncp_init_request_s(server, 5);
+	ncp_add_pstring(server, name);
+
+	if ((result = ncp_request(server, 22)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	*target = ncp_reply_byte(server, 0);
+	ncp_unlock_server(server);
+	return 0;
+}
+
+int
+ncp_close_file(struct ncp_server *server, const char *file_id)
+{
+	int result;
+
+	ncp_init_request(server);
+	ncp_add_byte(server, 0);
+	ncp_add_mem(server, file_id, 6);
+
+	if ((result = ncp_request(server, 66)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	ncp_unlock_server(server);
+	return 0;
+}
+
+static void
+ncp_add_handle_path(struct ncp_server *server,
+		    __u8 vol_num,
+		    __u32 dir_base, int have_dir_base,
+		    char *path)
+{
+	ncp_add_byte(server, vol_num);
+	ncp_add_dword(server, dir_base);
+	if (have_dir_base != 0)
+	{
+		ncp_add_byte(server, 1); /* dir_base */
+	}
+	else
+	{
+		ncp_add_byte(server, 0xff); /* no handle */
+	}
+	if (path != NULL)
+	{
+		ncp_add_byte(server, 1); /* 1 component */
+		ncp_add_pstring(server, path);
+	}
+	else
+	{
+		ncp_add_byte(server, 0);
+	}
+}
+
+static void
+ncp_extract_file_info(void *structure, struct nw_info_struct *target)
+{
+	__u8 *name_len;
+	const int info_struct_size = sizeof(struct nw_info_struct) - 257;
+
+	memcpy(target, structure, info_struct_size);
+	name_len = structure + info_struct_size;
+	target->nameLen = *name_len;
+	strncpy(target->entryName, name_len+1, *name_len);
+	target->entryName[*name_len] = '\0';
+	return;
+}
+		
+
+int
+ncp_do_lookup(struct ncp_server *server,
+	      struct nw_info_struct *dir,
+	      char *path,	/* may only be one component */
+	      struct nw_info_struct *target)
+{
+	__u8  vol_num;
+	__u32 dir_base;
+	int result;
+	char *volname = NULL;
+
+	if (target == NULL)
+	{
+		return -EINVAL;
+	}
+ 
+	if (dir == NULL)
+	{
+
+		DDPRINTK("ncp_do_lookup: looking up vol %s\n", path);
+
+		/* Access a volume's root directory */
+		ncp_init_request(server);
+		ncp_add_byte(server, 22); /* subfunction */
+		ncp_add_byte(server, 0); /* dos name space */
+		ncp_add_byte(server, 0); /* reserved */
+		ncp_add_byte(server, 0); /* reserved */
+		ncp_add_byte(server, 0); /* reserved */
+		ncp_add_handle_path(server, 0, 0, 0, /* no handle */
+				    path);
+
+		if ((result = ncp_request(server, 87)) != 0)
+		{
+			ncp_unlock_server(server);
+			return result;
+		}
+
+		dir_base = ncp_reply_dword(server, 4);
+		vol_num  = ncp_reply_byte (server, 8);
+		ncp_unlock_server(server);
+		volname = path;
+		path = NULL;
+	}
+	else
+	{
+		vol_num = dir->volNumber;
+		dir_base = dir->DosDirNum;
+	}
+
+	ncp_init_request(server);
+	ncp_add_byte(server, 6); /* subfunction */
+	ncp_add_byte(server, 0); /* dos name space */
+	ncp_add_byte(server, 0); /* dos name space as dest */
+	ncp_add_word(server, 0xff); /* get all */
+	ncp_add_dword(server, RIM_ALL);
+	ncp_add_handle_path(server, vol_num, dir_base, 1,
+			    path);
+
+	if ((result = ncp_request(server, 87)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	ncp_extract_file_info(ncp_reply_data(server, 0), target);
+
+	if (volname != NULL)
+	{
+		target->nameLen = strlen(volname);
+		strcpy(target->entryName, volname);
+	}
+
+	ncp_unlock_server(server);
+	return 0;
+}
+
+int
+ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
+				   struct nw_info_struct *file,
+				   __u32 info_mask,
+				   struct nw_modify_dos_info *info)
+{
+	int result;
+
+	ncp_init_request(server);
+	ncp_add_byte(server, 7); /* subfunction */
+	ncp_add_byte(server, 0); /* dos name space */
+	ncp_add_byte(server, 0); /* reserved */
+	ncp_add_word(server, 0x8006); /* search attribs: all */
+
+	ncp_add_dword(server, info_mask);
+	ncp_add_mem(server, info, sizeof(*info));
+	ncp_add_handle_path(server, file->volNumber,
+			    file->DosDirNum, 1, NULL);
+
+	if ((result = ncp_request(server, 87)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	ncp_unlock_server(server);
+	return 0;
+}
+
+int
+ncp_del_file_or_subdir(struct ncp_server *server,
+		       struct nw_info_struct *dir, char *name)
+{
+	int result;
+
+	ncp_init_request(server);
+	ncp_add_byte(server, 8); /* subfunction */
+	ncp_add_byte(server, 0); /* dos name space */
+	ncp_add_byte(server, 0); /* reserved */
+	ncp_add_word(server, 0x8006); /* search attribs: all */
+	ncp_add_handle_path(server, dir->volNumber,
+			    dir->DosDirNum, 1, name);
+	
+	if ((result = ncp_request(server, 87)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	ncp_unlock_server(server);
+	return 0;
+}
+
+static inline void
+ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] )
+{
+    __u16 *dest = (__u16 *) ret;
+    memcpy(&(dest[1]), &sfd, 4);
+    dest[0] = dest[1] + 1;
+    return;
+}
+
+/* If both dir and name are NULL, then in target there's already a
+   looked-up entry that wants to be opened. */
+int
+ncp_open_create_file_or_subdir(struct ncp_server *server,
+			       struct nw_info_struct *dir, char *name,
+			       int open_create_mode,
+			       __u32 create_attributes,
+			       int desired_acc_rights,
+			       struct nw_file_info *target)
+{
+	int result;
+
+	ncp_init_request(server);
+	ncp_add_byte(server, 1); /* subfunction */
+	ncp_add_byte(server, 0); /* dos name space */
+	ncp_add_byte(server, open_create_mode);
+	ncp_add_word(server, 0x8006);
+	ncp_add_dword(server, RIM_ALL);
+	ncp_add_dword(server, create_attributes);
+	/* The desired acc rights seem to be the inherited rights mask
+	   for directories */
+	ncp_add_word(server, desired_acc_rights);
+
+	if (dir != NULL)
+	{
+		ncp_add_handle_path(server, dir->volNumber,
+				    dir->DosDirNum, 1, name);
+	}
+	else
+	{
+		ncp_add_handle_path(server,
+				    target->i.volNumber, target->i.DosDirNum,
+				    1, NULL);
+	}	
+
+	if ((result = ncp_request(server, 87)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	target->opened = 1;
+	target->server_file_handle = ncp_reply_dword(server, 0);
+	target->open_create_action = ncp_reply_byte(server, 4);
+
+	if (dir != NULL)
+	{
+		/* in target there's a new finfo to fill */
+		ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i));
+	}
+
+	ConvertToNWfromDWORD(target->server_file_handle, target->file_handle);
+
+	ncp_unlock_server(server);
+	return 0;
+}
+	
+
+int
+ncp_initialize_search(struct ncp_server *server,
+		      struct nw_info_struct *dir,
+		      struct nw_search_sequence *target)
+{
+	int result;
+
+	ncp_init_request(server);
+	ncp_add_byte(server, 2); /* subfunction */
+	ncp_add_byte(server, 0); /* dos name space */
+	ncp_add_byte(server, 0); /* reserved */
+	ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
+	
+	if ((result = ncp_request(server, 87)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
+
+	ncp_unlock_server(server);
+	return 0;
+}
+	
+/* Search for everything */
+int
+ncp_search_for_file_or_subdir(struct ncp_server *server,
+			      struct nw_search_sequence *seq,
+			      struct nw_info_struct *target)
+{
+	int result;
+
+	ncp_init_request(server);
+	ncp_add_byte(server, 3); /* subfunction */
+	ncp_add_byte(server, 0); /* dos name space */
+	ncp_add_byte(server, 0); /* data stream (???) */
+	ncp_add_word(server, 0xffff); /* Search attribs */
+	ncp_add_dword(server, RIM_ALL);	/* return info mask */
+	ncp_add_mem(server, seq, 9);
+	ncp_add_byte(server, 2); /* 2 byte pattern */
+	ncp_add_byte(server, 0xff); /* following is a wildcard */
+	ncp_add_byte(server, '*');
+	
+	if ((result = ncp_request(server, 87)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
+	ncp_extract_file_info(ncp_reply_data(server, 10), target);
+
+	ncp_unlock_server(server);
+	return 0;
+}
+
+int
+ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
+			      struct nw_info_struct *old_dir, char *old_name,
+			      struct nw_info_struct *new_dir, char *new_name)
+{
+	int result;
+
+	if (   (old_dir == NULL) || (old_name == NULL)
+	    || (new_dir == NULL) || (new_name == NULL))
+		return -EINVAL;
+	
+	ncp_init_request(server);
+	ncp_add_byte(server, 4); /* subfunction */
+	ncp_add_byte(server, 0); /* dos name space */
+	ncp_add_byte(server, 1); /* rename flag */
+	ncp_add_word(server, 0x8006); /* search attributes */
+
+	/* source Handle Path */
+	ncp_add_byte(server, old_dir->volNumber);
+	ncp_add_dword(server, old_dir->DosDirNum);
+	ncp_add_byte(server, 1);
+	ncp_add_byte(server, 1); /* 1 source component */
+
+	/* dest Handle Path */
+	ncp_add_byte(server, new_dir->volNumber);
+	ncp_add_dword(server, new_dir->DosDirNum);
+	ncp_add_byte(server, 1);
+	ncp_add_byte(server, 1); /* 1 destination component */
+
+	/* source path string */
+	ncp_add_pstring(server, old_name);
+	/* dest path string */
+	ncp_add_pstring(server, new_name);
+
+	result = ncp_request(server, 87);
+	ncp_unlock_server(server);
+	return result;
+}
+	
+
+/* We have to transfer to/from user space */
+int
+ncp_read(struct ncp_server *server, const char *file_id,
+	 __u32 offset, __u16 to_read,
+	 char *target, int *bytes_read)
+{
+	int result;
+
+	ncp_init_request(server);
+	ncp_add_byte(server, 0);
+	ncp_add_mem(server, file_id, 6);
+	ncp_add_dword(server, htonl(offset));
+	ncp_add_word(server, htons(to_read));
+
+	if ((result = ncp_request(server, 72)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	*bytes_read = ntohs(ncp_reply_word(server, 0));
+
+	memcpy_tofs(target, ncp_reply_data(server, 2), *bytes_read);
+
+	ncp_unlock_server(server);
+	return 0;
+}
+
+int
+ncp_write(struct ncp_server *server, const char *file_id,
+	  __u32 offset, __u16 to_write,
+	  const char *source, int *bytes_written)
+{
+	int result;
+
+	ncp_init_request(server);
+	ncp_add_byte(server, 0);
+	ncp_add_mem(server, file_id, 6);
+	ncp_add_dword(server, htonl(offset));
+	ncp_add_word(server, htons(to_write));
+	ncp_add_mem_fromfs(server, source, to_write);
+
+	if ((result = ncp_request(server, 73)) != 0)
+	{
+		ncp_unlock_server(server);
+		return result;
+	}
+
+	*bytes_written = to_write;
+
+	ncp_unlock_server(server);
+	return 0;
+}
+
diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/ncplib_kernel.h linux/fs/ncpfs/ncplib_kernel.h
--- v1.3.52/linux/fs/ncpfs/ncplib_kernel.h	Thu Jan  1 02:00:00 1970
+++ linux/fs/ncpfs/ncplib_kernel.h	Tue Jan  2 14:18:43 1996
@@ -0,0 +1,156 @@
+#ifndef _NCPLIB_H
+#define _NCPLIB_H
+
+#include <linux/fs.h>
+#include <linux/ncp.h>
+#include <linux/ncp_fs.h>
+#include <linux/ncp_fs_sb.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <asm/segment.h>
+#include <asm/string.h>
+
+#include <linux/ncp.h>
+
+int
+ncp_negotiate_buffersize(struct ncp_server *server, int size,
+			 int *target);
+int
+ncp_get_encryption_key(struct ncp_server *server,
+		       char *target);
+int
+ncp_get_bindery_object_id(struct ncp_server *server,
+			  int object_type, char *object_name,
+			  struct ncp_bindery_object *target);
+int
+ncp_login_encrypted(struct ncp_server *server,
+		    struct ncp_bindery_object *object,
+		    unsigned char *key,
+		    unsigned char *passwd);
+int
+ncp_login_user(struct ncp_server *server,
+	       unsigned char *username,
+	       unsigned char *password);
+int
+ncp_get_volume_info_with_number(struct ncp_server *server, int n,
+				struct ncp_volume_info *target);
+
+int
+ncp_get_volume_number(struct ncp_server *server, const char *name,
+		      int *target);
+
+int
+ncp_file_search_init(struct ncp_server *server,
+		     int dir_handle, const char *path,
+		     struct ncp_filesearch_info *target);
+
+int
+ncp_file_search_continue(struct ncp_server *server,
+			 struct ncp_filesearch_info *fsinfo,
+			 int attributes, const char *path,
+			 struct ncp_file_info *target);
+
+int
+ncp_get_finfo(struct ncp_server *server,
+	      int dir_handle, const char *path, const char *name,
+	      struct ncp_file_info *target);
+
+int
+ncp_open_file(struct ncp_server *server,
+	      int dir_handle, const char *path,
+	      int attr, int access,
+	      struct ncp_file_info *target);
+int
+ncp_close_file(struct ncp_server *server, const char *file_id);
+
+int
+ncp_create_newfile(struct ncp_server *server,
+		   int dir_handle, const char *path,
+		   int attr,
+		   struct ncp_file_info *target);
+
+int
+ncp_create_file(struct ncp_server *server,
+		int dir_handle, const char *path,
+		int attr,
+		struct ncp_file_info *target);
+
+int
+ncp_erase_file(struct ncp_server *server,
+	       int dir_handle, const char *path,
+	       int attr);
+
+int
+ncp_rename_file(struct ncp_server *server,
+		int old_handle, const char *old_path,
+		int attr,
+		int new_handle, const char *new_path);
+
+int
+ncp_create_directory(struct ncp_server *server,
+		     int dir_handle, const char *path,
+		     int inherit_mask);
+
+int
+ncp_delete_directory(struct ncp_server *server,
+		     int dir_handle, const char *path);
+
+int
+ncp_rename_directory(struct ncp_server *server,
+		     int dir_handle,
+		     const char *old_path, const char *new_path);
+
+int
+ncp_read(struct ncp_server *server, const char *file_id,
+	 __u32 offset, __u16 to_read,
+	 char *target, int *bytes_read);
+
+int
+ncp_write(struct ncp_server *server, const char *file_id,
+	  __u32 offset, __u16 to_write,
+	  const char *source, int *bytes_written);
+
+int
+ncp_do_lookup(struct ncp_server *server,
+	      struct nw_info_struct *dir,
+	      char *path,	/* may only be one component */
+	      struct nw_info_struct *target);
+
+int
+ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
+				   struct nw_info_struct *file,
+				   __u32 info_mask,
+				   struct nw_modify_dos_info *info);
+
+int
+ncp_del_file_or_subdir(struct ncp_server *server,
+		       struct nw_info_struct *dir, char *name);
+
+int
+ncp_open_create_file_or_subdir(struct ncp_server *server,
+			       struct nw_info_struct *dir, char *name,
+			       int open_create_mode,
+			       __u32 create_attributes,
+			       int desired_acc_rights,
+			       struct nw_file_info *target);
+
+int
+ncp_initialize_search(struct ncp_server *server,
+		      struct nw_info_struct *dir,
+		      struct nw_search_sequence *target);
+
+int
+ncp_search_for_file_or_subdir(struct ncp_server *server,
+			      struct nw_search_sequence *seq,
+			      struct nw_info_struct *target);
+
+int
+ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
+			      struct nw_info_struct *old_dir, char *old_name,
+			      struct nw_info_struct *new_dir, char *new_name);
+
+
+#endif /* _NCPLIB_H */
diff -u --recursive --new-file v1.3.52/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c
--- v1.3.52/linux/fs/ncpfs/sock.c	Thu Jan  1 02:00:00 1970
+++ linux/fs/ncpfs/sock.c	Tue Jan  2 14:18:43 1996
@@ -0,0 +1,606 @@
+/*
+ *  linux/fs/ncp/sock.c
+ *
+ *  Copyright (C) 1992, 1993  Rick Sladkey
+ *
+ *  Modified 1995 by Volker Lendecke to be usable for ncp
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/ncp_fs.h>
+#include <linux/errno.h>
+#include <linux/socket.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <asm/segment.h>
+#include <linux/in.h>
+#include <linux/net.h>
+#include <linux/mm.h>
+#include <linux/netdevice.h>
+#include <linux/ipx.h>
+
+#include <linux/ncp.h>
+#include <linux/ncp_fs.h>
+#include <linux/ncp_fs_sb.h>
+#include <net/sock.h>
+
+
+#define _S(nr) (1<<((nr)-1))
+static int _recvfrom(struct socket *sock, unsigned char *ubuf,
+		     int size, int noblock, unsigned flags,
+		     struct sockaddr_ipx *sa, int *addr_len)
+{
+        struct iovec iov;
+        struct msghdr msg;
+
+        iov.iov_base = ubuf;
+        iov.iov_len  = size;
+
+        msg.msg_name      = (void *)sa;
+        msg.msg_namelen   = 0;
+        if (addr_len)
+                msg.msg_namelen = *addr_len;
+        msg.msg_accrights = NULL;
+        msg.msg_iov       = &iov;
+        msg.msg_iovlen    = 1;
+
+        return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len);
+}
+
+static int _sendto(struct socket *sock, const void *buff,
+		   int len, int nonblock, unsigned flags,
+		   struct sockaddr_ipx *sa, int addr_len)
+
+{
+        struct iovec iov;
+        struct msghdr msg;
+
+        iov.iov_base = (void *)buff;
+        iov.iov_len  = len;
+
+        msg.msg_name      = (void *)sa;
+        msg.msg_namelen   = addr_len;
+        msg.msg_accrights = NULL;
+        msg.msg_iov       = &iov;
+        msg.msg_iovlen    = 1;
+
+        return sock->ops->sendmsg(sock, &msg, len, nonblock, flags);
+}
+
+
+static void
+ncp_wdog_data_ready(struct sock *sk, int len)
+{
+	struct socket *sock = sk->socket;
+
+	if (!sk->dead)
+	{
+		unsigned char packet_buf[2];
+		struct sockaddr_ipx sender;
+		int addr_len = sizeof(struct sockaddr_ipx);
+		int result;
+		unsigned short fs;
+
+		fs = get_fs();
+		set_fs(get_ds());
+
+		result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0,
+				   &sender, &addr_len);
+
+		if (   (result != 2)
+		    || (packet_buf[1] != '?')
+		    /* How to check connection number here? */
+		    )
+		{
+			/* Error, throw away the complete packet */
+			_recvfrom(sock, (void *)packet_buf, 2, 1, 0,
+				  &sender, &addr_len);
+
+			printk("ncpfs: got strange packet on watchdog "
+			       "socket\n");
+			
+		}
+		else
+		{
+			int result;
+			DDPRINTK("ncpfs: got watchdog from:\n");
+			DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
+				" conn:%02X,type:%c\n",
+				htonl(sender.sipx_network),
+				sender.sipx_node[0], sender.sipx_node[1],
+				sender.sipx_node[2], sender.sipx_node[3],
+				sender.sipx_node[4], sender.sipx_node[5],
+				ntohs(sender.sipx_port),
+				packet_buf[0], packet_buf[1]);
+
+			packet_buf[1] = 'Y';
+			result = _sendto(sock, (void *)packet_buf, 2, 1, 0,
+					 &sender, sizeof(sender));
+			DDPRINTK("send result: %d\n", result);
+		}
+		set_fs(fs);
+	}
+}
+
+
+int
+ncp_catch_watchdog(struct ncp_server *server)
+{
+        struct file   *file;
+        struct inode  *inode;
+        struct socket *sock;
+        struct sock   *sk;
+
+        if (   (server == NULL)
+            || ((file  = server->wdog_filp) == NULL)
+            || ((inode = file->f_inode) == NULL)
+            || (!S_ISSOCK(inode->i_mode)))
+	{
+                printk("ncp_catch_watchdog: did not get valid server!\n");
+                server->data_ready = NULL;
+                return -EINVAL;
+        }
+
+        sock = &(inode->u.socket_i);
+
+        if (sock->type != SOCK_DGRAM)
+	{
+                printk("ncp_catch_watchdog: did not get SOCK_STREAM\n");
+                server->data_ready = NULL;
+                return -EINVAL;
+        }
+
+        sk   = (struct sock *)(sock->data);
+
+        if (sk == NULL)
+	{
+                printk("ncp_catch_watchdog: sk == NULL");
+                server->data_ready = NULL;
+                return -EINVAL;
+        }
+
+        DDPRINTK("ncp_catch_watchdog.: sk->d_r = %x, server->d_r = %x\n",
+                 (unsigned int)(sk->data_ready),
+                 (unsigned int)(server->data_ready));
+
+        if (sk->data_ready == ncp_wdog_data_ready)
+	{
+                printk("ncp_catch_watchdog: already done\n");
+                return -EINVAL;
+        }
+
+        server->data_ready = sk->data_ready;
+        sk->data_ready = ncp_wdog_data_ready;
+	sk->allocation = GFP_ATOMIC;
+        return 0;
+}
+                
+int
+ncp_dont_catch_watchdog(struct ncp_server *server)
+{
+        struct file   *file;
+        struct inode  *inode;
+        struct socket *sock;
+        struct sock   *sk;
+
+        if (   (server == NULL)
+            || ((file  = server->wdog_filp) == NULL)
+            || ((inode = file->f_inode) == NULL)
+            || (!S_ISSOCK(inode->i_mode)))
+	{
+                printk("ncp_dont_catch_watchdog: "
+                       "did not get valid server!\n");
+                return -EINVAL;
+        }
+
+        sock = &(inode->u.socket_i);
+
+        if (sock->type != SOCK_DGRAM)
+	{
+                printk("ncp_dont_catch_watchdog: did not get SOCK_STREAM\n");
+                return -EINVAL;
+        }
+
+        sk   = (struct sock *)(sock->data);
+
+        if (sk == NULL)
+	{
+                printk("ncp_dont_catch_watchdog: sk == NULL");
+                return -EINVAL;
+        }
+
+        if (server->data_ready == NULL)
+	{
+                printk("ncp_dont_catch_watchdog: "
+                       "server->data_ready == NULL\n");
+                return -EINVAL;
+        }
+
+        if (sk->data_ready != ncp_wdog_data_ready)
+	{
+                printk("ncp_dont_catch_watchdog: "
+                       "sk->data_callback != ncp_data_callback\n");
+                return -EINVAL;
+        }
+
+        DDPRINTK("ncp_dont_catch_watchdog: sk->d_r = %x, server->d_r = %x\n",
+                 (unsigned int)(sk->data_ready),
+                 (unsigned int)(server->data_ready));
+
+        sk->data_ready = server->data_ready;
+	sk->allocation = GFP_KERNEL;
+        server->data_ready = NULL;
+        return 0;
+}
+
+
+
+#define NCP_SLACK_SPACE 1024
+
+#define _S(nr) (1<<((nr)-1))
+
+static int
+do_ncp_rpc_call(struct ncp_server *server, int size)
+{
+	struct file *file;
+	struct inode *inode;
+	struct socket *sock;
+	unsigned short fs;
+	int result;
+	char *start = server->packet;
+	select_table wait_table;
+	struct select_table_entry entry;
+	int (*select) (struct inode *, struct file *, int, select_table *);
+	int init_timeout, max_timeout;
+	int timeout;
+	int retrans;
+	int major_timeout_seen;
+	char *server_name;
+	int n;
+	int addrlen;
+	unsigned long old_mask;
+
+	/* We have to check the result, so store the complete header */
+	struct ncp_request_header request =
+		*((struct ncp_request_header *)(server->packet));
+
+	struct ncp_reply_header reply;	
+
+
+	file = server->ncp_filp;
+	inode = file->f_inode;
+	select = file->f_op->select;
+	sock = &inode->u.socket_i;
+	if (!sock)
+	{
+		printk("ncp_rpc_call: socki_lookup failed\n");
+		return -EBADF;
+	}
+	init_timeout = server->m.time_out;
+	max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
+	retrans = server->m.retry_count;
+	major_timeout_seen = 0;
+	server_name = server->m.server_name;
+	old_mask = current->blocked;
+	current->blocked |= ~(_S(SIGKILL)
+#if 0
+		| _S(SIGSTOP)
+#endif
+		| ((server->m.flags & NCP_MOUNT_INTR)
+		? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL
+			? _S(SIGINT) : 0)
+		| (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL
+			? _S(SIGQUIT) : 0))
+		: 0));
+	fs = get_fs();
+	set_fs(get_ds());
+	for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1)
+	{
+		DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
+			htonl(server->m.serv_addr.sipx_network),
+			server->m.serv_addr.sipx_node[0],
+			server->m.serv_addr.sipx_node[1],
+			server->m.serv_addr.sipx_node[2],
+			server->m.serv_addr.sipx_node[3],
+			server->m.serv_addr.sipx_node[4],
+			server->m.serv_addr.sipx_node[5],
+			ntohs(server->m.serv_addr.sipx_port));
+		DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
+			"seq: %d",
+			request.type,
+			(request.conn_high << 8) + request.conn_low,
+			request.sequence);
+		DDPRINTK(" func: %d\n",
+			 request.function);
+
+		result = _sendto(sock, (void *) start, size, 0, 0,
+				 &(server->m.serv_addr),
+				 sizeof(server->m.serv_addr));
+		if (result < 0)
+		{
+			printk("ncp_rpc_call: send error = %d\n", result);
+			break;
+		}
+	re_select:
+		wait_table.nr = 0;
+		wait_table.entry = &entry;
+		current->state = TASK_INTERRUPTIBLE;
+		if (   !select(inode, file, SEL_IN, &wait_table)
+		    && !select(inode, file, SEL_IN, NULL))
+		{
+			if (timeout > max_timeout)
+			{
+			  /* JEJB/JSP 2/7/94
+			   * This is useful to see if the system is
+			   * hanging */
+			  printk("NCP max timeout reached on %s\n",
+				 server_name);
+			  timeout = max_timeout;
+			}
+			current->timeout = jiffies + timeout;
+			schedule();
+			remove_wait_queue(entry.wait_address, &entry.wait);
+			current->state = TASK_RUNNING;
+			if (current->signal & ~current->blocked)
+			{
+				current->timeout = 0;
+				result = -ERESTARTSYS;
+				break;
+			}
+			if (!current->timeout)
+			{
+				if (n < retrans)
+					continue;
+				if (server->m.flags & NCP_MOUNT_SOFT)
+				{
+					printk("NCP server %s not responding, "
+						"timed out\n", server_name);
+					result = -EIO;
+					break;
+				}
+				n = 0;
+				timeout = init_timeout;
+				init_timeout <<= 1;
+				if (!major_timeout_seen)
+				{
+				  printk("NCP server %s not responding, "
+					 "still trying\n", server_name);
+				}
+				major_timeout_seen = 1;
+				continue;
+			}
+			else
+				current->timeout = 0;
+		}
+		else if (wait_table.nr)
+			remove_wait_queue(entry.wait_address, &entry.wait);
+		current->state = TASK_RUNNING;
+		addrlen = 0;
+
+		/* Get the header from the next packet using a peek, so keep it
+		 * on the recv queue.  If it is wrong, it will be some reply
+		 * we don't now need, so discard it */
+		result = _recvfrom(sock, (void *)&reply,
+				   sizeof(reply), 1, MSG_PEEK,
+				   NULL, &addrlen);
+		if (result < 0)
+		{
+			if (result == -EAGAIN)
+			{
+				DPRINTK("ncp_rpc_call: bad select ready\n");
+				goto re_select;
+			}
+			if (result == -ECONNREFUSED)
+			{
+				DPRINTK("ncp_rpc_call: server playing coy\n");
+				goto re_select;
+			}
+			if (result != -ERESTARTSYS)
+			{
+				printk("ncp_rpc_call: recv error = %d\n",
+					-result);
+			}
+			break;
+		}
+		if (   (result     == sizeof(reply))
+		    && (reply.type == NCP_POSITIVE_ACK))
+		{
+			/* Throw away the packet */
+			DPRINTK("ncp_rpc_call: got positive acknowledge\n");
+			_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
+				  NULL, &addrlen);
+			goto re_select;
+		}
+
+		DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
+			"seq: %d\n",
+			reply.type,
+			(reply.conn_high << 8) + reply.conn_low,
+			reply.task,
+			reply.sequence);
+		
+		if (   (result          >= sizeof(reply))
+		    && (reply.type      == NCP_REPLY)
+		    && (   (request.type    == NCP_ALLOC_SLOT_REQUEST)
+			|| (   (reply.sequence  == request.sequence)
+			    && (reply.conn_low  == request.conn_low)
+/* seem to get wrong task from NW311 && (reply.task      == request.task)*/
+			    && (reply.conn_high == request.conn_high))))
+		{
+			if (major_timeout_seen)
+				printk("NCP server %s OK\n", server_name);
+			break;
+		}
+		/* JEJB/JSP 2/7/94
+		 * we have xid mismatch, so discard the packet and start
+		 * again.  What a hack! but I can't call recvfrom with
+		 * a null buffer yet. */
+		_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL,
+			  &addrlen);
+#if 1
+		printk("ncp_rpc_call: reply mismatch\n");
+#endif
+		goto re_select;
+	}
+	/* 
+	 * we have the correct reply, so read into the correct place and
+	 * return it
+	 */
+	result = _recvfrom(sock, (void *)start, server->packet_size,
+			   1, 0, NULL, &addrlen);
+	if (result < 0)
+	{
+		printk("NCP: notice message: result=%d\n", result);
+	}
+	else if (result < sizeof(struct ncp_reply_header))
+	{
+		printk("NCP: just caught a too small read memory size..., "
+		       "email to NET channel\n");
+		printk("NCP: result=%d,addrlen=%d\n", result, addrlen);
+		result = -EIO;
+	}
+
+	current->blocked = old_mask;
+	set_fs(fs);
+	return result;
+}
+
+
+/*
+ * We need the server to be locked here, so check!
+ */
+
+static int
+ncp_do_request(struct ncp_server *server, int size)
+{
+	if (server->lock == 0)
+	{
+		printk("ncpfs: Server not locked!\n");
+		return -EIO;
+	}
+
+	return do_ncp_rpc_call(server, size);
+}
+
+/* ncp_do_request assures that at least a complete reply header is
+ * received. It assumes that server->current_size contains the ncp
+ * request size */
+int
+ncp_request(struct ncp_server *server, int function)
+{
+	struct ncp_request_header *h
+		= (struct ncp_request_header *)(server->packet);
+	struct ncp_reply_header *reply
+		= (struct ncp_reply_header *)(server->packet);
+
+	int request_size = server->current_size
+		- sizeof(struct ncp_request_header);
+
+	int result;
+
+	if (server->has_subfunction != 0)
+	{
+		*(__u16 *)&(h->data[0]) = request_size - 2;
+	}
+
+	h->type = NCP_REQUEST;
+	
+	server->sequence += 1;
+	h->sequence  = server->sequence;
+	h->conn_low  = (server->connection) & 0xff;
+	h->conn_high = ((server->connection) & 0xff00) >> 8;
+	h->task      = (current->pid) & 0xff;
+	h->function  = function;
+
+	if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0)
+	{
+		DPRINTK("ncp_request_error: %d\n", result);
+		return result;
+	}
+
+	server->completion  = reply->completion_code;
+	server->conn_status = reply->connection_state;
+	server->reply_size  = result;
+	server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
+
+	result = reply->completion_code;
+
+	if (result != 0)
+	{
+		DPRINTK("ncp_completion_code: %d\n", result);
+	}
+	return result;	
+}
+
+int
+ncp_connect(struct ncp_server *server)
+{
+	struct ncp_request_header *h
+		= (struct ncp_request_header *)(server->packet);
+	int result;
+
+	h->type = NCP_ALLOC_SLOT_REQUEST;
+	
+	server->sequence = 0;
+	h->sequence  = server->sequence;
+	h->conn_low  = 0xff;
+	h->conn_high = 0xff;
+	h->task      = (current->pid) & 0xff;
+	h->function  = 0;
+
+	if ((result = ncp_do_request(server, sizeof(*h))) < 0)
+	{
+		return result;
+	}
+
+	server->sequence = 0;
+	server->connection = h->conn_low + (h->conn_high * 256);
+	return 0;
+}
+	
+int
+ncp_disconnect(struct ncp_server *server)
+{
+	struct ncp_request_header *h
+		= (struct ncp_request_header *)(server->packet);
+
+	h->type = NCP_DEALLOC_SLOT_REQUEST;
+	
+	server->sequence += 1;
+	h->sequence  = server->sequence;
+	h->conn_low  = (server->connection) & 0xff;
+	h->conn_high = ((server->connection) & 0xff00) >> 8;
+	h->task      = (current->pid) & 0xff;
+	h->function  = 0;
+
+	return ncp_do_request(server, sizeof(*h));
+}
+
+void
+ncp_lock_server(struct ncp_server *server)
+{
+#if 0
+	/* For testing, only 1 process */
+	if (server->lock != 0)
+	{
+		DPRINTK("ncpfs: server locked!!!\n");
+	}
+#endif
+        while (server->lock)
+		sleep_on(&server->wait);
+	server->lock = 1;
+}
+
+void
+ncp_unlock_server(struct ncp_server *server)
+{
+        if (server->lock != 1)
+	{
+                printk("ncp_unlock_server: was not locked!\n");
+        }
+
+        server->lock = 0;
+        wake_up(&server->wait);
+}
+        
diff -u --recursive --new-file v1.3.52/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.3.52/linux/fs/proc/array.c	Sat Dec 30 15:50:54 1995
+++ linux/fs/proc/array.c	Tue Jan  2 14:02:05 1996
@@ -41,6 +41,7 @@
 #include <linux/ioport.h>
 #include <linux/config.h>
 #include <linux/mm.h>
+#include <linux/pagemap.h>
 #ifdef CONFIG_APM
 #include <linux/apm_bios.h>
 #endif
@@ -276,10 +277,10 @@
 
 	si_meminfo(&i);
 	si_swapinfo(&i);
-	return sprintf(buffer, "        total:   used:    free:   shared:  buffers:\n"
-		"Mem:  %8lu %8lu %8lu %8lu %8lu\n"
+	return sprintf(buffer, "        total:    used:    free:  shared: buffers:  cached:\n"
+		"Mem:  %8lu %8lu %8lu %8lu %8lu %8lu\n"
 		"Swap: %8lu %8lu %8lu\n",
-		i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram,
+		i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE,
 		i.totalswap, i.totalswap-i.freeswap, i.freeswap);
 }
 
diff -u --recursive --new-file v1.3.52/linux/fs/read_write.c linux/fs/read_write.c
--- v1.3.52/linux/fs/read_write.c	Mon Nov 27 12:48:32 1995
+++ linux/fs/read_write.c	Sat Dec 30 12:09:08 1995
@@ -263,6 +263,7 @@
 
 asmlinkage int sys_writev(unsigned long fd, const struct iovec * vector, long count)
 {
+	int error;
 	struct file * file;
 	struct inode * inode;
 
@@ -270,5 +271,8 @@
 		return -EBADF;
 	if (!(file->f_mode & 2))
 		return -EBADF;
-	return do_readv_writev(VERIFY_READ, inode, file, vector, count);
+	down(&inode->i_sem);
+	error = do_readv_writev(VERIFY_READ, inode, file, vector, count);
+	up(&inode->i_sem);
+	return error;
 }
diff -u --recursive --new-file v1.3.52/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v1.3.52/linux/fs/smbfs/dir.c	Tue Dec 26 04:45:40 1995
+++ linux/fs/smbfs/dir.c	Tue Jan  2 14:18:43 1996
@@ -501,7 +501,7 @@
                 return NULL;
         }
 
-        new_inode_info->state = INODE_LOOKED_UP;
+        new_inode_info->state = SMB_INODE_LOOKED_UP;
         new_inode_info->nused = 0;
         new_inode_info->dir   = SMB_INOP(dir);
 
@@ -539,8 +539,8 @@
                 return;
         }
 
-        i->state = INODE_CACHED;
-        while ((i->nused == 0) && (i->state == INODE_CACHED)) {
+        i->state = SMB_INODE_CACHED;
+        while ((i->nused == 0) && (i->state == SMB_INODE_CACHED)) {
                 struct smb_inode_info *dir = i->dir;
 
                 i->next->prev = i->prev;
@@ -565,7 +565,7 @@
         root->finfo.len  = strlen(root->finfo.path);
         root->finfo.opened = 0;
 
-        root->state = INODE_LOOKED_UP;
+        root->state = SMB_INODE_LOOKED_UP;
         root->nused = 1;
         root->dir   = NULL;
         root->next = root->prev = root;
@@ -690,8 +690,8 @@
 
         if (result_info != 0) {
 
-                if (result_info->state == INODE_CACHED)
-                        result_info->state = INODE_LOOKED_UP;
+                if (result_info->state == SMB_INODE_CACHED)
+                        result_info->state = SMB_INODE_LOOKED_UP;
 
                 put_pname(name);
 
diff -u --recursive --new-file v1.3.52/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v1.3.52/linux/fs/smbfs/file.c	Tue Dec 26 04:45:40 1995
+++ linux/fs/smbfs/file.c	Tue Jan  2 14:18:43 1996
@@ -17,6 +17,11 @@
 #include <linux/smb_fs.h>
 #include <linux/malloc.h>
 
+static inline int min(int a, int b)
+{
+	return a<b ? a : b;
+}
+
 static int 
 smb_fsync(struct inode *inode, struct file *file)
 {
diff -u --recursive --new-file v1.3.52/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v1.3.52/linux/fs/smbfs/inode.c	Sat Nov 11 17:41:34 1995
+++ linux/fs/smbfs/inode.c	Tue Jan  2 14:18:43 1996
@@ -62,13 +62,13 @@
 
         do {
                 if (inode_info == check_info) {
-                        if (check_info->state == INODE_LOOKED_UP) {
+                        if (check_info->state == SMB_INODE_LOOKED_UP) {
                                 DDPRINTK("smb_read_inode: found it!\n");
                                 goto good;
                         }
                         else {
                                 printk("smb_read_inode: "
-                                       "state != INODE_LOOKED_UP\n");
+                                       "state != SMB_INODE_LOOKED_UP\n");
                                 return;
                         }
                 }
@@ -82,7 +82,7 @@
 
  good:
 #endif
-        inode_info->state = INODE_VALID;
+        inode_info->state = SMB_INODE_VALID;
 
         SMB_INOP(inode) = inode_info;
 
diff -u --recursive --new-file v1.3.52/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- v1.3.52/linux/fs/smbfs/proc.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/smbfs/proc.c	Tue Jan  2 14:18:44 1996
@@ -32,6 +32,11 @@
 void smb_printerr(int class, int num);
 static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc);
 
+static inline int min(int a, int b)
+{
+	return a<b ? a : b;
+}
+
 /*****************************************************************************/
 /*                                                                           */
 /*  Encoding/Decoding section                                                */
diff -u --recursive --new-file v1.3.52/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- v1.3.52/linux/include/asm-i386/bugs.h	Sun Dec 17 11:43:22 1995
+++ linux/include/asm-i386/bugs.h	Tue Jan  2 15:11:04 1996
@@ -112,18 +112,17 @@
 
 static void check_tlb(void)
 {
+#ifndef CONFIG_M386
 	/*
 	 * 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;
 	}
+#endif
 }
 
 static void check_bugs(void)
diff -u --recursive --new-file v1.3.52/linux/include/asm-i386/byteorder.h linux/include/asm-i386/byteorder.h
--- v1.3.52/linux/include/asm-i386/byteorder.h	Wed Dec 27 09:12:14 1995
+++ linux/include/asm-i386/byteorder.h	Tue Jan  2 15:11:55 1996
@@ -27,7 +27,7 @@
 extern __inline__ unsigned long int
 __ntohl(unsigned long int x)
 {
-#if defined(CONFIG_M486) && defined(__KERNEL__)
+#if defined(__KERNEL__) && !defined(CONFIG_M386)
 	__asm__("bswap %0" : "=r" (x) : "0" (x));
 #else
 	__asm__("xchgb %b0,%h0\n\t"	/* swap lower bytes	*/
diff -u --recursive --new-file v1.3.52/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v1.3.52/linux/include/asm-i386/pgtable.h	Sun Dec 17 11:43:22 1995
+++ linux/include/asm-i386/pgtable.h	Tue Jan  2 15:13:12 1996
@@ -35,11 +35,11 @@
 #define __invalidate() \
 __asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
 
-#ifdef CONFIG_M486
+#ifdef CONFIG_M386
+#define __invalidate_one(addr) invalidate()
+#else
 #define __invalidate_one(addr) \
 __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
-#else
-#define __invalidate_one(addr) invalidate()
 #endif
  
 #ifndef __SMP__
diff -u --recursive --new-file v1.3.52/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v1.3.52/linux/include/linux/interrupt.h	Sun Sep  3 12:27:02 1995
+++ linux/include/linux/interrupt.h	Sat Dec 30 21:00:41 1995
@@ -78,7 +78,7 @@
  * 7. service the device to clear its pending interrupt.
  * 8. loop again if paranoia is required.
  *
- * probe_irq_on() returns a mask of snarfed irq's.
+ * probe_irq_on() returns a mask of allocated irq's.
  *
  * probe_irq_off() takes the mask as a parameter,
  * and returns the irq number which occurred,
diff -u --recursive --new-file v1.3.52/linux/include/linux/ioport.h linux/include/linux/ioport.h
--- v1.3.52/linux/include/linux/ioport.h	Fri Nov 17 08:42:28 1995
+++ linux/include/linux/ioport.h	Sat Dec 30 21:00:41 1995
@@ -13,12 +13,11 @@
 #define HAVE_PORTRESERVE
 /*
  * Call check_region() before probing for your hardware.
- * Once you have found you hardware, register it with snarf_region().
+ * Once you have found you hardware, register it with request_region().
  * If you unload the driver, use release_region to free ports.
  */
 extern void reserve_setup(char *str, int *ints);
 extern int check_region(unsigned int from, unsigned int extent);
-extern void snarf_region(unsigned int from, unsigned int extent);
 extern void request_region(unsigned int from, unsigned int extent,const char *name);
 extern void release_region(unsigned int from, unsigned int extent);
 extern int get_ioport_list(char *);
diff -u --recursive --new-file v1.3.52/linux/include/linux/mm.h linux/include/linux/mm.h
--- v1.3.52/linux/include/linux/mm.h	Tue Dec 26 04:45:41 1995
+++ linux/include/linux/mm.h	Tue Jan  2 12:20:05 1996
@@ -109,8 +109,8 @@
 typedef struct page {
 	unsigned int count;
 	unsigned dirty:16,
-		 age:6,
-		 unused:9,
+		 age:8,
+		 unused:7,
 		 reserved:1;
 	unsigned long offset;
 	struct inode *inode;
@@ -137,7 +137,7 @@
 };
 
 extern struct mem_list free_area_list[NR_MEM_LISTS];
-extern unsigned char * free_area_map[NR_MEM_LISTS];
+extern unsigned int * free_area_map[NR_MEM_LISTS];
 
 /*
  * This is timing-critical - most of the time in getting a new page
diff -u --recursive --new-file v1.3.52/linux/include/linux/ncp.h linux/include/linux/ncp.h
--- v1.3.52/linux/include/linux/ncp.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/ncp.h	Tue Jan  2 14:18:44 1996
@@ -0,0 +1,298 @@
+/*
+ *  ncp_fs.h
+ *
+ *  Copyright (C) 1995 by Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_NCP_H
+#define _LINUX_NCP_H
+
+#include <linux/types.h>
+#include <linux/ipx.h>
+
+#define NCP_PTYPE                (0x11)
+#define NCP_PORT                 (0x0451)
+
+#define NCP_ALLOC_SLOT_REQUEST   (0x1111)
+#define NCP_REQUEST              (0x2222)
+#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
+
+struct ncp_request_header {
+	__u16   type      __attribute__ ((packed));
+	__u8    sequence  __attribute__ ((packed));
+	__u8    conn_low  __attribute__ ((packed));
+	__u8    task      __attribute__ ((packed));
+	__u8    conn_high __attribute__ ((packed));
+	__u8    function  __attribute__ ((packed));
+	__u8    data[0]   __attribute__ ((packed));
+};
+
+#define NCP_REPLY                (0x3333)
+#define NCP_POSITIVE_ACK         (0x9999)
+
+struct ncp_reply_header {
+	__u16   type             __attribute__ ((packed));
+	__u8    sequence         __attribute__ ((packed));
+	__u8    conn_low         __attribute__ ((packed));
+	__u8    task             __attribute__ ((packed));
+	__u8    conn_high        __attribute__ ((packed));
+	__u8    completion_code  __attribute__ ((packed));
+	__u8    connection_state __attribute__ ((packed));
+	__u8    data[0]          __attribute__ ((packed));
+};
+
+
+#define NCP_BINDERY_USER (0x0001)
+#define NCP_BINDERY_UGROUP (0x0002)
+#define NCP_BINDERY_PQUEUE (0x0003)
+#define NCP_BINDERY_FSERVER (0x0004)
+#define NCP_BINDERY_NAME_LEN (48)
+struct ncp_bindery_object {
+	__u32   object_id;
+	__u16   object_type;
+	__u8    object_name[NCP_BINDERY_NAME_LEN];
+	__u8    object_flags;
+	__u8    object_security;
+	__u8    object_has_prop;
+};
+
+struct nw_property {
+	__u8    value[128];
+	__u8    more_flag;
+	__u8    property_flag;
+};
+
+struct prop_net_address {
+	__u32 network                __attribute__ ((packed));
+	__u8  node[IPX_NODE_LEN]     __attribute__ ((packed));
+	__u16 port                   __attribute__ ((packed));
+};
+
+#define NCP_VOLNAME_LEN (16)
+#define NCP_NUMBER_OF_VOLUMES (64)
+struct ncp_volume_info {
+	__u32   total_blocks;
+	__u32   free_blocks;
+	__u32   purgeable_blocks;
+	__u32   not_yet_purgeable_blocks;
+	__u32   total_dir_entries;
+	__u32   available_dir_entries;
+	__u8    sectors_per_block;
+	char    volume_name[NCP_VOLNAME_LEN+1];
+};
+
+struct ncp_filesearch_info {
+	__u8    volume_number;
+	__u16   directory_id;
+	__u16   sequence_no;
+	__u8    access_rights;
+};
+
+#define NCP_MAX_FILENAME 14
+
+/* these define the attribute byte as seen by NCP */
+#define aRONLY     (1L<<0)
+#define aHIDDEN    (1L<<1)
+#define aSYSTEM    (1L<<2)
+#define aEXECUTE   (1L<<3)
+#define aDIR       (1L<<4)
+#define aARCH      (1L<<5)
+
+#define AR_READ      (0x01)
+#define AR_WRITE     (0x02)
+#define AR_EXCLUSIVE (0x20)
+
+#define NCP_FILE_ID_LEN 6
+struct ncp_file_info {
+	__u8    file_id[NCP_FILE_ID_LEN];
+        char    file_name[NCP_MAX_FILENAME+1];
+	__u8    file_attributes;
+	__u8    file_mode;
+	__u32   file_length;
+	__u16   creation_date;
+	__u16   access_date;
+	__u16   update_date;
+	__u16   update_time;
+};
+
+
+/*  Defines for ReturnInformationMask */
+#define RIM_NAME	      (0x0001L)
+#define RIM_SPACE_ALLOCATED   (0x0002L)
+#define RIM_ATTRIBUTES	      (0x0004L)
+#define RIM_DATA_SIZE	      (0x0008L)
+#define RIM_TOTAL_SIZE	      (0x0010L)
+#define RIM_EXT_ATTR_INFO     (0x0020L)
+#define RIM_ARCHIVE	      (0x0040L)
+#define RIM_MODIFY	      (0x0080L)
+#define RIM_CREATION	      (0x0100L)
+#define RIM_OWNING_NAMESPACE  (0x0200L)
+#define RIM_DIRECTORY	      (0x0400L)
+#define RIM_RIGHTS	      (0x0800L)
+#define RIM_ALL 	      (0x0FFFL)
+#define RIM_COMPRESSED_INFO   (0x80000000L)
+
+/* open/create modes */
+#define OC_MODE_OPEN	  0x01
+#define OC_MODE_TRUNCATE  0x02
+#define OC_MODE_REPLACE   0x02
+#define OC_MODE_CREATE	  0x08
+
+/* open/create results */
+#define OC_ACTION_NONE	   0x00
+#define OC_ACTION_OPEN	   0x01
+#define OC_ACTION_CREATE   0x02
+#define OC_ACTION_TRUNCATE 0x04
+#define OC_ACTION_REPLACE  0x04
+
+/* access rights attributes */
+#ifndef AR_READ_ONLY
+#define AR_READ_ONLY	   0x0001
+#define AR_WRITE_ONLY	   0x0002
+#define AR_DENY_READ	   0x0004
+#define AR_DENY_WRITE	   0x0008
+#define AR_COMPATIBILITY   0x0010
+#define AR_WRITE_THROUGH   0x0040
+#define AR_OPEN_COMPRESSED 0x0100
+#endif
+
+struct nw_info_struct
+{
+	__u32 spaceAlloc                  __attribute__ ((packed));
+	__u32 attributes                  __attribute__ ((packed));
+	__u16 flags                       __attribute__ ((packed));
+	__u32 dataStreamSize              __attribute__ ((packed));
+	__u32 totalStreamSize             __attribute__ ((packed));
+	__u16 numberOfStreams             __attribute__ ((packed));
+	__u16 creationTime                __attribute__ ((packed));
+	__u16 creationDate                __attribute__ ((packed));
+	__u32 creatorID                   __attribute__ ((packed));
+	__u16 modifyTime                  __attribute__ ((packed));
+	__u16 modifyDate                  __attribute__ ((packed));
+	__u32 modifierID                  __attribute__ ((packed));
+	__u16 lastAccessDate              __attribute__ ((packed));
+	__u16 archiveTime                 __attribute__ ((packed));
+	__u16 archiveDate                 __attribute__ ((packed));
+	__u32 archiverID                  __attribute__ ((packed));
+	__u16 inheritedRightsMask         __attribute__ ((packed));
+	__u32 dirEntNum                   __attribute__ ((packed));
+	__u32 DosDirNum                   __attribute__ ((packed));
+	__u32 volNumber                   __attribute__ ((packed));
+	__u32 EADataSize                  __attribute__ ((packed));
+	__u32 EAKeyCount                  __attribute__ ((packed));
+	__u32 EAKeySize                   __attribute__ ((packed));
+	__u32 NSCreator                   __attribute__ ((packed));
+	__u8  nameLen                     __attribute__ ((packed));
+	__u8  entryName[256]              __attribute__ ((packed));
+};
+
+/* modify mask - use with MODIFY_DOS_INFO structure */
+#define DM_ATTRIBUTES		  (0x0002L)
+#define DM_CREATE_DATE		  (0x0004L)
+#define DM_CREATE_TIME		  (0x0008L)
+#define DM_CREATOR_ID		  (0x0010L)
+#define DM_ARCHIVE_DATE 	  (0x0020L)
+#define DM_ARCHIVE_TIME 	  (0x0040L)
+#define DM_ARCHIVER_ID		  (0x0080L)
+#define DM_MODIFY_DATE		  (0x0100L)
+#define DM_MODIFY_TIME		  (0x0200L)
+#define DM_MODIFIER_ID		  (0x0400L)
+#define DM_LAST_ACCESS_DATE	  (0x0800L)
+#define DM_INHERITED_RIGHTS_MASK  (0x1000L)
+#define DM_MAXIMUM_SPACE	  (0x2000L)
+
+struct nw_modify_dos_info
+{
+	__u32 attributes                  __attribute__ ((packed));
+	__u16 creationDate                __attribute__ ((packed));
+	__u16 creationTime                __attribute__ ((packed));
+	__u32 creatorID                   __attribute__ ((packed));
+	__u16 modifyDate                  __attribute__ ((packed));
+	__u16 modifyTime                  __attribute__ ((packed));
+	__u32 modifierID                  __attribute__ ((packed));
+	__u16 archiveDate                 __attribute__ ((packed));
+	__u16 archiveTime                 __attribute__ ((packed));
+	__u32 archiverID                  __attribute__ ((packed));
+	__u16 lastAccessDate              __attribute__ ((packed));
+	__u16 inheritanceGrantMask        __attribute__ ((packed));
+	__u16 inheritanceRevokeMask       __attribute__ ((packed));
+	__u32 maximumSpace                __attribute__ ((packed));
+};
+
+struct nw_file_info {
+	struct nw_info_struct i;
+	int   opened;
+	int   access;
+	__u32 server_file_handle          __attribute__ ((packed));
+	__u8  open_create_action          __attribute__ ((packed));
+	__u8  file_handle[6]              __attribute__ ((packed));
+};
+
+struct nw_search_sequence {
+	__u8  volNumber                   __attribute__ ((packed));
+	__u32 dirBase                     __attribute__ ((packed));
+	__u32 sequence                    __attribute__ ((packed));
+};
+
+struct nw_queue_job_entry {
+	__u16 InUse                       __attribute__ ((packed));
+	__u32 prev                        __attribute__ ((packed));
+	__u32 next                        __attribute__ ((packed));
+	__u32 ClientStation               __attribute__ ((packed));
+	__u32 ClientTask                  __attribute__ ((packed));
+	__u32 ClientObjectID              __attribute__ ((packed));
+	__u32 TargetServerID              __attribute__ ((packed));
+	__u8  TargetExecTime[6]           __attribute__ ((packed));
+	__u8  JobEntryTime[6]             __attribute__ ((packed));
+	__u32 JobNumber                   __attribute__ ((packed));
+	__u16 JobType                     __attribute__ ((packed));
+	__u16 JobPosition                 __attribute__ ((packed));
+	__u16 JobControlFlags             __attribute__ ((packed));
+	__u8  FileNameLen                 __attribute__ ((packed));
+	char  JobFileName[13]             __attribute__ ((packed));
+	__u32 JobFileHandle               __attribute__ ((packed));
+	__u32 ServerStation               __attribute__ ((packed));
+	__u32 ServerTaskNumber            __attribute__ ((packed));
+	__u32 ServerObjectID              __attribute__ ((packed));
+	char  JobTextDescription[50]      __attribute__ ((packed));
+	char  ClientRecordArea[152]       __attribute__ ((packed));
+};
+
+struct queue_job {
+	struct nw_queue_job_entry j;
+	__u8 file_handle[6];
+};
+
+#define QJE_OPER_HOLD	0x80
+#define QJE_USER_HOLD	0x40
+#define QJE_ENTRYOPEN	0x20
+#define QJE_SERV_RESTART    0x10
+#define QJE_SERV_AUTO	    0x08
+
+/* ClientRecordArea for print jobs */
+
+#define   KEEP_ON        0x0400
+#define   NO_FORM_FEED   0x0800
+#define   NOTIFICATION   0x1000
+#define   DELETE_FILE    0x2000
+#define   EXPAND_TABS    0x4000
+#define   PRINT_BANNER   0x8000
+
+struct print_job_record {
+    __u8  Version                         __attribute__ ((packed));
+    __u8  TabSize                         __attribute__ ((packed));
+    __u16 Copies                          __attribute__ ((packed));
+    __u16 CtrlFlags                       __attribute__ ((packed));
+    __u16 Lines                           __attribute__ ((packed));
+    __u16 Rows                            __attribute__ ((packed));
+    char  FormName[16]                    __attribute__ ((packed));
+    __u8  Reserved[6]                     __attribute__ ((packed));
+    char  BannerName[13]                  __attribute__ ((packed));
+    char  FnameBanner[13]                 __attribute__ ((packed));
+    char  FnameHeader[14]                 __attribute__ ((packed));
+    char  Path[80]                        __attribute__ ((packed));
+};
+
+
+#endif /* _LINUX_NCP_H */
diff -u --recursive --new-file v1.3.52/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h
--- v1.3.52/linux/include/linux/ncp_fs.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/ncp_fs.h	Tue Jan  2 15:21:45 1996
@@ -0,0 +1,145 @@
+/*
+ *  ncp_fs.h
+ *
+ *  Copyright (C) 1995 by Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_NCP_FS_H
+#define _LINUX_NCP_FS_H
+
+#include <linux/fs.h>
+#include <linux/in.h>
+#include <linux/types.h>
+
+#include <linux/ncp_mount.h>
+#include <linux/ncp_fs_sb.h>
+#include <linux/ncp_fs_i.h>
+
+/*
+ * ioctl commands
+ */
+
+struct ncp_ioctl_request {
+	unsigned int   function;
+	unsigned int   size;
+	char          *data;
+};
+
+#define	NCP_IOC_NCPREQUEST		_IOR('n', 1, unsigned char *)
+#define	NCP_IOC_GETMOUNTUID		_IOR('u', 1, uid_t)
+
+/*
+ * The packet size to allocate. One page should be enough.
+ */
+#define NCP_PACKET_SIZE 4070
+
+#define NCP_MAXPATHLEN 255
+#define NCP_MAXNAMELEN 14
+
+#ifdef __KERNEL__
+
+/* The readdir cache size controls how many directory entries are
+ * cached.
+ */
+#define NCP_READDIR_CACHE_SIZE        64
+
+
+#define NCP_MAX_RPC_TIMEOUT (60) /* 6 seconds */
+
+/* Guess, what 0x564c is :-) */
+#define NCP_SUPER_MAGIC  0x564c
+
+
+#define NCP_SBP(sb)          ((struct ncp_server *)((sb)->u.generic_sbp))
+#define NCP_INOP(inode)      ((struct ncp_inode_info *)((inode)->u.generic_ip))
+
+#define NCP_SERVER(inode)    NCP_SBP((inode)->i_sb)
+#define NCP_FINFO(inode)     (&(NCP_INOP(inode)->finfo))
+#define NCP_ISTRUCT(inode)   (&(NCP_FINFO(inode)->i))
+
+#ifdef DEBUG_NCP_MALLOC
+
+#include <linux/malloc.h>
+
+extern int ncp_malloced;
+extern int ncp_current_malloced;
+
+static inline void *
+ncp_kmalloc(unsigned int size, int priority)
+{
+        ncp_malloced += 1;
+        ncp_current_malloced += 1;
+        return kmalloc(size, priority);
+}
+
+static inline void
+ncp_kfree_s(void *obj, int size)
+{
+        ncp_current_malloced -= 1;
+        kfree_s(obj, size);
+}
+
+#else /* DEBUG_NCP_MALLOC */
+
+#define ncp_kmalloc(s,p) kmalloc(s,p)
+#define ncp_kfree_s(o,s) kfree_s(o,s)
+
+#endif /* DEBUG_NCP_MALLOC */
+
+#if DEBUG_NCP > 0
+#define DPRINTK(format, args...) printk(format , ## args)
+#else
+#define DPRINTK(format, args...)
+#endif
+
+#if DEBUG_NCP > 1
+#define DDPRINTK(format, args...) printk(format , ## args)
+#else
+#define DDPRINTK(format, args...)
+#endif
+
+
+/* linux/fs/ncpfs/file.c */
+extern struct inode_operations ncp_file_inode_operations;
+int ncp_make_open(struct inode *i, int right);
+
+/* linux/fs/ncpfs/dir.c */
+extern struct inode_operations ncp_dir_inode_operations;
+void ncp_free_inode_info(struct ncp_inode_info *i);
+void ncp_free_all_inodes(struct ncp_server *server);
+void ncp_init_root(struct ncp_server *server);
+int  ncp_stat_root(struct ncp_server *server);
+void ncp_init_dir_cache(void);
+void ncp_invalid_dir_cache(unsigned long ino);
+void ncp_invalidate_all_inodes(struct ncp_server *server);
+void ncp_free_dir_cache(void);
+int  ncp_date_dos2unix(__u16 time, __u16 date);
+void ncp_date_unix2dos(int unix_date, __u16 *time, __u16 *date);
+
+
+/* linux/fs/ncpfs/ioctl.c */
+int ncp_ioctl (struct inode * inode, struct file * filp,
+               unsigned int cmd, unsigned long arg);
+
+/* linux/fs/ncpfs/inode.c */
+struct super_block *ncp_read_super(struct super_block *sb,
+                                   void *raw_data, int silent);
+void ncp_invalidate_connection(struct ncp_server *server);
+int ncp_conn_is_valid(struct ncp_server *server);
+
+/* linux/fs/ncpfs/sock.c */
+int ncp_request(struct ncp_server *server, int function);
+int ncp_connect(struct ncp_server *server);
+int ncp_disconnect(struct ncp_server *server);
+int ncp_catch_watchdog(struct ncp_server *server);
+int ncp_dont_catch_watchdog(struct ncp_server *server);
+void ncp_lock_server(struct ncp_server *server);
+void ncp_unlock_server(struct ncp_server *server);
+
+/* linux/fs/ncpfs/mmap.c */
+int ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_NCP_FS_H */
diff -u --recursive --new-file v1.3.52/linux/include/linux/ncp_fs_i.h linux/include/linux/ncp_fs_i.h
--- v1.3.52/linux/include/linux/ncp_fs_i.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/ncp_fs_i.h	Tue Jan  2 14:18:44 1996
@@ -0,0 +1,35 @@
+/*
+ *  ncp_fs_i.h
+ *
+ *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_NCP_FS_I
+#define _LINUX_NCP_FS_I
+
+#include <linux/ncp.h>
+
+#ifdef __KERNEL__
+
+enum ncp_inode_state {
+        NCP_INODE_VALID = 19,	/* Inode currently in use */
+        NCP_INODE_LOOKED_UP,	/* directly before iget */
+        NCP_INODE_CACHED,	/* in a path to an inode which is in use */
+        NCP_INODE_INVALID
+};
+
+/*
+ * ncp fs inode data (in memory only)
+ */
+struct ncp_inode_info {
+        enum ncp_inode_state state;
+        int nused;              /* for directories:
+                                   number of references in memory */
+        struct ncp_inode_info *dir;
+        struct ncp_inode_info *next, *prev;
+	struct nw_file_info finfo;
+};
+
+#endif
+#endif
diff -u --recursive --new-file v1.3.52/linux/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h
--- v1.3.52/linux/include/linux/ncp_fs_sb.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/ncp_fs_sb.h	Tue Jan  2 14:18:44 1996
@@ -0,0 +1,61 @@
+/*
+ *  ncp_fs_sb.h
+ *
+ *  Copyright (C) 1995 by Volker Lendecke
+ *
+ */
+
+#ifndef _NCP_FS_SB
+#define _NCP_FS_SB
+
+#include <linux/ncp_mount.h>
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+
+#define NCP_DEFAULT_BUFSIZE 1024
+
+struct ncp_server {
+
+	struct ncp_mount_data m; /* Nearly all of the mount data is of
+				    interest for us later, so we store
+				    it completely. */
+
+	struct file *ncp_filp;	/* File pointer to ncp socket */
+
+	struct file *wdog_filp;	/* File pointer to wdog socket */
+	void *data_ready;	/* The wdog socket gets a new
+				   data_ready callback. We store the
+				   old one for checking purposes and
+				   to reset it on unmounting. */
+
+	u8         sequence;
+	u8         task;
+	u16        connection;	/* Remote connection number */
+
+	u8         completion;	/* Status message from server */
+	u8         conn_status;	/* Bit 4 = 1 ==> Server going down, no
+				   requests allowed anymore */
+
+	int        buffer_size;	/* Negotiated bufsize */
+
+	int        reply_size;	/* Size of last reply */
+
+	int        packet_size;
+	unsigned char *packet;	/* Here we prepare requests and
+				   receive replies */
+
+	int        lock;	/* To prevent mismatch in protocols. */
+	struct wait_queue *wait;
+
+	int        current_size; /* for packet preparation */
+	int        has_subfunction;
+	int        ncp_reply_size;
+
+        struct ncp_inode_info root;
+	char       root_path;	/* '\0' */
+};
+
+#endif /* __KERNEL__ */
+
+#endif
diff -u --recursive --new-file v1.3.52/linux/include/linux/ncp_mount.h linux/include/linux/ncp_mount.h
--- v1.3.52/linux/include/linux/ncp_mount.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/ncp_mount.h	Tue Jan  2 14:18:44 1996
@@ -0,0 +1,49 @@
+/*
+ *  ncp_mount.h
+ *
+ *  Copyright (C) 1995 by Volker Lendecke
+ *
+ */
+
+#ifndef _LINUX_NCP_MOUNT_H
+#define _LINUX_NCP_MOUNT_H
+
+#include <linux/types.h>
+#include <linux/ipx.h>
+#include <linux/ncp.h>
+#include <linux/ncp_fs_i.h>
+
+#define NCP_MOUNT_VERSION 1
+
+#define NCP_USERNAME_LEN (NCP_BINDERY_NAME_LEN)
+#define NCP_PASSWORD_LEN 20
+
+/* Values for flags */
+#define NCP_MOUNT_SOFT 0x0001
+#define NCP_MOUNT_INTR 0x0002
+
+struct ncp_mount_data {
+	int version;
+	unsigned int ncp_fd;	/* The socket to the ncp port */
+	unsigned int wdog_fd;	/* Watchdog packets come here */
+	unsigned int message_fd; /* Not used yet, maybe for messages */
+        uid_t mounted_uid;      /* Who may umount() this filesystem? */
+
+	struct sockaddr_ipx serv_addr;
+	unsigned char server_name[49];
+
+	unsigned char username[NCP_USERNAME_LEN+1];
+	unsigned char password[NCP_PASSWORD_LEN+1];
+
+	unsigned int time_out;	/* How long should I wait after
+				   sending a NCP request? */
+	unsigned int retry_count; /* And how often should I retry? */
+	unsigned int flags;
+
+        uid_t uid;
+        gid_t gid;
+        mode_t file_mode;
+        mode_t dir_mode;
+};
+
+#endif
diff -u --recursive --new-file v1.3.52/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v1.3.52/linux/include/linux/pagemap.h	Tue Dec 26 04:45:41 1995
+++ linux/include/linux/pagemap.h	Tue Jan  2 13:13:04 1996
@@ -13,7 +13,9 @@
 }
 
 #define PAGE_HASH_SIZE 257
+#define PAGE_AGE_VALUE 16
 
+extern unsigned long page_cache_size;
 extern struct page * page_hash_table[PAGE_HASH_SIZE];
 
 static inline unsigned long _page_hashfn(struct inode * inode, unsigned long offset)
@@ -33,6 +35,7 @@
 			continue;
 		if (page->offset != offset)
 			continue;
+		page->age = PAGE_AGE_VALUE | (page->age >> 1);
 		break;
 	}
 	return page;
@@ -42,6 +45,7 @@
 {
 	struct page **p = &page_hash(page->inode,page->offset);
 
+	page_cache_size--;
 	if (page->next_hash)
 		page->next_hash->prev_hash = page->prev_hash;
 	if (page->prev_hash)
@@ -55,6 +59,8 @@
 {
 	struct page **p = &page_hash(inode,page->offset);
 
+	page_cache_size++;
+	page->age = PAGE_AGE_VALUE;
 	page->prev_hash = NULL;
 	if ((page->next_hash = *p) != NULL)
 		page->next_hash->prev_hash = page;
diff -u --recursive --new-file v1.3.52/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- v1.3.52/linux/include/linux/smb_fs.h	Mon Aug 28 14:52:23 1995
+++ linux/include/linux/smb_fs.h	Tue Jan  2 15:21:45 1996
@@ -50,10 +50,6 @@
 #define SMB_HEADER_LEN   37     /* includes everything up to, but not
                                  * including smb_bcc */
 
-static inline int min(int a, int b) {
-  return a<b ? a : b;
-}
-
 #ifdef DEBUG_SMB_MALLOC
 
 #include <linux/malloc.h>
diff -u --recursive --new-file v1.3.52/linux/include/linux/smb_fs_i.h linux/include/linux/smb_fs_i.h
--- v1.3.52/linux/include/linux/smb_fs_i.h	Fri Jul  7 08:54:54 1995
+++ linux/include/linux/smb_fs_i.h	Tue Jan  2 14:18:44 1996
@@ -12,10 +12,10 @@
 #include <linux/smb.h>
 
 enum smb_inode_state {
-        INODE_VALID = 19,       /* Inode currently in use */
-        INODE_LOOKED_UP,        /* directly before iget */
-        INODE_CACHED,           /* in a path to an inode which is in use */
-        INODE_INVALID
+        SMB_INODE_VALID = 19,	/* Inode currently in use */
+        SMB_INODE_LOOKED_UP,	/* directly before iget */
+        SMB_INODE_CACHED,	/* in a path to an inode which is in use */
+        SMB_INODE_INVALID
 };
 
 /*
diff -u --recursive --new-file v1.3.52/linux/init/main.c linux/init/main.c
--- v1.3.52/linux/init/main.c	Sat Dec 30 15:50:55 1995
+++ linux/init/main.c	Sat Dec 30 16:02:55 1995
@@ -390,13 +390,10 @@
 static void parse_options(char *line)
 {
 	char *next;
-#ifdef CONFIG_ROOT_NFS
-	char *devnames[] = { "nfs", "hda", "hdb", "hdc", "hdd", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
-	int devnums[]    = { 0x0FF, 0x300, 0x340, 0x1600, 0x1640, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
-#else
-	static const char *devnames[] = { "hda", "hdb", "hdc", "hdd", "sda", "sdb", "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
-	static int devnums[]    = { 0x300, 0x340, 0x1600, 0x1640, 0x800, 0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
-#endif
+	char *devnames[] = { "nfs", "hda", "hdb", "hdc", "hdd", "sda", "sdb",
+		"sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
+	int devnums[]    = { 0x0FF, 0x300, 0x340, 0x1600, 0x1640, 0x800,
+		0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
 	int args, envs;
 	if (!*line)
 		return;
@@ -435,7 +432,7 @@
 			ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255);
 			if (line[0] == '/' || (line[0] >= '0' && line[0] <= '9')) {
 				strncpy(nfs_root_name, line, sizeof(nfs_root_name));
-				nfs_root_name[sizeof(nfs_root_name)] = '\0';
+				nfs_root_name[sizeof(nfs_root_name)-1] = '\0';
 				continue;
 			}
 			n = strlen(line) + strlen(NFS_ROOT);
diff -u --recursive --new-file v1.3.52/linux/kernel/module.c linux/kernel/module.c
--- v1.3.52/linux/kernel/module.c	Sat Dec 30 15:50:55 1995
+++ linux/kernel/module.c	Sun Dec 31 14:32:45 1995
@@ -812,5 +812,10 @@
 	return -ENOSYS;
 }
 
+int register_symtab(struct symbol_table *intab)
+{
+	return 0;
+}
+
 #endif	/* CONFIG_MODULES */
 
diff -u --recursive --new-file v1.3.52/linux/kernel/resource.c linux/kernel/resource.c
--- v1.3.52/linux/kernel/resource.c	Thu Jun  1 08:49:37 1995
+++ linux/kernel/resource.c	Sat Dec 30 21:00:41 1995
@@ -92,15 +92,6 @@
 	}
 }
 
-/*
- * This is for compatibility with older drivers.
- * It can be removed when all drivers call the new function.
- */
-void snarf_region(unsigned int from, unsigned int num)
-{
-	request_region(from,num,"No name given.");
-}
-
 /* 
  * Call this when the device driver is unloaded
  */
diff -u --recursive --new-file v1.3.52/linux/kernel/sys.c linux/kernel/sys.c
--- v1.3.52/linux/kernel/sys.c	Sat Nov 25 19:04:57 1995
+++ linux/kernel/sys.c	Tue Jan  2 13:41:06 1996
@@ -17,6 +17,7 @@
 #include <linux/stat.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/pagemap.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -452,6 +453,8 @@
 	 * fool it, but this should catch most mistakes.
 	 */
 	freepages = buffermem >> PAGE_SHIFT;
+	freepages += page_cache_size;
+	freepages >>= 1;
 	freepages += nr_free_pages;
 	freepages += nr_swap_pages;
 	freepages -= MAP_NR(high_memory) >> 4;
diff -u --recursive --new-file v1.3.52/linux/mm/filemap.c linux/mm/filemap.c
--- v1.3.52/linux/mm/filemap.c	Wed Dec 27 09:12:14 1995
+++ linux/mm/filemap.c	Tue Jan  2 13:30:37 1996
@@ -33,6 +33,7 @@
  * Shared mappings now work. 15.8.1995  Bruno.
  */
 
+unsigned long page_cache_size = 0;
 struct page * page_hash_table[PAGE_HASH_SIZE];
 
 /*
@@ -78,14 +79,21 @@
 	limit = MAP_NR(limit);
 	if (clock >= limit)
 		clock = 0;
-	priority = limit >> priority;
+	priority = (limit<<2) >> priority;
 	page = mem_map + clock;
 	while (priority-- > 0) {
-		if (page->inode && page->count == 1) {
-			remove_page_from_hash_queue(page);
-			remove_page_from_inode_queue(page);
-			free_page(page_address(page));
-			return 1;
+		if (page->inode) {
+			unsigned age = page->age;
+			/* if the page is shared, we juvenate it slightly */
+			if (page->count != 1)
+				age |= PAGE_AGE_VALUE;
+			page->age = age >> 1;
+			if (age <= PAGE_AGE_VALUE/2) {
+				remove_page_from_hash_queue(page);
+				remove_page_from_inode_queue(page);
+				free_page(page_address(page));
+				return 1;
+			}
 		}
 		page++;
 		clock++;
diff -u --recursive --new-file v1.3.52/linux/mm/memory.c linux/mm/memory.c
--- v1.3.52/linux/mm/memory.c	Tue Dec 26 04:45:41 1995
+++ linux/mm/memory.c	Tue Jan  2 07:34:22 1996
@@ -57,7 +57,7 @@
 int nr_swap_pages = 0;
 int nr_free_pages = 0;
 struct mem_list free_area_list[NR_MEM_LISTS];
-unsigned char * free_area_map[NR_MEM_LISTS];
+unsigned int * free_area_map[NR_MEM_LISTS];
 
 /*
  * We special-case the C-O-W ZERO_PAGE, because it's such
@@ -669,7 +669,7 @@
 	 * case where we use a fake user buffer with get_fs/set_fs()) we
 	 * don't expect to find the address in the user vm map.
 	 */
-	if (get_fs() == get_ds())
+	if (!size || get_fs() == get_ds())
 		return 0;
 
 	vma = find_vma(current, start);
diff -u --recursive --new-file v1.3.52/linux/mm/swap.c linux/mm/swap.c
--- v1.3.52/linux/mm/swap.c	Sat Dec 30 15:50:56 1995
+++ linux/mm/swap.c	Tue Jan  2 14:15:25 1996
@@ -44,7 +44,7 @@
 
 swap_control_t swap_control = {
 	20, 3, 1, 3,		/* Page aging */
-	10, 2, 2, 0,		/* Buffer aging */
+	10, 2, 2, 4,		/* Buffer aging */
 	32, 4,			/* Aging cluster */
 	8192, 8192,		/* Pageout and bufferout weights */
 	-200,			/* Buffer grace */
@@ -1343,7 +1343,7 @@
 		bitmap_size = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT + i);
 		bitmap_size = (bitmap_size + 7) >> 3;
 		bitmap_size = LONG_ALIGN(bitmap_size);
-		free_area_map[i] = (unsigned char *) start_mem;
+		free_area_map[i] = (unsigned int *) start_mem;
 		memset((void *) start_mem, 0, bitmap_size);
 		start_mem += bitmap_size;
 	}
