]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.53 1.3.53
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:28 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:28 +0000 (15:10 -0500)
82 files changed:
CREDITS
Documentation/CodingStyle [new file with mode: 0644]
Documentation/Configure.help
Makefile
arch/alpha/defconfig
arch/i386/Makefile
arch/i386/config.in
arch/i386/defconfig
arch/ppc/Makefile
arch/ppc/boot/Makefile
arch/ppc/boot/cortstrip.c [new file with mode: 0644]
arch/ppc/kernel/Makefile
arch/ppc/kernel/misc.S
arch/ppc/kernel/pci.c
arch/ppc/kernel/ppc_asm.tmpl
arch/ppc/kernel/process.c
arch/ppc/kernel/raw_printf.c
arch/ppc/kernel/setup.c
arch/ppc/kernel/stubs.c
arch/ppc/kernel/traps.c
arch/ppc/mm/Makefile
arch/ppc/mm/fault.c
arch/ppc/mm/init.c
drivers/block/Config.in
drivers/block/Makefile
drivers/block/rd.c
drivers/cdrom/sonycd535.c
drivers/net/ac3200.c
drivers/net/depca.c
drivers/net/ewrk3.c
drivers/net/ewrk3.h
drivers/net/lance.c
drivers/net/net_init.c
drivers/net/pi2.c
drivers/net/pt.c
drivers/net/skeleton.c
drivers/scsi/aha1740.c
drivers/scsi/scsi.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/seagate.c
drivers/scsi/ultrastor.c
fs/Config.in
fs/Makefile
fs/ext2/file.c
fs/filesystems.c
fs/inode.c
fs/ncpfs/Makefile [new file with mode: 0644]
fs/ncpfs/dir.c [new file with mode: 0644]
fs/ncpfs/file.c [new file with mode: 0644]
fs/ncpfs/inode.c [new file with mode: 0644]
fs/ncpfs/ioctl.c [new file with mode: 0644]
fs/ncpfs/mmap.c [new file with mode: 0644]
fs/ncpfs/ncplib_kernel.c [new file with mode: 0644]
fs/ncpfs/ncplib_kernel.h [new file with mode: 0644]
fs/ncpfs/sock.c [new file with mode: 0644]
fs/proc/array.c
fs/read_write.c
fs/smbfs/dir.c
fs/smbfs/file.c
fs/smbfs/inode.c
fs/smbfs/proc.c
include/asm-i386/bugs.h
include/asm-i386/byteorder.h
include/asm-i386/pgtable.h
include/linux/interrupt.h
include/linux/ioport.h
include/linux/mm.h
include/linux/ncp.h [new file with mode: 0644]
include/linux/ncp_fs.h [new file with mode: 0644]
include/linux/ncp_fs_i.h [new file with mode: 0644]
include/linux/ncp_fs_sb.h [new file with mode: 0644]
include/linux/ncp_mount.h [new file with mode: 0644]
include/linux/pagemap.h
include/linux/smb_fs.h
include/linux/smb_fs_i.h
init/main.c
kernel/module.c
kernel/resource.c
kernel/sys.c
mm/filemap.c
mm/memory.c
mm/swap.c

diff --git a/CREDITS b/CREDITS
index b9d9022b5a7cf7dd65fc8d6dee86b3fb9e30aad6..9dd0d7dc27b916797c7dacc1ee961f054b63d193 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -372,6 +372,14 @@ S: 25360 Georgia Tech Station
 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 --git a/Documentation/CodingStyle b/Documentation/CodingStyle
new file mode 100644 (file)
index 0000000..cdf3d47
--- /dev/null
@@ -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. 
index d23be7964185a04ef62ac0cfef174d32536c9c08..42439fa6904ba7ce5d35db957b1a9304a650f67e 100644 (file)
@@ -317,6 +317,14 @@ CONFIG_M486
   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 @@ CONFIG_SKB_LARGE
 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 @@ CONFIG_SYSV_FS
   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
@@ -2023,6 +2032,18 @@ CONFIG_SMB_FS
   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
   This is a card which gives you many serial ports. You would need
index 72024eeceedcd6e0a7968570f9e7af20a5f38b5d..a0c54c4a1d9df323486008068b30167151645f88 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 52
+SUBLEVEL = 53
 
 ARCH = i386
 
@@ -266,6 +266,7 @@ modules_install:
        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; \
index 64b9c8c6dbceb53c2f613848dcbb0a38e1f8f5d9..324b6e10ec445182761a9bda79df9096f98ceae9 100644 (file)
@@ -22,6 +22,7 @@ CONFIG_ALPHA_CABRIOLET=y
 # 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 @@ CONFIG_SYSVIPC=y
 # block devices
 #
 CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_RAM is not set
 CONFIG_ST506=y
 
 #
@@ -142,6 +144,7 @@ CONFIG_DE4X5=y
 #
 # 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_PSMOUSE=y
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_APM is not set
+# CONFIG_WATCHDOG is not set
 
 #
 # Sound
index b90dc0bea4a32a53781ae1f5a6dc1ebc30c45b00..f8b62b8e3eaf3986d5a94fd92ec682b8776e42fe 100644 (file)
@@ -46,14 +46,16 @@ LINKFLAGS =-qmagic -Ttext 0xfffe0
 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
index d240810a84037f59a70008bb73f21a9cca2bdca7..b118469680a98b839dbf393c104e7e090661f687 100644 (file)
@@ -27,10 +27,10 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 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
 
index 102884b6d6b3d472aca0cd365fcef4282021c183..efc82ea42d5ae5ab65e3838aa6a36da8422454cf 100644 (file)
@@ -19,7 +19,9 @@ CONFIG_PCI_OPTIMIZE=y
 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_MSDOS_FS=y
 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
index 27abc1a265f19d3427d9dd9e621bdbb74a3dd001..e21c627df8d9447aa7d3b27d2e579090308a0e80 100644 (file)
 #
 # 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 @@ CFLAGS              = -D__KERNEL__ -I$(TOPDIR)/include \
                -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 @@ arch/ppc/mm: dummy
 
 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
index bce3956df1213a11bbbd39bfc2c7e49b6e986e5a..c7b4a2f215195d93bda7e3d7042e82ba979ff9ee 100644 (file)
@@ -24,8 +24,11 @@ OBJECTS = head.o main.o
 
 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 --git a/arch/ppc/boot/cortstrip.c b/arch/ppc/boot/cortstrip.c
new file mode 100644 (file)
index 0000000..df0ceab
--- /dev/null
@@ -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);
+}
+
+
index 746fcbe5d9f576e2f740f7d603b10a8a4c2fa8fa..3566f96c0fe4bc3ba7a0c5a5172defcce88d53e7 100644 (file)
@@ -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 @@ HOST_CC = gcc
 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
index 46a8c983abb26b8d3bc1b32170b8635c48fe19d4..cadbaac8b793c12959ce05db011a43ca00452496 100644 (file)
@@ -560,7 +560,8 @@ sys_call_table:
        .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 @@ sys_call_table:
        .globl  floppy_track_buffer
 floppy_track_buffer:
        .space  512*2*38                /* Space for one entire cylinder! */    
-#endif
+#endif
\ No newline at end of file
index e9cbc1bb4a3457ffb2aec846e8bf94996de31581..1e4901cc8e0092b5e70b4bad4b3f94e09606c6cf 100644 (file)
@@ -90,7 +90,7 @@ pcibios_read_config_word (unsigned char bus,
 #endif 
        if ((bus != 0) || (dev < 11) || (dev > 16))
        {
-               *val = 0xFFFFFFFF;
+               *val =(unsigned short) 0xFFFFFFFF;
                return PCIBIOS_DEVICE_NOT_FOUND;
        } else
        {
@@ -119,7 +119,7 @@ pcibios_read_config_byte (unsigned char bus,
 #endif         
        if ((bus != 0) || (dev < 11) || (dev > 16))
        {
-               *val = 0xFFFFFFFF;
+               *val = (unsigned char) 0xFFFFFFFF;
                return PCIBIOS_DEVICE_NOT_FOUND;
        } else
        {
@@ -207,7 +207,7 @@ pcibios_find_device (unsigned short vendor, unsigned short device_id,
                     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) {
index aece3d5f8c353da2b626f6266648fa86824e84a9..83125197d81137b018b54bd7dbd42b1b7976f064 100644 (file)
@@ -165,4 +165,7 @@ n:
 /* Missing instructions */
 #define bdne   bc 0,2,
 
-#include "ppc_machine.h"
+#include <asm/ppc_machine.h>
+
+
+
index f2de621274aded7854ec5420e988a3a49ed03fde..5876539bb75687eb6ed681793690cccf7e31983a 100644 (file)
@@ -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 @@ void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        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_newselect(int p1, int p2, int p3, int p4, int p5, int p6, str
 
 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 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
 {
        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 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
        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 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp, unsigned
     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 @@ print_backtrace(void)
        while (*sp)
        {
                printk("%08X ", sp[2]);
-               sp = *sp;
+               sp = (unsigned long *)*sp;
                if (++cnt == 8)
                {
                        printk("\n");
index e60403b0caddc844f038003ade29b05632455f7b..7a4d08e5ac53d5530286cd549aa796b4baadd98e 100644 (file)
@@ -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 @@ _printk(char const *fmt, ...)
 
 #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 @@ static _cvt(unsigned long val, char *buf, long radix, char *digits)
 /*
  * Console I/O interface
  */
-
 typedef const (*proc)();
 typedef int dev_t;
 
@@ -225,24 +276,24 @@ static int port = 0;
 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 @@ cnputc(char c)
          port = CRT_PORT;
       } else
       {
-         port = NS16550_init(0);
+         port =(int) NS16550_init(0);
       }
       init = TRUE;
    }
@@ -278,7 +329,7 @@ cnputc(char c)
    } else
    if (port)
    {
-      NS16550_putc(port, c);
+      NS16550_putc((struct NS16550 *)port, c);
    }
    if (c == '\n')
    {
@@ -294,7 +345,7 @@ cnputc(char c)
    }
 }
 
-_cnpause()
+void _cnpause(void)
 {
    int c;
    int s = _disable_interrupts();
@@ -323,7 +374,7 @@ _cnpause()
    _enable_interrupts(s);
 }
 
-cnpause()
+void cnpause(void)
 {
    int c;
    int s = _disable_interrupts();
@@ -333,45 +384,7 @@ cnpause()
    _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_init(int chan)
 }
 
 
-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 @@ unsigned short      pccolor_so;             /* color/attributes, standout mode */
 /*
  * 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 @@ cursor()
        }
 }
 
-static void
-initscreen()
+static void initscreen(void )
 {
        struct screen *d = &screen;
 
@@ -533,8 +545,7 @@ fillw(unsigned short val, unsigned short *buf, int num)
  * "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 @@ CRT_putc(int port, u_char c)
        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 @@ const unsigned char keycode[] = {
        _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 @@ loop:
        goto loop;
 }
 
-scankbd() {
+int scankbd(void)
+{
        return (kbd(1) != -1);
 }
 
-kbdreset()
+void kbdreset(void)
 {
        unsigned char c;
 
@@ -1066,14 +1076,14 @@ kbdreset()
                ;
 }
 
-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);
 }
index a5061760082be2a2c6b174943010745037a234c1..661e508a9def103606160dc55dce98125de444f1 100644 (file)
@@ -134,9 +134,6 @@ int size_memory;
 
 #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 @@ void setup_arch(char **cmdline_p,
 
        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;
index f2e0086b8eeafac85e05a1c1bb5cfff1d1535b6f..4d48525b3a24c1e9b3d49bbb515fcc4ad076b6b8 100644 (file)
@@ -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_quotactl(void) { _panic("sys_quotactl"); }
 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 @@ tcp_check(unsigned char *buf, int len, int saddr, int daddr)
        return (_val);
 }
 #endif
-_do_bottom_half()
+
+void _do_bottom_half(void)
 {
        _enable_interrupts(1);
        do_bottom_half();
index a962281b978320b9aa2c28e8a1d3893cf46db960..6364272af57879584be97751bd68bcd51d9ff402 100644 (file)
@@ -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 @@ MachineCheckException(struct pt_regs *regs)
 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)
index 84872d9a8911d37a5cc1ea3dc95dbaaab42e08fb..50a09cecdb1954a7a28a835f8381fa4d6c7a01ea 100644 (file)
@@ -24,6 +24,9 @@ modules:
 dep:
        $(CPP) -M *.c > .depend
 
+fastdep:
+       $(CPP) -M *.c > .depend
+
 #
 # include a dependency file if one exists
 #
index d7b0c166e37808b25312df2989d31c40356b37ce..395888e78f2a3f5418d557ec501295f21c76d332 100644 (file)
@@ -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 @@ DataAccessException(struct pt_regs *regs)
   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 @@ DataAccessException(struct pt_regs *regs)
     {
       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 @@ InstructionAccessException(struct pt_regs *regs)
   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 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long er
 {
   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 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long er
 #else
   vma = find_vma(current, address);
   if (!vma)
+  {
+  }
     goto bad_area;
 #endif
   if (vma->vm_start <= address){
@@ -171,13 +210,19 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long er
   }
   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 @@ good_area:
   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 @@ good_area:
       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 @@ good_area:
    */
 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) ;
index 66da1ece930ef588918b62d095f540cfe21a5c07..ae91d0c85e1c45ac63c56e23e83ab44697503034 100644 (file)
@@ -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 BAT1 =
    };
 BAT BAT2 =
    {
+/* map kernel with bats 0 = yes */
 #if 1
        {
                0x00000000>>17,         /* bepi */
@@ -468,9 +470,9 @@ void MMU_init(void)
 {
        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 @@ void MMU_init(void)
        {
                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 @@ MMU_get_page(void)
        {
                bzero((char *)pg, MMU_PAGE_SIZE);
        }
-       _printk("MMU Allocate Page at %08X\n", pg);
+/*     _printk("MMU Allocate Page at %08X\n", pg);*/
        return(pg);
 }
 
index ea743351181929f6fe80349993afbc51d8fba29e..b0dade40f6836bfe929127c4addf861dab46371f 100644 (file)
@@ -5,7 +5,7 @@ mainmenu_option next_comment
 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'
index 26fc41212be03be5de8624549e9536bcf2a740f3..a6bfeeb7dd4a176c03a7db8b42be69170347b2bb 100644 (file)
@@ -30,6 +30,10 @@ endif
 
 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)
index 8b6a3e7d43895f61ea4c0e83ab05ca95ed70ef65..eacecb747f15535cf0f777420682cf5f6f58bc7d 100644 (file)
@@ -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 @@ extern void wait_for_keypress(void);
 #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 @@ static int rd_blocksizes[NUM_RAMDISKS];
  * 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 @@ static int rd_open(struct inode * inode, struct file * filp)
        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 @@ static struct file_operations fd_fops = {
        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 rd_init(void)
        int             i;
 
        if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
-               printk("RAMDISK: Could not get major %d", MAJOR_NR);
+               printk("RAMDISK: Could not get major %d", MAJOR_NR);
                return -EIO;
        }
 
@@ -181,6 +201,7 @@ int rd_init(void)
        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 @@ crd_load(struct file * fp, struct file *outfp)
        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 */
index b39d619ecc4b6104658a27f9cd6e7a4c344bd8d7..af2da532680ac749e831b8116b5d40aac3e3589d 100644 (file)
@@ -286,7 +286,8 @@ static inline void
 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 @@ static inline void
 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
index bbb5332f33f0561b33f2e32e1db41d8c3c891ced..054af13a47ef2c95feab8b609e0a88607d0e3e80 100644 (file)
@@ -158,7 +158,7 @@ static int ac_probe1(int ioaddr, struct device *dev)
                   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)
index b8653b2fa88b57272d6ba10a9128c21a046b6d57..bd2a86555121e9024310e5d254fd307867b4ef54 100644 (file)
@@ -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.
 
     =========================================================================
 
     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!
     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:
     ------
                           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 @@ static const char *version = "depca.c:v0.41 5/26/95 davies@wanton.lkg.dec.com\n"
 #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 @@ static const char *version = "depca.c:v0.41 5/26/95 davies@wanton.lkg.dec.com\n"
 #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   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    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 int    autoprobed = 0, loading_module = 0;
 
 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 @@ depca_hw_init(struct device *dev, u_long ioaddr)
   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 @@ depca_hw_init(struct device *dev, u_long ioaddr)
          
            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 @@ depca_hw_init(struct device *dev, u_long ioaddr)
 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;
-    }
+  struct depca_private *lp = (struct depca_private *)dev->priv;
+  u_long ioaddr = dev->base_addr;
+  s16 nicsr;
+  int status = 0;
 
-    irq2dev_map[dev->irq] = dev;
-    STOP_DEPCA;
-    nicsr = inb(DEPCA_NICSR);
+  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);
-    }
+  /* Make sure the shadow RAM is enabled */
+  if (adapter != DEPCA) {
+    nicsr |= SHE;
+    outb(nicsr, DEPCA_NICSR);
+  }
 
-    /* Re-initialize the DEPCA... */
-    depca_init_ring(dev);
-    LoadCSRs(dev);
+  /* Re-initialize the DEPCA... */
+  depca_init_ring(dev);
+  LoadCSRs(dev);
 
-    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.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));
-    }
+  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 @@ depca_rx(struct device *dev)
 
        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 @@ set_multicast_list(struct device *dev)
     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 @@ set_multicast_list(struct device *dev)
 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 @@ static void SetMulticastFilter(struct device *dev)
        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 @@ static int load_packet(struct device *dev, struct sk_buff *skb)
     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 @@ static int EISA_signature(char *name, s32 eisa_id)
   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 @@ static int EISA_signature(char *name, s32 eisa_id)
   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 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
     }
 
     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 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
     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 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
     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 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 #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 @@ init_module(void)
 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 */
 
index 252117eb42f3616f0daadc804718fcb3fcc56ada..90e3b932f267fd68b70e24f0d2d7b51f3f5a8a02 100644 (file)
@@ -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
     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
     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.
 
                           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 @@ static const char *version = "ewrk3.c:v0.32 1/16/95 davies@wanton.lkg.dec.com\n"
 #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 = EWRK3_DEBUG;
 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 @@ static int ewrk3_debug = 1;
 #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 @@ static long mem_chkd = EWRK3_IO_SEARCH; /* holds which I/O addrs should be */
 #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 @@ static long mem_chkd = EWRK3_IO_SEARCH; /* holds which I/O addrs should be */
 /*
 ** 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 @@ static unsigned char irq_mask = TNEM|TXDM|RNEM|RXDM;
                                            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 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(short iobase);
-static void SetMulticastFilter(struct device *dev, int num_addr, char *multicast_table);
+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(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);
+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);
 
-#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 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);\
+}
 
 
 \f
 
 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);
+    }
+
+    /*
+    ** Walk the device list to check that at least one device
+    ** initialised OK
+    */
+    for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next);
 
-  if (status) dev->base_addr = base_addr;
+    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 @@ ewrk3_hw_init(struct device *dev, short iobase)
 
   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 @@ ewrk3_hw_init(struct device *dev, short iobase)
       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 @@ ewrk3_hw_init(struct device *dev, short iobase)
       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 @@ ewrk3_hw_init(struct device *dev, short iobase)
        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 @@ ewrk3_hw_init(struct device *dev, short iobase)
              /* 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 @@ ewrk3_hw_init(struct device *dev, short iobase)
              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 @@ ewrk3_hw_init(struct device *dev, short iobase)
                   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 @@ ewrk3_hw_init(struct device *dev, short iobase)
                  printk(" and requires IRQ%d.\n", dev->irq);
                }
              }
+             if (status) release_region(iobase, EWRK3_TOTAL_SIZE);
            } else {
              status = -ENXIO;
            }
@@ -645,9 +612,9 @@ static int
 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 @@ ewrk3_open(struct device *dev)
   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 @@ ewrk3_open(struct device *dev)
 
       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 @@ static void
 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 @@ static int
 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 @@ ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev)
     ** 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 @@ ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev)
        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 @@ ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev)
 
          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 @@ ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev)
            }
            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 @@ ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev)
        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 @@ ewrk3_interrupt(int irq, struct pt_regs * regs)
 {
     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 @@ ewrk3_interrupt(int irq, struct pt_regs * regs)
       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 @@ ewrk3_interrupt(int irq, struct pt_regs * regs)
       ** 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 @@ static int
 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 @@ ewrk3_rx(struct device *dev)
       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 @@ ewrk3_rx(struct device *dev)
        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 @@ ewrk3_rx(struct device *dev)
                *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 @@ ewrk3_rx(struct device *dev)
                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 @@ static int
 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 @@ static int
 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 @@ ewrk3_get_stats(struct device *dev)
 
 /*
 ** 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;
+  u_long iobase = dev->base_addr;
+  u_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);
-  }
+  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 @@ set_multicast_list(struct device *dev)
 ** 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 */
+  while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
 
-       if (lp->shmem_length == IO_ONLY) 
-       {
-               outb(0, EWRK3_IOPR);
-               outw((short)((long)multicast_table), EWRK3_PIR1);
-       } 
-       else
-       {
-               outb(0, EWRK3_MPR);
-       }
+  if (lp->shmem_length == IO_ONLY) {
+    outb(0, EWRK3_IOPR);
+    outw(EEPROM_OFFSET(lp->mctbl), EWRK3_PIR1);
+  } else {
+    outb(0, EWRK3_MPR);
+  }
 
-       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++;
-                       }
-               }
+  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));
+    }
+
+    /* 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);
+         }
        }
-       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;
-               }
+       hashcode = crc & ((1 << 9) - 1);     /* hashcode is 9 LSb of CRC */
 
-               /* 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 */
-
-                               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;
-                               }
-                       }
-               }
+       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) {
+         u_char tmp;
+
+         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;
-
-  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++;
-           }
+  int i = num_ewrk3s, maxSlots;
+  u_long iobase;
+
+  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) {
+  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;
+  }
 
-    /* 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++;
+  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 @@ static int Read_EEPROM(short iobase, unsigned char eaddr)
 /*
 ** 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 int Write_EEPROM(short data, short iobase, unsigned char eaddr)
 */
 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 @@ static void EthwrkSignature(char *name, char *eeprom_image)
       }
     }
     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 @@ static void EthwrkSignature(char *name, char *eeprom_image)
 /*
 ** 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 @@ static int DevicePresent(short iobase)
 ** 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;
@@ -1630,6 +1627,42 @@ static unsigned char aprom_crc(struct device *dev, unsigned char *eeprom_image,
   return status;
 }
 
+/*
+** 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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 {
   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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
       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 */
-
-      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);
-      }
+      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);
+       }
 
-      csr &= ~(TXD|RXD);                       /* Enable the TX and RX */
-      outb(csr, EWRK3_CSR);
+       csr &= ~(CSR_TXD|CSR_RXD);             /* Enable the TX and RX */
+       outb(csr, EWRK3_CSR);
+      }
     } else {
       status = -EPERM;
     }
@@ -1682,8 +1714,8 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
   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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
   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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
     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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
     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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
   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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
     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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
     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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
     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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
     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 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
   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 @@ init_module(void)
 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 */
 
@@ -1923,5 +1931,3 @@ cleanup_module(void)
  * End:
  */
 
-
-
index 941d6bbbccbacc9aebdd5f8222b8f70aa44b9826..b37abf46a3dbdaab41d82af84f57f869df01aed5 100644 (file)
 /*
 ** 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)
 /*
 ** 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 */ 
 #define MASK_INTERRUPTS   1
 #define UNMASK_INTERRUPTS 0
 
+#define EEPROM_OFFSET(a) ((u_short)((u_long)(a)))
+
 /*
 ** Include the IOCTL stuff
 */
index 4d8f422a5ff9b2a4410902286243ed15e1f21114..ca332bbab40ba4431c6c0bad4b165b6a50fda58f 100644 (file)
@@ -569,7 +569,7 @@ lance_open(struct device *dev)
        }
 
        /* 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;
 
index 9d8e821281b2db3c47d8a4c146193bb30cf7f137..e29e095222d311bac5deb4532c74b21a4c37b65d 100644 (file)
@@ -237,7 +237,6 @@ int ether_config(struct device *dev, struct ifmap *map)
        return 0;
 }
 
-#ifdef CONFIG_MODULES
 int register_netdev(struct device *dev)
 {
        struct device *d = dev_base;
@@ -357,8 +356,6 @@ void unregister_netdev(struct device *dev)
 
        restore_flags(flags);
 }
-#endif         /* CONFIG_MODULES */
-
 
 \f
 /*
index 273fe82974c9e00b29c288510fd2c49bc7cd5980..d1cb0b649e2137c8a4e15fc49336ccc678085d15 100644 (file)
@@ -1407,7 +1407,7 @@ static int pi_probe(struct device *dev, int card_type)
        }
 
        /* Grab the region */
-       snarf_region(ioaddr & 0x3f0, PI_TOTAL_SIZE);
+       request_region(ioaddr & 0x3f0, PI_TOTAL_SIZE, "pi2" );
 
 
     }                          /* Only for A port */
index 0d4369a57aed69e8792894c07c25e9d49190a332..ee782028e38876c498b7888fda9a3b398843e115 100644 (file)
@@ -877,7 +877,7 @@ static int pt_probe(struct device *dev)
         }
 
         /* 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;
index 560a8db0e623fd106dc26f7c8324a4730f3265c8..7ac43dba502948e82847cfb3713f092a291ca581 100644 (file)
@@ -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 @@ static const char *version =
 #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 @@ static unsigned int net_debug = NET_DEBUG;
 /* 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 @@ static void set_multicast_list(struct device *dev);
 extern void    hardware_send_packet(short ioaddr, char *buf, int length);
 extern void chipset_init(struct device *dev, int startp);
 
-\f
-/* 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 @@ netcard_probe(struct device *dev)
        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 @@ netcard_probe(struct device *dev)
 }
 #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 @@ static int netcard_probe1(struct device *dev, int ioaddr)
 
        /* 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 @@ static int netcard_probe1(struct device *dev, int ioaddr)
                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 @@ static int netcard_probe1(struct device *dev, int ioaddr)
                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 @@ static int netcard_probe1(struct device *dev, int ioaddr)
        }
 #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 @@ static int netcard_probe1(struct device *dev, int ioaddr)
                /* 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 @@ static int netcard_probe1(struct device *dev, int ioaddr)
        return 0;
 }
 
-\f
-/* 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 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
        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 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
                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 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
 
        return 0;
 }
-\f
-/* 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 @@ net_rx(struct device *dev)
                }
        } 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 @@ net_close(struct device *dev)
        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 @@ net_close(struct device *dev)
 
 }
 
-/* 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 @@ net_get_stats(struct device *dev)
        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);
 }
-\f
+
 #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 @@ int init_module(void)
                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 @@ void
 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 @@ cleanup_module(void)
 }
 
 #endif /* MODULE */
-\f
+
 /*
  * 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
index a92ec6fa81e43ce6b44d675c1abe0b42aaf7d4f7..20190a0d68576cef687f28320985c4ca6ccfd867 100644 (file)
@@ -448,11 +448,11 @@ int aha1740_detect(Scsi_Host_Template * tpnt)
     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;
     }
index e941bcc998fb387849ec446c9759eb29e561b8bb..fea2671c71d2519880184eb74c739a8a67be0aa4 100644 (file)
@@ -58,6 +58,21 @@ const unsigned char scsi_command_size[8] = { 6, 10, 10, 12, 12, 12, 10, 10 };
 
 #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 @@ static int scan_scsis_single (int channel,int dev,int lun,int * max_scsi_dev ,
 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 @@ static int update_timeout(Scsi_Cmnd * SCset, int timeout)
     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 @@ void *scsi_malloc(unsigned int len)
     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 @@ void *scsi_malloc(unsigned int len)
     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 @@ void *scsi_malloc(unsigned int len)
 
 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 @@ int scsi_proc_info(char *buffer, char **start, off_t offset, int length,
 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 @@ static void resize_dma_pool(void)
        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 @@ static void resize_dma_pool(void)
     }
     /* 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 @@ static void resize_dma_pool(void)
     
     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 @@ static void resize_dma_pool(void)
        }
     }
     
+    /* limit DMA memory to 32MB: */
     new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
     
     /*
@@ -2593,22 +2604,20 @@ static void resize_dma_pool(void)
     
     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 @@ static void resize_dma_pool(void)
     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 @@ scsi_dump_status(void)
 extern struct symbol_table scsi_symbol_table;
 
 int init_module(void) {
+    unsigned long size;
+
     /*
      * This makes /proc/scsi visible.
      */
@@ -3127,7 +3138,7 @@ int init_module(void) {
 #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 @@ int init_module(void) {
      */
     
     /* 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;
index 39a22503344d2659fb26c3305a4a71b58e31c4c3..11d57baec834346e0b2f179bb8efcd94441990a3 100644 (file)
@@ -124,14 +124,14 @@ static int ioctl_internal_command(Scsi_Device *dev, char * cmd)
            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 */
index 72b26ce2025a2b823e1aa4666773ced42a2b8ca5..5b25a83307c886aaf90a4f4b1a53fa5a074cacb3 100644 (file)
@@ -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.
  */
 
 /*
index 23e94a91b39c439cfca1df25c9fa7cd4cd7856e9..ecea6c1299fcdef5cc8c30b8be59d6c44069f1f9 100644 (file)
@@ -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
index 2b18627a7a3ba1a38813f25b4a471bcbaecf8629..6b9e063fbbdb8c0966b1d4a0ec0c913e272b2938 100644 (file)
@@ -19,10 +19,11 @@ if [ "$CONFIG_INET" = "y" ]; then
   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
index a8dd06b6667c9eae68ca3905867da04b823ce704..5e9167985d7183446a725c650fdd72f5ce2c6f15 100644 (file)
@@ -16,7 +16,8 @@ O_OBJS    = open.o read_write.o inode.o devices.o file_table.o buffer.o \
                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
@@ -108,6 +109,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_NCP_FS),y)
+SUB_DIRS += ncpfs
+else
+  ifeq ($(CONFIG_NCP_FS),m)
+  MOD_SUB_DIRS += ncpfs
+  endif
+endif
+
 ifeq ($(CONFIG_HPFS_FS),y)
 SUB_DIRS += hpfs
 else
index f37e7a02bb0ef5d2e3973c94daa7ec2693272adc..ef19860c0866bff498c859f5565c907aab9ebf16 100644 (file)
@@ -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 @@ struct inode_operations ext2_file_inode_operations = {
        NULL,                   /* rename */
        NULL,                   /* readlink */
        NULL,                   /* follow_link */
-       NULL,                   /* readpage */
+       ext2_readpage,          /* readpage */
        NULL,                   /* writepage */
        ext2_bmap,              /* bmap */
        ext2_truncate,          /* truncate */
@@ -79,150 +82,101 @@ struct inode_operations ext2_file_inode_operations = {
        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;
+       int *p, nr[PAGE_SIZE/512];
+       int i;
 
-       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;
-       }
+       i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
+       offset >>= inode->i_sb->s_blocksize_bits;
+       p = nr;
+       do {
+               *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);
+}
 
-       /*
-        * 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.
-        */
+/*
+ * 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;
 
-       clusterblocks = 0;
+       if (count <= 0)
+               return 0;
 
-       do {
-               bhrequest = 0;
-               uptodate = 1;
-               while (blocks) {
-                       --blocks;
-#if 1
-                       if(!clusterblocks) clusterblocks = ext2_getcluster(inode, block);
-                       if(clusterblocks) clusterblocks--;
-#endif
+       pos = filp->f_pos;
+       
+       for (;;) {
+               unsigned long offset, nr;
 
-                       *bhb = ext2_getblk (inode, block++, 0, &err);
-                       if (*bhb && !buffer_uptodate(*bhb)) {
-                               uptodate = 0;
-                               bhreq[bhrequest++] = *bhb;
-                       }
+               if (pos >= inode->i_size)
+                       break;
 
-                       if (++bhb == &buflist[NBUF])
-                               bhb = buflist;
+               offset = pos & ~PAGE_MASK;
+               nr = PAGE_SIZE - offset;
+               if (nr > count)
+                       nr = count;
 
-                       /*
-                        * If the block we have on hand is uptodate, go ahead
-                        * and complete processing
-                        */
-                       if (uptodate)
-                               break;
+               /* is it already cached? */
+               page = find_page(inode, pos & PAGE_MASK);
+               if (page)
+                       goto found_page;
 
-                       if (bhb == bhe)
+               /* 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;
+                       }
                }
+               inode->i_op->readpage(inode, pos & PAGE_MASK, (char *) addr);
 
-               /*
-                * Now request them all
-                */
-               if (bhrequest)
-                       ll_rw_block (READ, bhrequest, bhreq);
+               /* 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;
 
-               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 = 0;
-                       chars = sb->s_blocksize;
-                       if (++bhe == &buflist[NBUF])
-                               bhe = buflist;
-               } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
-       } while (left > 0);
+               /* 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);
 
-       /*
-        * Release the read-ahead blocks
-        */
-       while (bhe != bhb) {
-               brelse (*bhe);
-               if (++bhe == &buflist[NBUF])
-                       bhe = buflist;
+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 @@ static int ext2_file_read (struct inode * inode, struct file * filp,
        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 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
                                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);
index 6d08da47ba5a14e981e6d3258ace372b5baeb65b..7606af007767b05f20f240fe12511ce4ba043cd4 100644 (file)
@@ -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);
@@ -87,6 +88,11 @@ asmlinkage int sys_setup(void)
                {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
        register_filesystem(&(struct file_system_type)
                {isofs_read_super, "iso9660", 1, NULL});
index 59edc8c368d6eb803bf71c3ab586182175dc05ed..e78563623929fd71f018d9ec0b5f150d21e012db 100644 (file)
@@ -86,13 +86,13 @@ static inline void put_last_free(struct inode *inode)
        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 @@ void grow_inodes(void)
 
        for ( ; i ; i-- )
                insert_inode_free(inode++);
+       return 0;
 }
 
 unsigned long inode_init(unsigned long start, unsigned long end)
@@ -443,7 +444,7 @@ struct inode * get_empty_inode(void)
 {
        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 @@ repeat:
                        }
                }
        }
-       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 --git a/fs/ncpfs/Makefile b/fs/ncpfs/Makefile
new file mode 100644 (file)
index 0000000..19c00fb
--- /dev/null
@@ -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 --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
new file mode 100644 (file)
index 0000000..eadd026
--- /dev/null
@@ -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 --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
new file mode 100644 (file)
index 0000000..edd9047
--- /dev/null
@@ -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 --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
new file mode 100644 (file)
index 0000000..487efcd
--- /dev/null
@@ -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 --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
new file mode 100644 (file)
index 0000000..600e86f
--- /dev/null
@@ -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 --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
new file mode 100644 (file)
index 0000000..0418860
--- /dev/null
@@ -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 --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
new file mode 100644 (file)
index 0000000..83b5eeb
--- /dev/null
@@ -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 --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
new file mode 100644 (file)
index 0000000..3278cdf
--- /dev/null
@@ -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 --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
new file mode 100644 (file)
index 0000000..6fffbcf
--- /dev/null
@@ -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);
+}
+        
index 0025a3a702464a5c5b33f05c935e4f913f44a36d..858dc19c7f2db2d2c75d040b6e9d4a25c3f9d9bd 100644 (file)
@@ -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 @@ static int get_meminfo(char * buffer)
 
        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);
 }
 
index d79319f5b3786cf3699b07b4f65ef24fb1a1cdf8..3c938c214ce51fdc6b3d6272f3e266f14f24443a 100644 (file)
@@ -263,6 +263,7 @@ asmlinkage int sys_readv(unsigned long fd, const struct iovec * vector, long cou
 
 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 @@ asmlinkage int sys_writev(unsigned long fd, const struct iovec * vector, long co
                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;
 }
index f899e3c4b5f08f120c82d2bf25b57c9a46952e96..d8a2c0576c2407ffeec38b17e5b596f35407b1b2 100644 (file)
@@ -501,7 +501,7 @@ smb_iget(struct inode *dir, char *path, struct smb_dirent *finfo)
                 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 @@ smb_free_inode_info(struct smb_inode_info *i)
                 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 @@ smb_init_root(struct smb_server *server)
         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 @@ smb_lookup(struct inode *dir, const char *__name, int len,
 
         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);
 
index ff0d801ec2e074f931f21def3bf72df249ed0f5b..9a64f012a4c697ac9a50ae40baa619d3e1cd5f64 100644 (file)
 #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)
 {
index 39118f9636e9a13c4ace275c983d4d8fa13d6edc..2bf99fb4c9d40a240b08a0454e0d9f757418cf49 100644 (file)
@@ -62,13 +62,13 @@ smb_read_inode(struct inode *inode)
 
         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 @@ smb_read_inode(struct inode *inode)
 
  good:
 #endif
-        inode_info->state = INODE_VALID;
+        inode_info->state = SMB_INODE_VALID;
 
         SMB_INOP(inode) = inode_info;
 
index 12b09510ce72ad84fdb5f04b4d688f53feba572d..dff51047fca58715cb9a0a4148acc4e92a19fbf5 100644 (file)
 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                                                */
index e7b6d3e2a1431bb6104a8dbcc26b09769970b8db..60f2b1f8a6c368a69282e33ddd08667b2c38d670 100644 (file)
@@ -112,18 +112,17 @@ static void check_hlt(void)
 
 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)
index d4cbf29322748744544ed8185b82157adc1c7304..406a5e24089da48d54edeb43005b9d03b490d81c 100644 (file)
@@ -27,7 +27,7 @@ extern __inline__ unsigned short int  __constant_ntohs(unsigned short int);
 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     */
index b1d5e33073587832847db2092c6c83ae21e97442..add33674ee3e9a793dd2c1bf4ac253218f2a107f 100644 (file)
 #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__
index d06f971f4fc4d4773f951f8a123f041168a8102e..08b9b0be91ea7944294adc8a8e2eecbf488428de 100644 (file)
@@ -78,7 +78,7 @@ extern inline void end_bh_atomic(void)
  * 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,
index bbeb596e10778ad6148a6da8e8c47cf9a7d4bf1d..335e3b65f7631aca59e6d0ef5a0cac036e0b436c 100644 (file)
 #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 *);
index fb01b3127a5c0db3f5c8c7610f6662ac0695496a..ba3fe20dd303aac676b234eece3bae01cee9a1c9 100644 (file)
@@ -109,8 +109,8 @@ struct vm_operations_struct {
 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 @@ struct mem_list {
 };
 
 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 --git a/include/linux/ncp.h b/include/linux/ncp.h
new file mode 100644 (file)
index 0000000..895c5ae
--- /dev/null
@@ -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 --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
new file mode 100644 (file)
index 0000000..38ffab2
--- /dev/null
@@ -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 --git a/include/linux/ncp_fs_i.h b/include/linux/ncp_fs_i.h
new file mode 100644 (file)
index 0000000..a72fb07
--- /dev/null
@@ -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 --git a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h
new file mode 100644 (file)
index 0000000..fc5e955
--- /dev/null
@@ -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 --git a/include/linux/ncp_mount.h b/include/linux/ncp_mount.h
new file mode 100644 (file)
index 0000000..83007be
--- /dev/null
@@ -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
index 1fcaae1a21058097dd7d54cd53df74f7a94cf2a6..e3561b757ab88f58d71df3bc509554ef6ea12f9b 100644 (file)
@@ -13,7 +13,9 @@ static inline unsigned long page_address(struct page * page)
 }
 
 #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 @@ static inline struct page * find_page(struct inode * inode, unsigned long offset
                        continue;
                if (page->offset != offset)
                        continue;
+               page->age = PAGE_AGE_VALUE | (page->age >> 1);
                break;
        }
        return page;
@@ -42,6 +45,7 @@ static inline void remove_page_from_hash_queue(struct page * page)
 {
        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 @@ static inline void add_page_to_hash_queue(struct inode * inode, struct page * pa
 {
        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;
index 382ae83d3bd320ab9be9249ba529c3ba2cd30d39..1eda0af96b760e3c41c76b2acd7c6f87744bf56b 100644 (file)
 #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>
index 98e4f151cde79211615271cd19b4b22bfd837a87..436f99ac2977c94f68d051f8476d7ca8e46b5195 100644 (file)
 #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
 };
 
 /*
index 650559bc08fff86a156123806624fbb9b1a025ba..7fc18e6e8ed1d0cd02ce44b449b1063ef39b159b 100644 (file)
@@ -390,13 +390,10 @@ void calibrate_delay(void)
 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 @@ static void parse_options(char *line)
                        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);
index d6e17203b8852a2f96fa878ef81d3493f61389ff..2b3668a5fcc52f4f4a015a78e68a0ad32eac3ea1 100644 (file)
@@ -812,5 +812,10 @@ asmlinkage int sys_get_kernel_syms(void)
        return -ENOSYS;
 }
 
+int register_symtab(struct symbol_table *intab)
+{
+       return 0;
+}
+
 #endif /* CONFIG_MODULES */
 
index 5a7999d73d163839c555cbcf05d851781d63aedc..48184bfcf677a98c058be188e98a8cc355e3bc13 100644 (file)
@@ -92,15 +92,6 @@ void request_region(unsigned int from, unsigned int num, const char *name)
        }
 }
 
-/*
- * 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
  */
index 49ec238fdd96b5fa3fc07d12e9d3145091987bbf..1a7dd3c5f39ee567d673cf63184c1a63cac64734 100644 (file)
@@ -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 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
         * 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;
index d229c523b6c6594c93f5e81f4e60731968e7989a..d6e1fc5d3e0287d4b184167cc8515d65f5310510 100644 (file)
@@ -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 @@ int shrink_mmap(int priority, unsigned long limit)
        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++;
index 3f905cee439449cc3cfa673e044bd77d49b6e2f4..01c8eddb40411a60a1361d595eef14504074321a 100644 (file)
@@ -57,7 +57,7 @@ unsigned long high_memory = 0;
 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 @@ int verify_area(int type, const void * addr, unsigned long size)
         * 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);
index 95ba4e30f81799f01a64580d90b13b37616bfad2..2487e13d6565c06a3254cb3cdd46e0d74543a27d 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -44,7 +44,7 @@ int min_free_pages = 20;
 
 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 @@ unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem)
                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;
        }